endokのブログ

IT・プログラミングネタ

Dockerの公式MySQLイメージを使ってホストからアクセスするまで

Dockerわかってる人には単純な話かと思いますが、一部ハマったのでメモ。

やりたいこと

  • 公式MySQLイメージを使ってコンテナ起動する
  • ホスト側からmysqlコマンドでコンテナのmysqldに接続する。

mysql Repository | Docker Hub Registry - Repositories of Docker Images
こちらのイメージを利用する。

dockerはインストール済とする。

公式MySQLイメージをpullする

今回はバージョン5.5を利用。

$ docker pull mysql:5.5
$ docker ps
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
mysql                      5.5                 c8defdc7b8fa        6 days ago          214.7 MB

コンテナを起動する

MYSQL_ROOT_PASSWORDという環境変数でrootパスワードを設定する。
その他の環境変数は公式参照。

外部から接続するには、-p [ホスト側ポート]:[コンテナ側ポート]でポートを公開する必要があるとのこと。
今回はホストの13306でコンテナの3306ポートに接続する。

ここで問題発生。

最初、

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=mysql -d mysql:5.5 -p 13306:3306

としていたが、これだとすぐにコンテナがエラーで終了してしまった。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

ログを確認する。

$ docker logs mysql
...
150314 15:00:05 [ERROR] mysqld: unknown option '-p'
150314 15:00:05 [ERROR] Aborting

150314 15:00:05  InnoDB: Starting shutdown...
150314 15:00:06  InnoDB: Shutdown completed; log sequence number 1595675
150314 15:00:06 [Note] mysqld: Shutdown complete

mysqldに-pオプションが渡ってしまっている模様。
考えてみると当たり前だが、最後に-pオプションを指定していたのがまずかった。
-pオプションの場所を変更すると起動成功。

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=mysql -d -p 13306:3306 mysql:5.5
$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                     NAMES
5289e9512b4e        mysql:5.5           "/entrypoint.sh mysq   47 seconds ago      Up 46 seconds       0.0.0.0:13306->3306/tcp   mysql

ホストから接続する

ホストからlocalhostの13306ポートに接続すればよい。
パスワードは上の例では"mysql"。

$ mysql -u root -p -h 127.0.0.1 -P 13306
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.42 MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

無事接続成功。

Bootstrapでpull-leftしたアイコンを含む要素を表示/非表示するとその要素のテキスト、背景色が消える(iPhone Safariで発生)

原因よくわからないものの解決したのでとりあえずメモ。
かなり状況は限定的。

環境

Bootstrap 3.3.2
jQuery 1.11.2
iPhone6(iOS8.1.3)

現象

下記の"Button"を押すと左の"LEFT"がtoggleするようになっている。

"Button"を2回押して非表示→表示とすると、LEFTというテキスト、背景色が消える。

サンプルコードは下記。

<html lang="ja">
<head>
  <meta name="viewport" content="width=device-width">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
  <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>

  <style>
    body {
      font-size: 16px;
    }
    .left {
      background-color: skyblue;
    }
    .right {
      background-color: yellow;
    }
  </style>
</head>  
<body>
  <div class="container">
    <div class="clearfix">
      <div class="pull-left left">
        <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
        LEFT
      </div>
      <div class="pull-right right">
        RIGHT  
      </div>
    </div> 
    <button id="btn">Button</button>
  </div>

  <script>
    $(function(){
      $("#btn").on("click", function(){
        $(".left").toggle();
      });
    });
  </script>
</body> 
</html>

発生条件

下記条件を満たすときに発生する(本当はもっと細かい条件があるかもしれないが調べきれていない)

  • pull-left(float: left)した要素をclearfixクラスでクリアしている。
  • pull-leftしている要素内にglyphiconがある。
  • pull-leftしている要素をjQuery.toggle()する。
  • iPhonesafariで表示したときに発生する。(PCのChromeでは発生しない)

解決方法

pull-leftする要素とtoggleする要素を分離する。

    <div class="clearfix">
      <div class="pull-left">
        <div class="left">
          <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
          LEFT
        </div>
      </div>
      <div class="pull-right right">
        RIGHT  
      </div>
    </div>

