Vagrant+Dockerなんて使わなければよかった・・・

  • 222
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

と思わないために環境構築時や開発時のはまり所やひっかかった所を共有します。

Vagrant+Dockerで以下の環境を構築して開発を行っています。
* 開発環境
ホスト機(windows)<->Vagrant(centos)<->Docker(centos)
* ステージング・検証環境
centos<->Docker(centos)

環境構築時

Dockerfileの作成

Dockerfileに下記のような記述をして、mysql起動後に初期データベースを作ろうとしても失敗します。

RUN service mysql start
RUN mysql -uhoge -phogehoge -e"CREATE DATABASE hoge CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'"

DockerはRUN毎にプロセスを持っているようなので、何かを起動した後に実行したい処理がある時は&&で繋げる必要があります。

RUN service mysql start &&
mysql -uhoge -phogehoge -e"CREATE DATABASE hoge CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'"

cdなどでカレントディレクトリを移動する場合も同様です。
WORKDIRというコマンドがありますので、これを使えば&&で繋げる必要もなくなります。

またDockerfileでchkconfig mysqld onなどで自動起動設定していても、コンテナの起動時にはmysqlは起動されていません。initスクリプトの実行はdockerではスキップされる為です。

Docker起動時に起動したいサービスがある場合、ENTRYPOINTやCMDを使うか、起動スクリプトをdocker run時に指定してやる必要があります。

Vagrant+Dockerの連携

vagrant upするだけでWebシステムをブラウザで確認でき、
ソースもホスト機でデバック可能、mysqlなどのデータベースも
ツールで確認可能になる状態にする事ができます。

ポイントはポートフォワード、ファイル共有、vagrant up時の自動起動設定です。

ポートフォワード

Docker上のwebサーバーにアクセスするにはホスト機->vagrant->dockerを
ポートフォワードで繋げてやれば、アクセス可能です。

Vagrantfileでホスト機とvagrantのポートフォワード

Vagrantfile
config.vm.network "forwarded_port", guest: 8081, host: 8081

docker runコマンドでvagrantとdockerのポートフォワード指定

docker run -d -i --name hoge -p 8081:80 -t hoge /bin/bash

ファイル共有

dockerに展開しているソースでそのままデバックなどしたい場合は、
ホスト機<->vagrant<->dockerをファイル共有などで繋げてやる必要があります。

Vagrantfileでホスト機とvagrantのファイル共有

Vagrantfile
config.vm.synced_folder "src", "/vagrant", :mount_options => ["dmode=777", "fmode=777"]

docker runコマンドでvagrantとdockerのマウント指定

docker run -v /vagrant:/var/www -i --name hoge -p 8081:80 -t hoge /bin/bash

vagrant起動時にdocker起動

あらかじめDockerコンテナを作成しておき、vagrant起動時、
Dockerとコンテナが起動するように構成します。

Vagrantfile
  config.vm.provision "shell", inline: <<-SHELL
    sudo service docker start
    sudo docker start hoge
  SHELL

後、sshのポートもポートフォワードしてやれば、
Dockerコンテナにsshで入る事やdbにsshトンネルで繋げる事も可能になります。

ここまで設定してやれば、vagrant upするだけで即、開発デバックを行える状態になります。

Docker永続化

DockerでくぐっているとDocker永続化とか、mysql永続化とか、永続化という言葉が出てきます。
私は言葉をそのまま捉えて、最初はDockerはオンメモリで動くのだと思っていましたが、そうではありません。
Dockerコンテナ自体は永続化で保存されています。

以下のような場合、Dockerコンテナはimageなどに保存しておかないと使えなくなります。
* Dockerのバージョンアップを行い、以前バージョンとコンテナファイルの認識などに差分が発生した。
* ENTRYPOINTなどに指定した起動時の処理が失敗するような場合、コンテナ自体の起動ができなくなります。

他にもコンテナを誤ってrmしてしまったなどのケースがあると思います。
このような場合は永続化すべきデータがあっても戻す事ができません。
よってDockerコンテナは破棄される前提で考えていた方がよく、
永続化が必要なデータファイルなどは下記のような永続化対策を行っていた方がいいです。
Docker でデータのポータビリティをあげ永続化しよう

