2
4

【Docker】Laravelの環境を作成してDockerを理解する

Last updated at Posted at 2024-02-23

はじめに

エンジニアの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-laravel-app
├ docker
│    └ app
│        ├ Dockerfile
│        └ php.ini
│
└ docker-compose.yml

Dockerfile

appフォルダの中のDockerfileにはPHPの設定を記述します。

以下のように記述しました。

Dockerfile
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

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

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も以下の部分を修正しました。

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-laravel-app
├ docker
│    ├ app
│    │   ├ Dockerfile
│    │   └ php.ini
│    │   
│    └ nginx
│        ├ Dockerfile
│        └ default.conf
│
└ docker-compose.yml

Dockerfile

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

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の更新

以下のように更新しました。

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-laravel-app
├ docker
│    ├ app
│    │   ├ Dockerfile
│    │   └ php.ini
│    │   
│    └ nginx
│    │   ├ Dockerfile
│    │   └ default.conf
│    │   
│    └ db
│        ├ Dockerfile
│        └ my.conf
│
└ docker-compose.yml

Dockerfile

Dockerfile
FROM mysql:8.3

COPY ./my.conf /etc/my.conf

mysql:8.3のバージョンがあったので8.3にしました。

my.conf

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の更新

以下のように更新しました。

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/

image.png

Logファイルの権限が足りないというエラーが出てしまいました。

そのため、以下コマンドでstorageに権限を付けます。

chmod -R 775 storage

再度アクセスします。

image.png

これでLaraveLの初期画面を見ることができました。

さいごに

Dockerはなにか難しいものだという先入観があり、なかなか挑戦できなかったのですが、いざやってみると案外簡単にコンテナを立ち上げることができました。

やり方が違ったり、もっといいやり方があるというご指摘がある方はコメントしていただけると幸いです。

最後まで読んでいただきありがとうございました。

参考文献

次の記事

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4