rspec3でJST日付を検証する

modelのdatetime型項目を検証する。

例えば下記のmodelを考える。

class CreateTasks < ActiveRecord::Migration                                                           
  def change
    create_table :tasks do |t|
      t.string :title
      t.datetime :deadline

      t.timestamps null: false
    end
  end                                                                                                 
end

'2015/01/01'でdeadlineを初期化後に

p task.deadline

すると

Thu, 01 Jan 2015 00:00:00 JST +09:00

と表示される。

この状態で

expect(task.deadline).to eq DateTime.new(2015,1,1)

とすると

Failure/Error: expect(task.deadline).to eq DateTime.new(2015,1,1)
       expected: Thu, 01 Jan 2015 00:00:00.000000000 +0000
       got: 2015-01-01 00:00:00.000000000 +0900

と言われてしまう。
DateTimeではタイムゾーンが反映されないのが原因?の模様。
Timeを使うとタイムゾーンが反映され、比較OKとなる。

expect(task.deadline).to eq Time.new(2015,1,1)


DateTimeとTimeの扱いは下記ページが詳しい。
RubyとRailsにおけるTime, Date, DateTime, TimeWithZoneの違い - Qiita

Railsでassets/imagesの画像を差し替えるとundefined method `bytesize'が発生する

現象

railsで、app/assets/images配下に画像を配置していた。
その画像のサイズを変更しながら見栄えを確認していると、下記のような状態になった。

  • 同じファイル名で最初に配置したファイルよりもサイズの小さい画像を配置すると、 ERROR NoMethodError: undefined method `bytesize' for nil:NilClass というエラーが発生する。ブラウザ上では途中まで読み込みが行われるが、読み込み終わると画像読み込みエラーになる。
  • 同じファイル名で最初に配置したファイルよりもサイズの大きい画像を配置すると、画像の途中で読み込みが終わってしまう。
  • ファイル名を別名にしてみると、正常に表示される。

解決方法

どこかのキャッシュなんだろうと思いつつ調べていくと、サーバー側のassets情報のキャッシュが原因だった模様。

railsアプリケーションのルートフォルダから

$ rm -rf tmp/cache/assets

を実行したところ解消した。

Ansibleでgenerator-angular-fullstackのセットアップ

Ansibleでgenerator-angular-fullstackを使える状態にするtask設定例。
CentOS6.5用。

- name: node.jsのインストール
  yum: name="{{ item }}" enablerepo=epel
  with_items:
    - nodejs
    - npm 

- name: npmの更新
  npm: name=npm global=yes state=latest

- name: node.jsパッケージのインストール
  npm: name="{{ item }}" global=yes
  with_items:
    - yo
    - bower
    - grunt-cli
    - generator-angular-fullstack

compassをインストールする場合は、下記を追加。
(rubyは設定済とする)

- name: compassのインストール
  gem:
    name=compass
    user_install=no
    executable=/usr/local/bin/gem

ハマった部分として、yumでインストールしたnpmを再度npmで最新に更新しないと
yoのバージョンが古くなってしまいgenerator-angular-fullstackのインストールに失敗するということ。

generator-angular-fullstackでnpm installの際にgifsicleのインストールエラー

generator-angular-fullstackでgenerate後、npm install時にgifsicle@0.1.7のインストールエラーが発生。

> gifsicle@0.1.7 postinstall /home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle
> node index.js

⚠ pre-build test failed, compiling from source...
|
stream.js:94
      throw er; // Unhandled stream error in pipe.
            ^
Error: invalid tar file
    at Extract.Parse._startEntry (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/lib/parse.js:145:13)
    at Extract.Parse._process (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/lib/parse.js:127:12)
    at BlockStream.<anonymous> (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/lib/parse.js:47:8)
    at BlockStream.emit (events.js:95:17)
    at BlockStream._emitChunk (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/node_modules/block-stream/block-stream.js:145:10)
    at BlockStream.resume (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/node_modules/block-stream/block-stream.js:58:15)
    at Extract.Reader.resume (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/node_modules/fstream/lib/reader.js:255:34)
    at DirWriter.<anonymous> (/home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/lib/extract.js:57:8)
    at DirWriter.emit (events.js:92:17)
    at /home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/node_modules/bin-build/node_modules/download/node_modules/decompress/node_modules/tar/node_modules/fstream/lib/dir-writer.js:39:8

