はじめに
こんにちは。以前、LaradockでLaravelの開発環境を作っていました。ひとまずLaravelを触ってみたい時はそれで十分ですが、ほとんどチュートリアルのコピペで環境構築が終わってしまうので、dockerやdocker-composeが何をしているのかよく分からないままでした。
Laravel以外の環境構築もDockerで行えるようになっておきたいですし、今回は自力でdocker-composeを書いてローカル環境を構築してみます。
環境はmacOS High Sierra 10.13.6、Docker Desktop 2.0.0.2がインストール済みであることを前提とします。
nginxでwebサーバを立てる
適当なディレクトリを決めて、その中で作業します。どこでも構いませんが、今回は~/test
として、必要なコンテナを構築する情報をdocker-compose.yml
に記述していきます。
1 2 3 |
$ mkdir ~/test && cd $_1 $ mkdir -p ./docker/web $ vi ./docker-compose.yml |
1 2 3 4 5 6 7 8 9 |
version: "3" services: web: image: nginx:latest ports: - 80:80 volumes: - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html |
image: nginx:latest
で、DockerHub上にあるnginxの最新版のDockerイメージを指定できます。ローカルにイメージがあればそれを使い、無ければダウンロードされます。ports
はそのままポート番号です。左側がホスト側、右側がコンテナ側です。上記の場合はいずれもhttp通信のデフォルトである80番を指定しています。
例えば8000:80
と記述した場合、ブラウザからアクセスする際はhttp://ホスト名:8000
となります。volumes
でコンテナと共有したいパスを指定します。ホスト側で作成したdefault.conf
を、コンテナ側の同ファイルと置き換えます。
ポートと同じくホスト側パス:コンテナ側パス
の順で記述します。
default.conf作成
nginxの設定ファイルです。ひとまず最低限の設定のみ記述し、PHP関連の設定は後で追記します。
1 2 3 4 5 6 7 8 9 |
server { listen 80; root /var/www/html; index index.html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; } |
index.html作成
nginxの動作を確認できればよいので、htmlの中身は1行で構いません。
1 |
$ touch ./index.html && echo "<h1>Hello nginx.</h1>" > ./index.html |
nginxコンテナ起動
1 2 3 |
$ docker-compose up -d Creating network "test_default" with the default driver Creating test_web_1 ... done |
ブラウザでhttp://localhost
にアクセスしてHello nginx.
の文字が出てくればOKです。
nginxでPHP-FPMを動作させる
docker-compose.yml編集
静的コンテンツが見れるようになりましたので、次はPHP-FPMです。docker-compose.yml
にPHP-FPMコンテナの情報を記述していきます。
また、nginxにもPHP-FPMとの関連性を追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
version: "3" services: web: image: nginx:latest ports: - 80:80 volumes: - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html depends_on: - php-fpm php-fpm: image: php:7.3-fpm-alpine volumes: - .:/var/www/html |
image: php:7.3-fpm-alpine
で、nginxと同様にdockerhub上のイメージを指定します。PHP-FPMのイメージはたくさんあるのですが、ここでは軽量なalpine Linuxのイメージを使っています。depends_on:
はコンテナの依存関係を示します。上記のように記述することで「php-fpmコンテナが起動したらwebコンテナを起動する」という意味になり、起動の順番を制御できます。
default.conf編集
nginxの設定ファイルdefault.conf
にもPHP-FPMの設定を追記します。
fastcgi_pass
の項にPHP-FPMへの接続情報を記述します。docker-compose.yml
でPHP-FPMの名前として指定しているphp-fpm
を記述し、PHP-FPMのデフォルトポートである9000番を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
server { listen 80; root /var/www/html; index index.php index.html index.htm; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php-fpm:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
index.php作成
index.html
と同様に、起動を確認できれば充分です。
1 |
$ touch ./index.php && echo "<?php phpinfo(); ?>" > ./index.php |
コンテナ起動
初回起動ではイメージのダウンロードが実行されます。最後2行のdone
が表示されたら起動OKです。再度http://loalhost
にアクセスしてみましょう。
1 2 3 4 5 6 |
$ docker-compose up -d ... 中略 ... Creating test_php-fpm_1 ... done Recreating test_web_1 ... done |
MariaDBを立ち上げる
データベースはMariaDBを使用します。MySQLでも問題ありませんが、設定や接続方法はほとんど一緒(らしい)なので、試しに使ってみようという程度のチョイスです。
docker-compose.yml編集
db:
以下がMariaDBに関する記述です。また、php-fpm
にも上述のdepends_on
を追記しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
version: "3" services: web: image: nginx:latest ports: - 80:80 volumes: - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html depends_on: - php-fpm php-fpm: image: php:7.3-fpm-alpine volumes: - .:/var/www/html depends_on: - db db: image: mariadb:latest ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: root MYSQL_USER: test MYSQL_PASSWORD: test MYSQL_DATABASE: testdb volumes: - ./db-data:/var/lib/mysql |
environment
以下にMariaDBの情報を設定しています。MariaDB最新の10系はMySQL5.7がベースとなっており、MySQL用の設定がそのまま使えるようです。
MYSQL_ROOT_PASSWORD:
rootユーザーの初期パスワードです。MYSQL_USER
root以外の初期ユーザーを設定できます。MYSQL_PASSWORD
↑で設定した初期ユーザーのパスワードです。MYSQL_DATABASE
を指定することで、MariaDBコンテナに接続する際のデータベース名を定義できます。データベースが無い場合は作成されます。
コンテナ起動
docker-compose up -d
でMariaDBコンテナも起動するようになります。
1 2 3 |
Creating test_db_1 ... done Recreating test_php-fpm_1 ... done Recreating test_web_1 ... done |
接続確認
PHPからMariaDBへの接続はLaravelインストール後に設定しますので、まずはMariaDBが立ち上がっていることの確認のみです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#MariaDBコンテナに接続する $ docker-compose exec db sh # testdbに接続する $ mysql -u test -p testdb # MYSQL_PASSWORDの値を入力する Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 9 Server version: 10.3.13-MariaDB-1:10.3.13+maria~bionic mariadb.org binary distribution Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [testdb]> |
Laravelインストール
ようやくLaravelです。ComposerやPHP拡張など、Laravelのインストールと動作に必要なパッケージを用意します。php-fpm
コンテナの中でコマンドを実行してもよいのですが、docker-compose
コマンド実行時に自動でよしなにやってくれるように、docker-compose.yml
を編集します。
php:7.3-fpm-alpine
イメージには上述のパッケージが含まれていませんので、別途Dockerfile
を作成し、そこにインストールコマンドを記述します。
1 2 3 4 5 6 |
php-fpm: build: ./docker/php volumes: - .:/var/www/html depends_on: - db |
build:
に記述したパスにDockerfile
を作成します。
$ mkdir ./docker/php && vi ./docker/php/Dockerfile
1 2 3 4 5 6 7 8 9 |
FROM php:7.3-fpm-alpine RUN apk --update add \ && apk add build-base curl git zip unzip vim RUN cd /usr/bin && curl -sS https://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer RUN apk add libxml2-dev curl-devel $PHPIZE_DEPS RUN pecl install xdebug RUN docker-php-ext-install pdo_mysql mbstring xml curl session tokenizer json RUN docker-php-ext-enable pdo_mysql mbstring xml curl session tokenizer json xdebug WORKDIR /var/www/html |
RUN
以降をシェルコマンドとして、コンテナ起動時に実行します。apk add
でパッケージインストールを行います。alpine以外のイメージだと大抵はapt-get
で、CentOSなどのRedHat系で言うyum
ですね。$PHPIZE_DEPS
を指定することで、phpizeに必要なパッケージが自動でインストールされます。phpizeはPHP拡張モジュールを動的にビルドするのに必要で、これがないとPHP拡張を導入する際、いちいちPHP本体をビルドし直すことになってしまいます。pecl install xdebug
はdockerとは関係なく、peclライブラリを入れる時のコマンドそのままですね。必要に応じてimagickやredisなどお好きなものを。docker-php-ext-install
でPHP拡張をインストールし、docker-php-ext-enable
で有効化します。意味こそコマンド名そのままですが、dockerコンテナ上ではこういう書き方になるんですね。
MariaDBはMySQL用のライブラリで接続可能ですのでpdo_mysqlを入れます。その他mbstringなど最低限必要そうなものを入れていますが、ここもお好みで。RUN composer
の行はLaravelのインストールを実行するコマンドです。testapp
はプロジェクト名ですので、ここは自由にどうぞ。
コンテナ再構築
docker-compose up -d
を実行しましょう。パッケージのダウンロード/インストール/ビルドが一斉に走りますので、結構かかります。
上述のDockerfileの最後にLaravelインストールのコマンドを記述すればコンテナ構築と同時にインストールも実行されますが、Dockerfileに書くとコンテナ起動時に毎回Laravelのインストールが走ってしまうので、あとでコンテナに入って実行します。
Laravelインストール
1 2 3 |
$ docker-compose exec php-fpm sh /var/www/html # composer create-project --prefer-dist laravel/laravel testapp |
ここでもLaravelが依存するComposerのパッケージ群がモリモリ入りますので、数分お待ち下さい。
Laravelのwelcomeページを表示する
Laravelの公開ディレクトリをドキュメントルートにするため、default.conf
を編集します。location
の中に下記の1行を追記し、docker-compose restart
で変更を反映してください。
1 2 3 4 5 6 7 8 9 10 |
location ~ \.php$ { root /var/www/html/testapp/public; ←追記 fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php-fpm:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } |
LaravelからMariaDBに接続する
Laravelプロジェクト内の.env
ファイルに、docker-compose.yml
で設定した接続情報を記述します。DB_HOST
にはMariaDBのコンテナ名が入ります。この場合はdb
ですね。
1 2 3 4 5 6 7 8 |
$ vi testapp/.env DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=testdb DB_USERNAME=test DB_PASSWORD=test |
マイグレーション実行
php-fpm
コンテナ内で実行します。DB接続に成功すれば、最初から入っているマイグレーションファイルが実行されます。
1 2 3 4 5 6 7 8 9 |
$ docker-compose exec php-fpm sh /var/www/html # cd testapp/ /var/www/html/testapp # php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table |
上記のようなメッセージが表示されればOKです。お疲れ様でした。
さいごに
Laradockはチュートリアルが充実していたおかげで、docker-composeについてはほぼ知識ゼロでも構築ができてしまっていました。今回docker-compose.yml
を調べながら一項目ずつ書くことで、それぞれがどのような意味で何が実行されているのか、多少は把握することができるようになりました。
Laravelインストールの項目で用意する ./docker/php/Dockerfile の5行目にある
curl-devel
でエラーが出て、これは正しくは
curl-dev
でしょうか?
調べると teratail の記述のアンサーで解決できたのでお知らせさせていただきました。
https://teratail.com/questions/310977