今までvagrantでローカル環境を作成していたシステムで、dockerローカル環境を入れてみました!という備忘録です。
docker-composeを使います。
ローカル環境で用意するもの
php5.6
laravel5.1
mysql5.7
apache
phpmyadmin
workspace
バージョン古くね?という声は胸の中にしまっておいてください。
構築に必要な諸々のファイル
├── apache
│ ├── Dockerfile
│ └── php.ini
├── docker-compose.yml
├── .env
└── workspace
├── Dockerfile
└── php.ini
docker-compose.yml
version: '3'
services:
# ローカルでartisanコマンド打ったりする時用のworkspace
workspace:
build: workspace
container_name: project_workspace
volumes:
- ${BASE_DIR}
command: bash
environment:
- STAGE=docker
depends_on:
- mysql
- cache
# webサーバー。phpもここでインストールして動かす
apache:
build: apache
container_name: project_apache
volumes:
- ${BASE_DIR}
ports:
- 8080:80
environment:
- STAGE=docker
# ローカルで使うDB
mysql:
image: mysql:5.7
container_name: project_mysql
ports:
- '3307:3306'
environment:
- MYSQL_DATABASE=db
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=root
volumes:
- project_mysql:/var/lib/mysql
# GUIでDB見る時用のPhpMyadmin(MySQLworkbenchとか使うなら必要ない)
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: project_phpmyadmin
environment:
- PMA_HOST=project_mysql
- PMA_USER=dbuser
- PMA_PASSWORD=password
ports:
- "3333:80"
# キャッシュサーバー
cache:
image: memcached
container_name: project_cache
volumes:
project_mysql:
driver: "local"
.env
COMPOSE_PROJECT_NAME=project
BASE_DIR=../:/var/www/html
apache/Dockerfile
FROM php:5-apache
RUN apt-get update && apt-get install -y unzip libmemcached-dev zlib1g-dev
RUN docker-php-ext-install mysqli pdo_mysql
RUN pecl install memcached-2.2.0 && docker-php-ext-enable memcached
RUN cp /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled/
ENV APACHE_DOCUMENT_ROOT /var/www/html/public
RUN sed -ri -e 's!/var/www/html!/var/www/html/public!g' /etc/apache2/sites-enabled/*.conf
RUN sed -ri -e 's!/var/www/!/var/www/html/public!g' /etc/apache2/apache2.conf /etc/apache2/conf-enabled/*.conf
COPY php.ini /usr/local/etc/php/
RUN echo "date.timezone = Asia/Tokyo" >> /usr/local/etc/php/php.ini
workspace/Dockerfile
FROM php:5
RUN apt-get update && apt-get install -y unzip libmemcached-dev zlib1g-dev
RUN docker-php-ext-install mysqli pdo_mysql
RUN pecl install memcached-2.2.0 && docker-php-ext-enable memcached
RUN curl -sS https://getcomposer.org/installer | php; mv composer.phar /usr/local/bin/composer ; mkdir /var/dev
RUN mkdir /var/www && mkdir /var/www/html
COPY php.ini /usr/local/etc/php/
RUN echo "date.timezone = Asia/Tokyo" >> /usr/local/etc/php/php.ini
WORKDIR /var/www/html
CMD ["bash"]
構築手順
docker、docker-composeを使えるようにする
参考:https://qiita.com/zembutsu/items/dd2209a663cae37dfa81
composeディレクトリの中でコンテナを立ち上げる
cd (docker-compose.ymlが入ってるディレクトリ名)
docker-compose up -d apache mysql phpmyadmin cache
ローカル環境でartisanコマンドを使うとき
以下のコマンドでworkspaceに入りその中で行う
docker-compose run workspace
構築途中で直面した問題
php.iniのtimezone設定漏れによるエラー
php.iniのtimezoneを指定しないと、以下のようなエラーが表示され、ページが表示されません。
Error - date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in COREPATH/classes/fuel.php on line 161
そこで、apacheのDockerfileと同じ階層にデフォルトのphp.iniを置き、Dockerfileに以下を追記しました。
COPY php.ini /usr/local/etc/php/
RUN echo "date.timezone = Asia/Tokyo" >> /usr/local/etc/php/php.ini
これで実行時点で動作させる対象となるイメージが存在する場合は
docker-compose up -d --build
を、
存在しない場合は
docker-compose up -d
を実行すると、
apacheコンテナ(サーバー)作成時にphp.iniが作成されtimezoneも追記されます。
ちなみにイメージの確認は docker images
で可能です。
php.iniを直接書き換えてtimezoneを設定すれば
RUN echo "date.timezone = Asia/Tokyo" >> /usr/local/etc/php/php.ini
する必要もないですが、
私はめんどくさかったのでこっちを採用しましたー。
ホスト名指定によるローカル環境判断ができない
vagrantでローカル環境を用意していた際はホスト名を gethostname()
で指定して今動いてるシステムがローカル環境上のものかどうか判断する、といった処理をしていたのですが、
dockerで環境構築すると同じようなことができませんでした。
そこでdocker-compose.ymlのファイルを変え、apacheコンテナ(サーバー)のイメージ作成時に環境変数を指定し、この環境変数があればローカル環境、といった判断ができるようにしました。
apache:
build: apache
container_name: project_apache
volumes:
- ${BASE_DIR}
ports:
- 8080:80
environment:
- STAGE=docker
environmentのところで設定しています。
ちなみにPHP側で判別するときは以下みたいな感じです。
if (env("STAGE") == "docker") {
echo 'ローカル環境で動いています!';
}
php-apacheコンテナからmemcachedコンテナ、mysqlコンテナに繋げられない
laravelプロジェクト上の .env
でmemcachedコンテナ、mysqlコンテナに繋ぎたくても DB_HOST
やら MEMCACHED_HOST
やらに何を記載したらいいのかよくわからず…
と路頭に迷っていたところ、
docker-compose.ymlで宣言したサービスは、docker-compose upなどでコンテナ起動すると、同一のネットワークに所属することになる(Dockerネットワークと呼ぶ)。そして、それぞれホスト名が割り当てられる。そのホスト名はサービス名、もしくはdocker-compose.ymlで指定したコンテナ名となる。
(docker-composeとネットワーク、コンテナのホスト名の割り当てなどを理解するより引用)
とのこと!
つまり、ここで立てられた apache
, mysql
, cache
などのコンテナは全て同じネットワーク上に存在していることになり、
ホスト名(=コンテナ名)とポートで指定することで同ネットワーク上の別コンテナに接続ができるそうです。
コンテナ名は docker-compose.yml
内で container_name
として指定したもののことです。
docker ps
で NAMES
として出てきます。
また、指定しない場合でも、サービス名を指定することで接続できます。
今回のケースでは .env
に以下のように設定することでmemcachedコンテナ、mysqlコンテナへ繋がります。
DB_CONNECTION=mysql
DB_HOST=project_mysql
DB_PORT=3307
DB_DATABASE=db
DB_USERNAME=dbuser
DB_PASSWORD=password
MEMCACHED_HOST=project_cache
MEMCACHED_PORT=11211
PhpStorm/MySQLworkbenchがMySQLコンテナに繋がらない
docker ps
で出てきた情報を元に、以下で接続しようとしても繋がりません。。
hostname: 127.0.0.1
port: 3306
username: dbuser
password: password
というのも、 docker-compose.yml
の mysql
部分でportを指定していなかったのが原因でした。
以下みたいに設定してみることで繋がりました。
mysql:
image: mysql:5.7
container_name: project_mysql
ports:
- '3307:3306'
environment:
- MYSQL_DATABASE=db
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=root
volumes:
- project_mysql:/var/lib/mysql
volumes:
project_mysql:
driver: "local"
他のシステムのローカル環境等でMySQLのportを3306にすることが多いので、3307にしてみました。
これで以下の情報で繋がるはずです。
hostname: 127.0.0.1
port: 3307
username: dbuser
password: password
ports
の右側はコンテナ側のportで、左側はホストマシン側(ローカル)のポートだそうです。
ちなみに、volumesを設定しないとコンテナをdownすると同時に中身のデータまで吹っ飛びます。
忘れずに設定してローカルのディレクトリとMySQLコンテナのデータ領域をマウントしましょう。
導入してみて
やっぱりvagrantと比べてずっと容量も軽いし、開発もしやすくなりましたー。
面倒でも古い環境からモダンな環境に移行してみることが大事ですね。
dockerは勉強すればするほどこんなにシンプルで簡単なの!?と思わされることばかりですね。
勉強中の身なので、おかしい部分などあればご指摘いただけると幸いです!