Rancher DesktopでDocker環境を構築する!②
前回のあらすじ
Rancher DesktopでDocker環境を構築する!①
今回はもうちょっと実用的な環境をDockerで作っていきます。
目標
docker composeでLEMP環境を作ってみます。
- PHP8
- MySQL8
- Nginx(読み: エンジンエックス)
フレームワークはLaravel9を採用してみます。
動作確認済み環境
- MacBook Air(M1, 2020)
- メモリ: 16GB
- macOS: Ventura 13.0.1
- Rancher Desktop Version 1.7.0 (1.7.0)
- git version 2.37.1
本記事の想定読者
- VirtualBoxやVagrantは使ったことあるけどDockerは触ったことがない方
- なんとなく誰かが作ってくれたDocker環境で開発してるけどもうちょっとDockerに詳しくなりたい方
本記事執筆の目的
-
なんとなく誰かが作ってくれたDocker環境で開発してるけどもうちょっとDockerに詳しくなりたい方
→ まさに自分がこの状態だったので、改めてDockerの知識を基礎から身につける - Docker初心者が最低限の知識を獲得できる内容であること
- エラーなど失敗ケースも含めて記載し、知見共有ができるような記事であること
本記事では取り扱わないこと
- Git, GitHubの使い方詳細説明
- Windowsでの環境構築
前提
- Rancher Desktopがインストールされ、dockerの各種コマンドが叩けること
下準備
各種バージョン確認
git --version
git version 2.37.1
docker --version
Docker version 20.10.10, build b485636
docker compose version
Docker Compose version v2.1.1
バージョンの細かい違いは気にしなくても大丈夫ですが、Docker Composeだけはv2以上になっているかご確認ください。
→もし入っていなければ(バージョン情報が出てこなければ)、最新・安定版をインストールする
作業用ディレクトリをMac上に作成
今回は dev/sandbox_laravel9
を作成してみる(場所も名前もなんでも良いです)
GitHub上でリモートリポジトリを作成する
※GitHubアカウントを持っていない場合は、あらかじめ作成・初期設定しておく必要があります。
- ブラウザからGitHubへログインし、Create a new repository画面にいく
- Repository name以外はいじらなくてもOK
- 画面下の Create repositoryボタンを押す
- リモートリポジトリの作成手順が出てくるのでそれに従ってコマンド入力
cd dev/sandbox_laravel9
echo "# sandbox_laravel9" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:{GitHubユーザーアカウント名}/sandbox_laravel9.git
git push -u origin main
PHPのアプリケーションサーバーのコンテナを作る
復習: コンテナを作るには
- Dockerイメージを作るためのdockerfileが必要 ※DockerHubのイメージを使う時は別
- dockerfileを元にDockerイメージのビルドが必要
- 作成したDockerイメージからコンテナが作れる
先にフォルダ群と空ファイル群を作っておく
ルートディレクトリ直下にこのようなフォルダ・ファイルを作成しておきます。
infra/
L php/
L dockerfile
L php.ini
src/
docker-compose.yml
docker-compose.yml
の中身は下記の通りになります。
version: "3.9"
services:
app:
build: ./infra/php
volumes:
- ./src:/data
volumes:
- ./src:/data
↑ここでホスト側のディレクトリをコンテナ側にマウントするための設定を行っています。
=ホストとコンテナの間でソースの内容を同期させるためのもの
dockerfile
dockerfile
の中身は下記の通りになります。
composerでライブラリの管理・PHPの拡張モジュール追加をやりたいので色々書いてあります。
FROM php:8.1-fpm-buster
ENV COMPOSER_ALLOW_SUPERUSER=1 \
COMPOSER_HOME=/composer
COPY --from=composer:2.2 /usr/bin/composer /usr/bin/composer
RUN apt-get update && \
apt-get -y install --no-install-recommends git unzip libzip-dev bicu-dev libonig-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
docker-php-ext-install intl pdo_mysql zip bcmath
COPY ./php.ini /usr/local/etc/php/php.ini
WORKDIR /data
dockerfileの命令文の詳細は↓を参照させていただきました。
php.ini
php.ini
の中身は下記の通り。ひとまずこの辺の設定だけ入れておきます。
zend.exception_ignore_args = off
expose_php = on
max_execution_time = 30
max_input_vars = 1000
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M
error_reporting = E_ALL
display_errors = on
display_startup_errors = on
log_errors = on
error_log = /dev/stderr
default_charset = UTF-8
[Date]
date.timezone = Asia/Tokyo
[mysqlnd]
mysqlnd.collect_memory_statistics = on
[Assertion]
zend.assertions = 1
[mbstring]
mbstring.language = Japanese
ビルドしてイメージを作成する
今回はdockerfileに加え、docker-compose.ymlも使用してビルドし、Dockerイメージを作ってみます。
dev/sandbox_laravel9上で、
docker compose build
FINISHEDとなっていれば成功です。
作成したDockerイメージからコンテナを作成する
先ほどと同様のディレクトリで(docker-compose.ymlが置いてあるディレクトリ)
docker compose up -d
up
はdocker-compose.ymlに書いてあるサービスを起動すること
-d
は「デタッチドモード」で起動しますよ、のオプション(-dをつけないデフォルトの状態では「アタッチドモード」での起動になる)
今回は、バックグラウンドでの起動を意味する「デタッチドモード」を使いました。
コンテナ一覧を確認してみます
docker compose ps
STATUSがrunning(起動状態)になっています
作ったコンテナに入ってみましょう
docker compose exec app bash
※app
はymlファイルで指定したサービス名ですね
各種バージョン・PHP拡張機能を確認してみて問題がないか確認します
php -v
composer-V
php -m
exit
でコンテナからでます
☕️ 余談
ちょっとした確認ならわざわざコンテナに入らなくても実行可能です💡
例 docker compose exec app php -v
ここまで作業内容をコミットする
キリが良いのでこの辺でgit commitしておきます。
一旦コンテナを破棄しておく
docker-compose.ymlはあとで内容を変更するので、一旦コンテナを破棄しちゃいます。
(気楽に破棄しても簡単に戻せるので大丈夫)
docker compose down
アプリケーションサーバー作りはここまで。
続いてwebサーバー(nginx)を作っていきます。
Nginxのwebサーバーのコンテナを作る
追加でフォルダ群と空ファイル群を作っておく
+
の箇所が追加部分です
infra/
L php/
L dockerfile
L php.ini
+ L nginx/
+ L default.conf
src/
+ L public/
+ L index.html (動作確認用・後で消す)
+ L phpinfo.php (動作確認用・後で消す)
docker-compose.yml
docker-compose.ymlに手を入れる
version: "3.9"
services:
app:
build: ./infra/php
volumes:
- ./src:/data
web:
image: nginx:1.20-alpine
ports:
- 8080:80
volumes:
- ./src:/data
- ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf
working_dir: /data
↑ web:~以降を追加しました。
💀 (落とし穴ポイント)
追記時は、インデントに注意して記載してください。
docker-compose.ymlではインデントがズレるとうまく動作しません。
services:
L app:
L build: ~~~
L volumes: ~~~
L web:
L image: ~~~
L ports:
- ~~~
L volumes:
- ~~~
- ~~~
L working_dir: ~~~
こんなイメージです。
なお、インデントがズレると↓のようなエラーが発生します
docker compose up -d
(root) Additional property web is not allowed
参考
また、NginxはDockerHubで公開されているDockerイメージをそのまま使うので、今回はNginx用にdockerfileは使いません。
docker-compose.yml追記部分の解説
ports:
- 8080:80
これは、ホスト側からコンテナ側にアクセスするための公開用の設定で、
ポート設定がないとアプリケーションサーバーとwebサーバーの繋がりが作れないため設定を書いています。
volumes:
- ./src:/data
- ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf
working_dir: /data
ホスト側にあるディレクトリ、ファイルをコンテナ内へマウント(同期)させるための設定です。
前回記事では、無理やり手動でソースの同期を行いましたが、この設定により自動的にソースの内容が同期できるようになります😇
infra/nginx/default.confの中身を書く
server {
listen 80;
server_name example.com;
root /data/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
root
, fastcgi_pass
のドキュメントルート設定を書き換えています。
設定の詳細はこちらを参照ください
いよいよビルドしてみる
アプリケーションサーバーの時同様、docker-compose.ymlのあるディレクトリでビルドのコマンドを実行します。
docker compose up -d
念の為確認
docker compose ps
問題なさそうです
Nginxのバージョン確認もしてみます
docker compose exec web nginx -v
nginx version: nginx/1.20.2
バージョンが表示されていれば成功です。
ブラウザで画面表示できるか確認してみる
src/public内の2ファイルに表示確認ができそうなことを書いてみましょう。
- index.html
<p>Hello, world!</p>
- phpinfo.php
<?php phpinfo(); ?>
この状態でブラウザを確認し、
-
http://localhost:8080/index.html
でHello, world!
と表示されていること、 -
http://localhost:8080/phpinfo.php
で、phpの環境情報の画面が表示されること
これら2点が確認できれば成功です。
💀 (落とし穴ポイント)
余談: この時点でinfra/nginx/default.confがなかったり、中身が空っぽだと、
ブラウザ上ではレスポンスが返ってこないというエラーが出てしまうので注意。
ブラウザ表示確認ができたのでindex.htmlとphpinfo,phpは削除しちゃいましょう。
rm -rf src/*
※rm -rf
は実行すると取り返しのつかない強制削除なので警告が出ますが、このまま"y"(yes)を入力して実行してください。
ここまで作業内容をコミットする
キリが良いのでこの辺でgit commitしておきます。
Laravelをインストールする
手順
- appコンテナに入る
- composerでLaravelをインストールする
- ブラウザ上でLaravelの初期画面が出るか確認する
appコンテナに入ります
docker compose exec app bash
コンテナに入ったらcomposerでLaravelをインストールします
composer create-project --prefer-dist "laravel/laravel=9.*" .
💀 (落とし穴ポイント) /data/vendorディレクトリがない
インストールを進めていると、諸々のエラーが表示されてしまいます。
また、このままブラウザでアクセスするとエラーが表示されLaravelのwelcome画面が表示されません。
http://localhost:8080
色々とエラーが表示されていますが、
結論から言うと、
/data/public/../vendor/autoload.php を開くのに失敗してエラーになっていることを確認します。
git cloneが終わった状態では app コンテナ内に /data/vendor ディレクトリが存在しないためです。
参考
というわけで色々対処が必要そうです。😇 解決方法
appコンテナに入ります
docker compose exec app bash
書き込み権限がないとキャッシュやログにエラーを書き込めないので、権限を付与
chmod -R 777 storage bootstrap/cache
vendor
ディレクトリへライブラリ群をインストール
composer install
もう一度、 http://localhost:8080
にアクセスします。
💀 (落とし穴ポイント) No application encryption key has been specified.
さっきとは違うエラーが出てきます。
これは、
「アプリケーション暗号化キーが指定されていません。」というエラーになります。
.env の APP_KEY に値が設定されてないと表示されるエラーです。
.env.example はありますが、 .env ファイルが存在しません。
理由は .env はGit管理対象外に設定されているからです。
参考
😇 解決方法
.env.example
を元に .env
コピーして作成してみましょう
(.envはLaravelアプリケーション全体の設定ファイル)
appコンテナに入った状態で
cp .env.example .env
💀 (落とし穴ポイント) APP KEYがない
また同じエラーが出てきました。APP KEYがないとかどうとか言われています。
現時点で .env
の中身を見ると確かに'APP_KEY=' となっておりAPP KEYが設定されていないようです。
😇 解決方法
APP KEYを設定します
root@6fbff122b578:/data# php artisan key:generate
INFO Application key set successfully.
改めて .env
を確認すると、何らかの乱数がAPP_KEYに設定されています。
再度ブラウザで確認すると・・・
welcome画面が表示されました🎉
シンボリックリンクを張る
→ システムで生成したファイル等をブラウザからアクセスできるよう公開するためのものです。
root@6fbff122b578:/data# php artisan storage:link
INFO The [public/storage] link has been connected to [storage/app/public].
🤔 シンボリックリンクが必要な理由
例えば、Laravelでファイルアップロード機能と、アップロードされた画像やPDFなどファイルをブラウザ表示させる機能を作る場合、シンボリックリンクがないとファイルを外部に公開することが出来ません。
そのため、Laravelの php artisan storage:link
コマンドによって、
公開用のディレクトリを作成し、そこからアップロードされたファイルが保存されたディレクトリを参照することが出来るようにする必要があるという訳です。
ここまで作業内容をコミットする
キリが良いのでコンテナから exit
して、git commitしておきます。
おわりに
今回はアプリケーションサーバーとwebサーバーのコンテナを作成しました。
これでPHPとLaravelが動作する状態になりました。
次回ではまたまたdocker-compose.ymlを変更することになります。
そのため、一旦コンテナは破棄しましょう。
docker compose down
次はDBコンテナを作成していきます。
続く
Discussion