はじめに
Docker + Laravelの環境構築はQiitaに溢れているのですが、Docker + Symfonyの記事はあまり見当たらなかったので記事にしました。(と言ってもほぼLaravelと変わらないですが)。
Docker初心者なので、各種設定などを備忘録として細かく解説していこうと思います。
構成
ホスト環境
| ツール | バージョン |
|---|---|
| Mac macOS | Catalina 10.15.5 |
| docker-compose | 1.25.5 |
| docker-sync | 0.5.14 |
構築環境 (ゴール)
- PHP 7.4
- mysql 5.7
- Apache
- Symfony 5
ディレクトリ構成
appディレクトリにsymfonyのソースコードを配置します。注意点としてルートにある.envはSymfonyの.envとは異なります。
project/
├ app/
├ docker/
│ ├ apache/
│ │ └ my_app.conf
│ ├ php/
│ │ └ php.ini
│ └ Dockerfile
├ .env
├ docker-compose.yaml
└ docker-sync.yaml
必要なツール類のインストール
Homebrewを使って、ホスト環境に必要なツール類をインストールします。
docker
$ brew install docker
$ brew cask install docker
docker-sync
>> ~/.zshrcのところは環境に合わせて変えてください。
$ brew install ruby
$ echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc
$ source ~/.zshrc
$ gem install docker-sync -n /usr/local/bin
docker-composeの設定
version: '3'
services:
app:
container_name: my_app
build: ./docker
ports:
- 8880:80
volumes:
- my_app_symfony:/var/www/html
- ./docker/php/php.ini:/usr/local/etc/php/php.ini
- ./docker/apache/my_app.conf:/etc/apache2/sites-enabled/my_app.conf
depends_on:
- mysql
mysql:
image: mysql:5.7
container_name: my_app_app_mysql
environment:
MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
MYSQL_DATABASE: $DB_NAME
TZ: 'Asia/Tokyo'
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- 3306:3306
volumes:
my_app_symfony:
external: true
解説
docker-composeは複数のDockerコンテナをまとめて管理するツールです。docker-compose.yamlのservicesの下に各種コンテナの設定を記述します。
appには、WEBサーバーとして動作するコンテナの設定を記述してあります。container_nameのmy_appは好きな値に書き換えて大丈夫です。
build: ./dockerと記述することでdocker/Dockerfileの内容にしたがってビルドを行います。
portsにはコンテナで立ち上げたプロセスのどのポートをローカルのどのポートにバインドするかと言う設定を記述します。ローカル:コンテナの順で記述するので、今回はローカルの8880ポートをコンテナの80ポートへバインドする、と言う意味です。http://localhost:8880 へリクエストを送ると、コンテナ内の80ポートへリクエストが転送されます。
volumesにはローカルにあるファイルやディレクトリをコンテナと同期する場合に記述します。volumesの2,3行目はローカルのphp.iniとmy_app.confをコンテナと同期する設定が記述してあります。1行目は、appディレクトリにあるローカルのsymfonyのプロジェクトをコンテナの/var/www/htmlと言うように記述してありますが、symfonyのソースコードは量が多く普通に同期するとパフォーマンスが落ちるので後述するdocker-syncを用いて同期を行います。ここでは、一番下に記述してあるvolumesの項目で(docker-syncで作成された)外部のボリュームを定義し、それにmy_app_symfonyと言う名前をつけています。appコンテナのvolumesのローカルの方にはこのmy_app_symfonyを指定します。
mysqlにはDBとして使用するmysqlコンテナの設定が記述してあります。こちらはDockerfileを用いず、あらかじめ公開されているイメージを使用します。イメージはDockerhubなどで検索することができます。Dockerhubのmysqlのページにドキュメントがあるのですが、コンテナを作成する時に特定の環境変数を渡すことで各種設定を行うことができます。環境変数はenvironmentに書くことで渡すことができ、今回はMYSQL_ROOT_PASSWORD、MYSQL_DATABASE、TZの三つを使用していますです。役割は名前から推測できると思うので割愛します。また、このファイルに変数の値をベタがきしても良いのですが、今回は柔軟性を持たせるためにローカルの環境変数から値を取得してくるようにしています(ややこしい)。ルートディレクトリにある.envファイルに
DB_ROOT_PASSWORD=root
DB_NAME=app_db
と言うように書いておくことで、コンテナ作成時にdocker-compose.yaml無いの変数を書き換えてくれます。
commandにはコンテナ作成時にコンテナ内で実行されるコマンドを記述することができます。
/docker ディレクトリ
memory_limit = 2048M
date.timezone = "Asia/Tokyo"
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/my_app/public
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
FROM php:7.4-apache
RUN a2dissite 000-default
WORKDIR /var/www/html
RUN apt-get update && apt-get install -y git zip unzip
RUN apt-get install -y wget libjpeg-dev libfreetype6-dev
RUN apt-get install -y libmagick++-dev \
libmagickwand-dev \
libpq-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libwebp-dev \
libxpm-dev
RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd
RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && mv /usr/bin/composer.phar /usr/bin/composer
解説
php.iniとmy_app.confには特殊なことは書いていません。必要に応じて編集してください。
Dockerfileにはコンテナをどのようにビルドするかと言う手順を記述します。
1行目のFROMにはコンテナの元となるイメージを指定します(Dockerhubで検索)。RUN xxxxとすると、コンテナ内でxxxxを実行します。注意点として、RUNコマンドで実行した結果は次のRUNコマンドへは引き継がれませんので、cdなどでディレクトリ移動したのに何故かファイルが無い!!見たいなことが起こります。結果を引継ぎたい時は&&でコマンドを続けて指定します。
2行目以降ではApacheのデフォルトサイトを無効化し、phpのgd拡張のインストール及び、composerのインストールを行っています。WORKDIR /var/www/htmlでは作業ディレクトリを/var/www/htmlに設定しています。
docker-syncの設定
version: '2'
syncs:
my_app_symfony:
src: './app'
sync_host_ip: '127.0.0.1'
sync_host_port: '5000'
sync_strategy: 'native_osx'
sync_excludes: ['.git', '.gitignore', 'node_modules']
解説
syncsの中に各種ボリュームの定義を記述します。my_app_symfonyのところはdocker-composeのvolumesで指定したボリューム名と一致させます。
srcには同期させるディレクトリを指定し、sync_host_ipとsync_host_portそれぞれホストのIPトポートを指定します。sync_strategyは、色々あるようですが、とりあえずnative_osxで問題無いと思います(よくわかってない)。sync_excludesには同期しないファイル、ディレクトリを指定します。node_modulesなど量が多くPHPで使用しないソースコードなどは同期しない方が無難だと思います。
起動
※ 8880ポート、8888ポート、5000ポート、3306ポートを使用するので、これらを使用しているソフトがある場合は停止しておいてください。
$ docker-sync start
$ docker-compose up -d --build
この時点で各種コンテナが起動します。
続いて、コンテナへ入りcomposerを用いてsymfonyのプロジェクトを作成します。コンテナからはexitで抜けられます。
# appコンテナでbashを実行
$ docker-compose exec app /bin/bash
# コンテナ内
root@eb419aab1d32:/var/www/html# composer create-project symfony/skeleton my_app
ローカルのブラウザから http://localhost:8880 へアクセスするとsymfonyの画面が表示されていると思います!
各種操作
# コンテナの終了
$ docker-compose stop
# コンテナの再開
$ docker-compose start
# composer install
$ docker-compose exec app composer install
以上!