Vagrant上で動かしてた開発環境をDocker上で動かすようにしてみた(メモ)

docker
前職の開発は今はもうほとんどやらないんですけど、後任が決まったという連絡もないので一応自宅のローカル環境でも動かせるようにはなっています。この環境はちょうど4年ほど前に当時の上司の設定で構築されたものを2年ほど前に僕がWindows向けに書き換えたものなのですが、将来誰かに開発環境を渡すときのことを考えるとDockerに載せ替えておきたい。Vagrantも便利なんですけど設定しなければいけないことが多く細かくてなかなか大変なんですよ。MacとWindowsで設定変わるし。



というわけでVagrant上で動かしている開発環境をDockerに載せ替える方法……を書こうかなとも思ったんですけど、それほどやることはないのでメモ書き程度で。





大雑把な流れ

  1. 移行したい環境の主なプログラムのバージョンを調べます。今回の場合PHPとMySQLのバージョンさえあってればあとは何とかなります。フレームワークに関してはソースを流用する関係上別にインストールするわけではないので問題ありません。
  2. 用意したいインスタンスごとにDockerfile用意します。今回は「公開用サイト」「管理用サーバ」「バッチサーバ」と3つのインスタンス用にDockerfileを用意しました。中身は「DOCUMENT_ROOT」が変わっているだけで他は同じです。Dockerfileで何をインストールしたら良いのかは環境によって変わるので、動かしながら調整していきます。
  3. docker-compose.ymlを用意します。今回は3つのインスタンスの他に「proxy」「DB」「redis」の3つのコンテナを設定しています。
  4. $ docker-compose up --build -d で正常に起動するようになれば完了です。



ハマりポイント

ドキュメントルートにアクセスすると「403 Forbidden」

ドキュメントルートの設定は、環境変数「APACHE_DOCUMENT_ROOT」にドキュメントルートを設定して、confファイルの該当部分を ${APACHE_DOCUMENT_ROOT} に書き換えるというのが常套手段です。

ENV APACHE_DOCUMENT_ROOT /path_to_document_root/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf

でもこれだけだと足りない部分があるらしくPermission deninedになってしまいました。最終的に3行目を追加したら上手く動きました。

ENV APACHE_DOCUMENT_ROOT /path_to_document_root/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

最初よく解らなくてしばらく悩み、パーミッションのせいかなとかファイル所有者の問題かなとか色々試しましたが、今まで構築してきた環境では問題にならなかったので違うかなと。違いました。


シンボリックリンクが壊れる

インスタンス間で共通して使用しているライブラリをシンボリックリンクで設定していたんですが、Dockerではホスト側のシンボリックリンクが正常に読めないらしくライブラリが読み込めませんでした。困った。

色んな対策を考えましたが、最終的に共通ライブラリをdocker-compose.ymlのvolumesに追加するように設定して解決しました。それならコピーする必要がないし簡単です。


環境変数HTTPSがonにならない

「proxy」サーバを立てているのは次の2つの理由からです。

  • ドメインでアクセス出来るようにする
  • https://でアクセス出来るようにする

適切に設定してやると例えば以下のようなドメインでローカル開発環境にアクセス出来るようになります。

https://local.nplll.com

このとき何が起きているかというと、ブラウザからproxyサーバへはhttps(443ポート)で、proxyサーバから「公開用サイト」サーバにはhttp(80ポート)で接続しています。そのせいか「公開用サイト」のフレームワークはhttp://でアクセスしていると判断してしまうんですね。で、リダイレクトしてループするって言う。ダメじゃん。

環境変数HTTPSは上書きできるので、次の2つのファイルに「SetEnv HTTPS on」を追加すれば解決出来ます。

  • /etc/apache2/sites-available/000-default.conf
  • /etc/apache2/sites-available/default-ssl.conf

本番環境でそんなことしたらダメですが、どうせオレオレ証明書を使ってSSL通信してるローカル環境なので良しとします。動いたからヨシ!



docker-compose.yml(イメージ)

色々あるので細かい設定は変えていますが、イメージとしてはだいたいこんな感じです。

version: '3'

services:
 proxy:
   image: jwilder/nginx-proxy
   container_name: proxy
   volumes:
     - /var/run/docker.sock:/tmp/docker.sock:ro
     - ./app/ssl:/etc/nginx/certs
   restart: always
   ports:
     - 80:80
     - 443:443
    
 local_www:
   image: local/www
   container_name: www
   build: ./www
   restart: always
   volumes:
     - ../project/local:/home/webuser/local/
     - ../project/model:/home/webuser/local/fuel/app/classes/model/
   environment:
     - VIRTUAL_HOST=local.hoge.com
     - FUEL_ENV=local
     - CERT_NAME=shared

 local_admin:
   image: local/local-admin
   container_name: local-admin
   build: ./local-admin
   restart: always
   volumes:
     - ../project/local-admin:/home/webuser/local-admin/
     - ../project/model:/home/webuser/local-admin/fuel/app/classes/model/
   environment:
     - VIRTUAL_HOST=adminlocal.hoge.com
     - FUEL_ENV=local
     - CERT_NAME=shared

 local_batch:
   image: local/batch
   container_name: local-batch
   build: ./local-batch
   restart: always
   volumes:
     - ../project/local-batch:/home/webuser/local-batch/
     - ../project/model:/home/webuser/local-batch/fuel/app/classes/model/
   environment:
     - FUEL_ENV=local
     - CERT_NAME=shared

 db:
   image: mysql:5.6.51
   container_name: local-db
   volumes:
     - ./db/data:/var/lib/mysql
   restart: always
   environment:
     - MYSQL_ROOT_PASSWORD=root
     - MYSQL_DATABASE=local
     - MYSQL_USER=user
     - MYSQL_PASSWORD=pass
   ports:
     - 13306:3306

 redis:
   image: redis:latest
   container_name: local-redis
   ports:
     - 6379:6379
   volumes:
     - ./redis/data:/data
   restart: always



まとめ

そんなの大変すぎて出来ないだろうと昔は諦めてたんですけど、人間慣れればいろいろ出来るようになるもので出来ちゃいました。掛かった時間は5時間ぐらいかな。休日の暇つぶしにはちょうどよかったです。

考えてみれば今参画しているプロジェクトの開発環境もなんかスゲー雑に振られてなんのアドバイスもなかったんですけど、ソースコード読んで環境予想してDockerで開発環境作れちゃいましたし、やればできるもんです。というか僕がすごいんじゃなくてDockerがすごいです。間違いなく。ほとんど設定するところなんかないんですからね。ダメだったときに対処すれば良いだけで。


素晴らしい時代です。最高。