実際は最初のnpm install時には気づいておらず、grunt serve:dist時にimageminタスクでエラーになって気づいた。

ググるGitHubのissuesが見つかる。
npm install gifsicle@0.1.7 fails · Issue #36 · imagemin/gifsicle-bin · GitHub

package.jsonのgrunt-contrib-imageminのバージョンを0.8.1に上げて、再度インストール。

"grunt-contrib-imagemin": "~0.8.1"
$ rm -rf node_modules/grunt-contrib-imagemin
$ npm install
(省略)
> pngquant-bin@0.3.5 postinstall /home/endok/mean/node_modules/grunt-contrib-imagemin/node_modules/imagemin/node_modules/imagemin-pngquant/node_modules/pngquant-bin
> node index.js

⚠ pre-build test failed, compiling from source...
✖ pngquant failed to build, make sure that libpng-dev is installed

{ [Error: Command failed: make: *** `lib/libimagequant.a' に必要なターゲット `config.mk' を make するルールがありません.  中止.
] killed: false, code: 2, signal: null }

gifsicleはインストール成功するもpngquant-binのエラー。
libpng-devをインストールする。

$ sudo yum install libpng-devel

その後、再びnpm installで成功。

$ rm -rf node_modules/grunt-contrib-imagemin
$ npm install
(省略)
✔ pngquant built successfully!

grunt-contrib-coffeeでは最初のドットまでが同じcoffeeファイルは連結される

軽い気持ちでMEANスタックに触ってみたところ、npm,Gruntなどなど慣れないものばかりでハマりまくっています。

今回はcoffeeファイルをjsファイルに変換する際のGruntの挙動についてです。

現象

generator-angular-fullstackで生成したアプリケーションにて、
下記のようなcoffeeファイルがある場合。

$ ls client/app/main
main.coffee  main.controller.coffee

grunt serveで起動したHTMLを見てみると、

<script src="app/main/main.js"></script>

という記述のみで、main.controller.jsの読み込みはない。

main.jsの中身を見るとmain.coffeeとmain.controller.coffeeを連結した中身になっていた。

grunt-contrib-coffeeの挙動として連結されているのか?それとも別のプラグインの影響なのか?検証してみる。

検証

適当なフォルダにgrunt-contrib-coffeeを試すためのファイルを配置する。

{
  "name": "coffee",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-coffee": "^0.12.0"
  }
}
  • Gruntfile.js
module.exports = function(grunt) {
  grunt.initConfig({
    coffee: {
      compile: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['**/*.coffee'],
          dest: 'dest/',
          ext: '.js',
        }]  
      }   
    }   
  }); 
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.registerTask('default', 'coffee');
};
  • src/sample.coffee
variable = 100
  • src/sample.test.coffee
variable = 50

設置できたら、npmパッケージをインストールしてcoffeeタスクを実行。

$ npm install
$ grunt coffee

すると、
dest/sample.js
が出力される。

中身は

(function() {
  var variable;

  variable = 100;

}).call(this);

(function() {
  var variable;

  variable = 50;

}).call(this);

となっており、sample.coffeeとsample.test.coffeeが連結されていることが確認できる。

同様に、

  • src/sample.coffee
  • src/sample.test.coffee
  • src/sample2.coffee
  • src/sample2.test.coffee

の4ファイルを配置した場合、

  • dest/sample.js
  • dest/sample2.js

の2ファイルが生成される。

まとめ

結論としては、grunt-contrib-coffeeが複数ファイルコンパイルを行うときにこういった連結を行うということで良さそうです。
知っている人には当然ぽい挙動かと思いますが、何で検索したらいいかわからずでした。
近い話題としては下記が見つかりました。
coffeescript - grunt-contrib-coffee one-to-one compile - Stack Overflow
Gruntの理解にはまだまだかかりそうです。