はじめに
エンジニアのkeitaMaxです。
今までDockerに触れたことがなかったのですが、思い立ってDockerについて0から学習をしています。
まず最初にいつも使用しているフレームワークのLaravel の動作環境を作りたいと思っています。
PHPのコンテナ、Nginxのコンテナ、MySQLのコンテナの3つを作成します。
参考にする記事
この記事をもとに作成していきたいと思います。
PHPのコンテナを起動する
まず作業用のフォルダを作成します。名前はdocker-laravel-app
にしました。
つぎに、Dockerの設定をしていきます。
docker-laravel-app
フォルダ直下にdocker-compose.yml
ファイルを置きます。
そしてdocker
フォルダを用意し、その中にapp
フォルダ、その中にDockerfile
ファイルとphp.ini
ファイルを置きます。
現在のフォルダ構成は以下のようになります。
├ docker
│ └ app
│ ├ Dockerfile
│ └ php.ini
│
└ docker-compose.yml
Dockerfile
appフォルダの中のDockerfileにはPHPの設定を記述します。
以下のように記述しました。
FROM php:8.3-fpm
ENV TZ Asia/Tokyo
RUN apt-get update && \
apt-get install -y git unzip libzip-dev libicu-dev libonig-dev && \
docker-php-ext-install intl pdo_mysql zip bcmath
COPY ./php.ini /usr/local/etc/php/php.ini
COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer
WORKDIR /app
参考元の記事と変わったところとわからなくて調べたところだけ書きます。
各行で何をやっているか知りたい方は参考元の記事をみると分かりやすく書いてあります。
FROM php:8.3-fpm
phpの最新バージョンが8.3だったので8.3-fpmを使用しています。
COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer
ここの--from=composer:2.7
がわからなくて調べました。
Optionally COPY accepts a flag --from= that can be used to set the source location to a previous build stage (created with FROM .. AS ) that will be used instead of a build context sent by the user. In case a build stage with a specified name can't be found an image with the same name is attempted to be used instead.
(参照元:https://docs.docker.com/reference/dockerfile)
DeepLに翻訳してもらうと、
COPYには、-from=<名前>というフラグを指定することができます。このフラグを使用すると、ユーザーから送信されたビルドコンテキストの代わりに、以前のビルドステージ(FROM ... AS <名前>で作成されたもの)が使用されます。指定した名前のビルドステージが見つからない場合は、代わりに同じ名前のイメージを使用しようとします。
おそらく、composer:2.0
のイメージを見に行って、そこから/usr/bin/composer
をコピーしてきてくれるってことだと思います。(間違えていたら教えていただけると助かります)
公式見たら、もっと新しいバージョンがあったので2.7にしました。
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 = /var/log/php/php-error.log
default_charset = UTF-8
[Date]
date.timezone = Asia/Tokyo
[mysqlnd]
mysqlnd.collect_memory_statistics = on
[Assertion]
zend.assertions = 1
[mbstring]
mbstring.language = Japanese
これは参考元の記事と同じにしています。
docker-compose.yml
version: "3.9"
services:
app:
build:
context: ./docker/app
dockerfile: Dockerfile
volumes:
- ./src/:/app
こちらも参考元の記事とほぼ同じにしています。
context: ./docker/app
dockerfile: Dockerfile
この部分のみ変えています。
参考元のままだと以下のエラーが出てしまったので修正しました。
=> ERROR [app stage-0 3/5] COPY ./docker/app/php.ini /usr/local/etc/php/php.ini
------
> [app stage-0 3/5] COPY ./docker/app/php.ini /usr/local/etc/php/php.ini:
------
failed to solve: failed to compute cache key: failed to calculate checksum of ref e66b1e17-0a14-406d-9242-99b15955451a::z7zbl530wjoxlryuzh15gw5li: "/docker/app/php.ini": not found
php.ini
ファイルがないといわれていたので、ここを修正し、Dockerfileも以下の部分を修正しました。
COPY ./php.ini /usr/local/etc/php/php.ini
PHPコンテナを起動
dockerファイルができたので、以下のコマンドを実行してみます。
docker-compose up -d --build
色々出てくると思うのですが、以下が出てくれば立ち上がっています。
[+] Running 1/2
- Network docker-laravel-app_default Created
✔ Container docker-laravel-app-app-1 Started
以下のコマンドで起動中のコンテナを見てみます。
PS C:\develop\docker-laravel-app> docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-laravel-app-app-1 docker-laravel-app-app "docker-php-entrypoi…" app 6 minutes ago Up 6 minutes 9000/tcp
docker-laravel-app-app
がいるので、無事起動できていることが確認できました。
Nginxのコンテナを起動する
docker
フォルダの中にnginx
フォルダ、その中にDockerfile
ファイルとdefault.conf
ファイルを置きます。
現在のフォルダ構成は以下のようになります。
├ docker
│ ├ app
│ │ ├ Dockerfile
│ │ └ php.ini
│ │
│ └ nginx
│ ├ Dockerfile
│ └ default.conf
│
└ docker-compose.yml
Dockerfile
FROM nginx:1.25-alpine
ENV TZ Asia/Tokyo
COPY ./default.conf /etc/nginx/conf.d/default.conf
nginx:1.25-alpine
のバージョンがあったので1.25にしました。
default.conf
server {
listen 80;
server_name example.com;
root /app/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;
}
}
これは参考元の記事と同じにしています。
docker-compose.ymlの更新
以下のように更新しました。
version: "3.9"
services:
app:
build:
context: ./docker/app
dockerfile: Dockerfile
volumes:
- ./src/:/app
# ------以下を追記------
web:
build:
context: ./docker/nginx
dockerfile: Dockerfile
ports:
- 8081:80
depends_on:
- app
volumes:
- ./src/:/app
Nginxコンテナを起動
以下のコマンドを実行してみます。
docker-compose up -d --build
コマンドが成功したら、以下のコマンドで起動中のコンテナを見てみます。
PS C:\develop\docker-laravel-app> docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-laravel-app-app-1 docker-laravel-app-app "docker-php-entrypoi…" app 38 minutes ago Up 38 minutes 9000/tcp
docker-laravel-app-nginx-1 docker-laravel-app-nginx "/docker-entrypoint.…" nginx 6 seconds ago Up 5 seconds 0.0.0.0:8081->80/tcp
docker-laravel-app-nginx-1
がいるので、無事起動できていることが確認できました。
下記URLにアクセスしてみましょう。
http://localhost:8081
まだ何もファイルを置いていないのでFile not found.
となっていると思います。
困ったことを解決した備忘録
Nginxのコンテナを立ち上げるときにエラーが特に出ていないのにpsコマンドで表示されないことがありました。
困っていましたが、Docker Desktop のほうをのログを見ると
2024-02-22 19:35:13 nginx: [emerg] unknown directive "//" in /etc/nginx/conf.d/default.conf:6
と書いてあり、エラーになっていることに気が付きました。
(default.conf
をコピペしたせいで//
というコメントアウトの記述が残ってしまっていました、、、)
なぜかエラーがないのにコンテナが立ち上がらないときは、Docker Desktop をみるとヒントがあるかもしれないです。
MySQLのコンテナを起動する
docker
フォルダの中にdb
フォルダ、その中にDockerfile
ファイルとmy.conf
ファイルを置きます。
現在のフォルダ構成は以下のようになります。
├ docker
│ ├ app
│ │ ├ Dockerfile
│ │ └ php.ini
│ │
│ └ nginx
│ │ ├ Dockerfile
│ │ └ default.conf
│ │
│ └ db
│ ├ Dockerfile
│ └ my.conf
│
└ docker-compose.yml
Dockerfile
FROM mysql:8.3
COPY ./my.conf /etc/my.conf
mysql:8.3
のバージョンがあったので8.3にしました。
my.conf
[mysqld]
# character
character_set_server = utf8mb4
collation_server = utf8mb4_0900_ai_ci
# timezone
default-time-zone = SYSTEM
log_timestamps = SYSTEM
# Error Log
log-error = mysql-error.log
# Slow Query Log
slow_query_log = 1
slow_query_log_file = mysql-slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0
# General Log
general_log = 1
general_log_file = mysql-general.log
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
これは参考元の記事と同じにしています。
docker-compose.ymlの更新
以下のように更新しました。
version: "3.9"
services:
app:
build:
context: ./docker/app
dockerfile: Dockerfile
volumes:
- ./src/:/app
nginx:
build:
context: ./docker/nginx
dockerfile: Dockerfile
ports:
- 8081:80
depends_on:
- app
volumes:
- ./src/:/app
# ------以下を追記------
db:
build:
context: ./docker/db
dockerfile: Dockerfile
ports:
- 3306:3306
environment:
MYSQL_DATABASE: database
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
TZ: "Asia/Tokyo"
volumes:
- mysql-volume:/var/lib/mysql
MySQLコンテナを起動
以下のコマンドを実行してみます。
docker-compose up -d --build
コマンドが成功したら、以下のコマンドで起動中のコンテナを見てみます。
PS C:\develop\docker-laravel-app> docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-laravel-app-app-1 docker-laravel-app-app "docker-php-entrypoi…" app 3 hours ago Up 3 hours 9000/tcp
docker-laravel-app-db-1 docker-laravel-app-db "docker-entrypoint.s…" db 28 seconds ago Up 27 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp
docker-laravel-app-nginx-1 docker-laravel-app-nginx "/docker-entrypoint.…" nginx 3 hours ago Up 3 hours 0.0.0.0:8081->80/tcp
docker-laravel-app-db-1
がいるので、無事起動できていることが確認できました。
Laravelをインストールする
最後にLaravelをインストールして初期画面をブラウザで見れるようにします。
下記コマンドでappのコンテナの中に入ります。
docker compose exec app bash
app
の部分はdocker compose ps
コマンドを打つとでてくる、SERVICE
欄にある名前を入れます。
例えばdocker-laravel-app-db-1
に入りたい場合は以下のコマンドになります。
docker compose exec db bash
入ることができたら、以下のコマンドでLaravelを入れましょう。
composer create-project laravel/laravel .
これで最新のLaravelがインストールされます。
最後に.
を入れることによってカレントディレクトリにそのままインストールすることができます。
これを入れないとディレクトリが新しくできてしまい、無駄にもう一階層深いところにLaravelがインストールされてしまいます。
これで先ほどの以下のURLにアクセスします。
http://localhost:8081/
Logファイルの権限が足りないというエラーが出てしまいました。
そのため、以下コマンドでstorageに権限を付けます。
chmod -R 775 storage
再度アクセスします。
これでLaraveLの初期画面を見ることができました。
さいごに
Dockerはなにか難しいものだという先入観があり、なかなか挑戦できなかったのですが、いざやってみると案外簡単にコンテナを立ち上げることができました。
やり方が違ったり、もっといいやり方があるというご指摘がある方はコメントしていただけると幸いです。
最後まで読んでいただきありがとうございました。
参考文献
次の記事