Dockerの永続化はこのような抽象的な意味あいで使われるようです。

Dockerコンテナのディスクサイズ割り当て

Dockerコンテナは初期設定では(仮想)ディスクサイズの割り当てが10GBに設定されています。
永続化対策をして、サイズが大きくなりそうなディレクトをマウントなどすれば、10GB以上になる事はほとんどないかもしれませんが、10GB以上に設定変更する場合は、一旦、Dockerイメージをすべて削除して設定し直す必要があります。
本番運用が始まった後にDockerイメージをすべて削除するのは難しい場合もあると思いますので、運用前には永続化も含めて、ディスクサイズ割り当ても考慮しておいた方がいいです。

DockerのCPUアーキテクチャの依存

DockerはCPUアーキテクチャに依存します。x84ベースのDockerはx64では動きません。最近ではほとんどx64ベースになるので問題にはならないと思いますが、折角Dockerイメージを苦労して作ったのに本番環境では使えなかった、という事がないようにしましょう。

開発時

VagrantのDockerが消えた・・・

ある日、vagrant upをすると起動はしたのですが、
インストールしているはずのDockerが消えさってました。
原因はよく分かりません。周りにはvagrant destroyを
したのではないかと言われましたが、その時は
そのコマンド自体知らなかったので、ありえないです。
この現象を2回経験しています。
1回目の時はvagrantをbox化していなかったので、
構築し直し、2回目の時はboxから戻しました。
vagrantはタイミングを見てbox化しておいた方が、後々良さそうです。

Vagrantの容量が足らなくなった

vagrantにいろいろなdockerイメージを入れたり、
buildしたりしていたのですが、公式のvagrant boxのcentosの
ディスクサイズは8Gぐらいしかなく、docker buildができなくなりました。

vagrantのbox容量を拡張する方法

上記を参考にさせてもらいboxを拡張しましたが、
結構時間がかかります。開発時は時間が取れない時もあるので、
できれば容量は構築時に大目に拡張しておくのがいいと思います。

cssの変更が反映されない

cssを変更しても、ブラウザに反映されないという現象に当たりました。
ブラウザのキャッシュなどはクリアしても反映されません。

静的ファイルがキャッシュされる(ブラウザキャッシュじゃない場合)

VirtualBoxの共有フォルダに設定したディレクトリは、外部ストレージ的な扱いになり、その際、apacheがファイルの更新を検知できないようです。

httpd.confにキャッシュしない設定を追記し、再起動する事で、この現象は回避できます。

<Directory [対象のディレクトリ]>
EnableMMAP Off
EnableSendfile Off
</Directory>

phpのソースの大文字・小文字の判別が環境で違う

開発環境ではHogeclassをhogeclassとして記述しても、エラーになりませんでしたが、ステージング環境ではエラーになってしまいます。同じdocker imageを使っているので、環境的な差異はないはずです。

class_exists でのオートロード
上記が原因ぽいですが、df -Tでファイルシステムを確認する限り、
開発もステージングもextとなっていました。
これは原因はまだよく分かっていないです。

Dockerコンテナの起動ができなくなった

httpd.confの設定をいじり、コンテナをexitで抜け、終了しました。
しばらくしてコンテナをstartさせようとするとapacheの起動エラーで
コンテナの起動自体ができない自体に陥りました。
ENTRYPOINTでDocker起動時に起動させるサービスが
起動エラーとなった場合、コンテナ自体の起動ができなくなるようです。

Dockerコンテナをexitで抜けてしまう

docker attachしてDocker内に入り、その後exitするとコンテナを抜けると同時に起動しているDockerコンテナを終了してしまいます。コンテナを終了せずに抜ける必要がある場合はCtrl+p,qをする必要があります。

このようなDockerの仕様があるのですが、sshの癖で無意識にexitで抜けてしまいます。開発やステージングではいいですが、本番でこれをやるとサービスが一時的でもダウンしてしまうので気を付ける必要があります。

CoreOS で起動中のコンテナの中に入る
docker execで入ればプロセス注入なのでexitしてもDockerコンテナが終了する事はないようです。Dockerコンテナに入るのはdocker execで入る習慣化しておいた方がよさそうです。