DockerでLaravelの開発環境を作ってみる(6回目練習Ver)
DockerでLaravel 8の環境を作ろうと公式ドキュメントを見ると、“Laravel Sail"というコマンドラインツールの説明があります。 今回はVersion 8 から使えるようになったという"Laravel Sail"を使ってみます。
作業環境は
- OS Ubuntu 20.04.2 LTS
- Docker version 20.10.7
- docker-compose version 1.29.2
です。
Laravel Sail
“Laravel Sail"はLaravel既定のDocker開発環境を扱うためのコマンドラインツールで、PHP、MySQL、Redisを使用したアプリケーションを簡単に始めることが出来るそうです。
インストールする
公式ドキュメントの「インストール」に説明があります。 今回はUbuntu上で開発するので"Getting Started On Linux"の項目にあるコマンドで初めます。
コマンドはcurl -s https://laravel.build/アプリケーションディレクトリ名 | bash
で、今回は"example-app"とします。
途中でパスワードを聞かれるので入力します。
$ curl -s https://laravel.build/example-app | bash
Unable to find image 'laravelsail/php80-composer:latest' locally
latest: Pulling from laravelsail/php80-composer
852e50cd189d: Pull complete
・・・中略・・・
Status: Downloaded newer image for laravelsail/php80-composer:latest
_ _
| | | |
| | __ _ _ __ __ ___ _____| |
| | / _` | '__/ _` \ \ / / _ \ |
| |___| (_| | | | (_| |\ V / __/ |
|______\__,_|_| \__,_| \_/ \___|_|
Warning: TTY mode requires /dev/tty to be read/writable.
Creating a "laravel/laravel" project at "./example-app"
Installing laravel/laravel (v8.5.22)
- Downloading laravel/laravel (v8.5.22)
- Installing laravel/laravel (v8.5.22): Extracting archive
Created project in /opt/example-app
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies
・・・中略・・・
Application ready! Build something amazing.
Sail scaffolding installed successfully.
Please provide your password so we can make some final adjustments to your application's permissions.
[sudo] izumi のパスワード: ◀パスワードを入力します
Thank you! We hope you build something incredible. Dive in with: cd example-app && ./vendor/bin/sail up
コマンドで指定した"example-app"ディレクトリが作成されます。
とりあえず実行する
最後のメッセージにあるcd example-app && ./vendor/bin/sail up
コマンドでいきなり実行することが出来ます。
$ cd example-app && ./vendor/bin/sail up
Creating network "example-app_sail" with driver "bridge"
Creating volume "example-app_sailmysql" with local driver
Creating volume "example-app_sailredis" with local driver
Creating volume "example-app_sailmeilisearch" with local driver
Pulling mysql (mysql:8.0)...
8.0: Pulling from library/mysql
33847f680f63: Pull complete
・・・中略・・・
Creating example-app_mailhog_1 ... done
Creating example-app_redis_1 ... done
Creating example-app_meilisearch_1 ... done
Creating example-app_selenium_1 ... done
Creating example-app_mysql_1 ... done
Creating example-app_laravel.test_1 ...
Creating example-app_laravel.test_1 ... error
ERROR: for example-app_laravel.test_1 Cannot start service laravel.test: driver failed programming external connectivity on endpoint example-app_laravel.test_1 (64ddadc80cd745b658ecd8b96b583ca1cc1915ce222e1d86b2ae3d0e6d81db49): Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
ERROR: for laravel.test Cannot start service laravel.test: driver failed programming external connectivity on endpoint example-app_laravel.test_1 (64ddadc80cd745b658ecd8b96b583ca1cc1915ce222e1d86b2ae3d0e6d81db49): Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
ERROR: Encountered errors while bringing up the project.
Laravelの実行に失敗する
初回は時間がかかるとのことで10分くらい待たされました。が、結果は"ERROR"であっさり終了してしまいました。 すでに"0.0.0.0:80"が使われているからダメだと言われています。
ポートの使用状況がどうなっているのか確認します。
# ssコマンドで使われているソケットの情報を確認します
$ ss -antu
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.73%lo:53 0.0.0.0:*
udp ESTAB 0 0 192.168.20.107%eth0:68 192.168.20.1:67
udp UNCONN 0 0 172.28.255.255:137 0.0.0.0:*
・・・中略・・・
tcp LISTEN 0 4096 [::]:6379 [::]:*
tcp LISTEN 0 50 [::]:139 [::]:*
tcp LISTEN 0 511 *:80 *:*
tcp LISTEN 0 4096 [::]:7700 [::]:*
# ポート80がLISTEN待ちしているので、lsofコマンドでどのプロセスか確認します
$ sudo lsof -i :80
[sudo] izumi のパスワード: ◀パスワードを入力します
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
apache2 781 root 4u IPv6 26025 0t0 TCP *:http (LISTEN)
apache2 782 www-data 4u IPv6 26025 0t0 TCP *:http (LISTEN)
apache2 783 www-data 4u IPv6 26025 0t0 TCP *:http (LISTEN)
Laravel Sailが使おうとしていた80ポートはすでに"apache2"で使われていました。
docker ps
コマンドで確認するといくつかのコンテナが実行中になっていますがLaravelのサーバーが起動されていないのでどうにもなりません。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4569583342c mysql:8.0 "docker-entrypoint.s…" 16 minutes ago Up 46 minutes (healthy) 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp example-app_mysql_1
82e57932cd4b selenium/standalone-chrome "/opt/bin/entry_poin…" 16 minutes ago Up 46 minutes 4444/tcp example-app_selenium_1
9ff3afdd0cff getmeili/meilisearch:latest "tini -- /bin/sh -c …" 16 minutes ago Up 46 minutes (healthy) 0.0.0.0:7700->7700/tcp, :::7700->7700/tcp example-app_meilisearch_1
b21d9baad59f redis:alpine "docker-entrypoint.s…" 16 minutes ago Up 46 minutes (healthy) 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp example-app_redis_1
cce025c406b9 mailhog/mailhog:latest "MailHog" 16 minutes ago Up 46 minutes 0.0.0.0:1025->1025/tcp, :::1025->1025/tcp, 0.0.0.0:8025->8025/tcp, :::8025->8025/tcp example-app_mailhog_1
今回はエラーとなってしまったので全てのコンテナを削除して別のポートを使用するように変更します。sail up
コマンドで実行中のコンテナはsail down
コマンドでまとめて廃棄することが出来ます。
$ ./vendor/bin/sail down
example-app_laravel.test_1 start-container Exit 128
Shutting down old Sail processes...
Removing network example-app_sail
WARNING: Network example-app_sail not found.
使用するポートを変更する
LaraveのDockerコンテナが使用するポートを80番から8080番へ変更します。
Laravel Sailのドキュメントにあるように"docker-compose.yml"ファイルに定義されているので確認します。
https://laravel.com/docs/8.x/sail
“example-app/docker-compose.yml"ファイル
# For more information: https://laravel.com/docs/sail
version: '3'
services:
laravel.test:
build:
context: ./vendor/laravel/sail/runtimes/8.0
dockerfile: Dockerfile
args:
WWWGROUP: '${WWWGROUP}'
image: sail-8.0/app
ports:
- '${APP_PORT:-80}:80'
environment:
WWWUSER: '${WWWUSER}'
LARAVEL_SAIL: 1
volumes:
- '.:/var/www/html'
networks:
- sail
depends_on:
- mysql
- redis
- meilisearch
- selenium
mysql:
image: 'mysql:8.0'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- 'sailmysql:/var/lib/mysql'
networks:
- sail
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
retries: 3
timeout: 5s
redis:
image: 'redis:alpine'
ports:
- '${FORWARD_REDIS_PORT:-6379}:6379'
volumes:
- 'sailredis:/data'
networks:
- sail
healthcheck:
test: ["CMD", "redis-cli", "ping"]
retries: 3
timeout: 5s
meilisearch:
image: 'getmeili/meilisearch:latest'
ports:
- '${FORWARD_MEILISEARCH_PORT:-7700}:7700'
volumes:
- 'sailmeilisearch:/data.ms'
networks:
- sail
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"]
retries: 3
timeout: 5s
mailhog:
image: 'mailhog/mailhog:latest'
ports:
- '${FORWARD_MAILHOG_PORT:-1025}:1025'
- '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025'
networks:
- sail
selenium:
image: 'selenium/standalone-chrome'
volumes:
- '/dev/shm:/dev/shm'
networks:
- sail
networks:
sail:
driver: bridge
volumes:
sailmysql:
driver: local
sailredis:
driver: local
sailmeilisearch:
driver: local
Laravelのコンテナ"laravel.test"定義を見るとポートの定義は'${APP_PORT:-80}:80'
となっていて環境変数を参照するようになっています。
“${APP_PORT:-80}“は環境変数APP_PORT
が未定義の場合80
を使用するという意味です。
環境変数APP_PORT
を”.env"ファイルに定義します。
“example-app/.env"ファイルに以下の1行を追加します。
APP_PORT=8080
example-appをカレントディレクトリにして、再びsail up
コマンドを実行します
~/example-app$ ./vendor/bin/sail up
Creating network "example-app_sail" with driver "bridge"
Creating example-app_meilisearch_1 ... done
Creating example-app_mysql_1 ... done
Creating example-app_selenium_1 ... done
Creating example-app_mailhog_1 ... done
Creating example-app_redis_1 ... done
Creating example-app_laravel.test_1 ... done
Attaching to example-app_meilisearch_1, example-app_mysql_1, example-app_redis_1, example-app_mailhog_1, example-app_selenium_1, example-app_laravel.test_1
mailhog_1 | 2021/07/27 05:48:40 Using in-memory storage
mailhog_1 | 2021/07/27 05:48:40 [SMTP] Binding to address: 0.0.0.0:1025
・・・中略・・・
laravel.test_1 | 2021-07-27 05:48:45,468 INFO Set uid to user 0 succeeded
laravel.test_1 | 2021-07-27 05:48:45,470 INFO supervisord started with pid 18
laravel.test_1 | 2021-07-27 05:48:46,474 INFO spawned: 'php' with pid 19
laravel.test_1 | Starting Laravel development server: http://0.0.0.0:80
laravel.test_1 | [Tue Jul 27 05:48:46 2021] PHP 8.0.8 Development Server (http://0.0.0.0:80) started
laravel.test_1 | 2021-07-27 05:48:48,172 INFO success: php entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
今度はDockerコンテナの起動に成功したようです。
ブラウザでhttp://localhost:8080/
を参照するとLaravelの画面が表示されました。
docker ps
コマンドで複数のコンテナが実行中なのが確認できます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d0f5dfd399d sail-8.0/app "start-container" 2 minutes ago Up 2 minutes 8000/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp example-app_laravel.test_1
7a9742baf998 mailhog/mailhog:latest "MailHog" 2 minutes ago Up 2 minutes 0.0.0.0:1025->1025/tcp, :::1025->1025/tcp, 0.0.0.0:8025->8025/tcp, :::8025->8025/tcp example-app_mailhog_1
3877622963b8 redis:alpine "docker-entrypoint.s…" 2 minutes ago Up 2 minutes (healthy) 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp example-app_redis_1
ca3df90e0591 selenium/standalone-chrome "/opt/bin/entry_poin…" 2 minutes ago Up 2 minutes 4444/tcp example-app_selenium_1
cbb7f7e3d448 mysql:8.0 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes (healthy) 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp example-app_mysql_1
ead5acdaeead getmeili/meilisearch:latest "tini -- /bin/sh -c …" 2 minutes ago Up 2 minutes (healthy) 0.0.0.0:7700->7700/tcp, :::7700->7700/tcp example-app_meilisearch_1
Laravelコンテナを終了する
終了するときはログが表示されている端末でControl + C
キーを押すことで終了します。
laravel.test_1 | [Tue Jul 27 05:50:19 2021] 172.19.0.1:33656 Accepted
laravel.test_1 | [Tue Jul 27 05:50:21 2021] 172.19.0.1:33656 Closing
^CGracefully stopping... (press Ctrl+C again to force)
Stopping example-app_laravel.test_1 ... done
Stopping example-app_mailhog_1 ... done
Stopping example-app_redis_1 ... done
Stopping example-app_selenium_1 ... done
Stopping example-app_mysql_1 ... done
Stopping example-app_meilisearch_1 ... done
$
# Dockerのコマンドで全てのコンテナが終了していることが確認できます
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Laravelコンテナをバッグラウンドで実行する
-d
オプションでデタッチモードで起動することが出来ます。
$ ./vendor/bin/sail up -d
Creating network "example-app_sail" with driver "bridge"
Creating example-app_selenium_1 ... done
Creating example-app_mysql_1 ... done
Creating example-app_mailhog_1 ... done
Creating example-app_meilisearch_1 ... done
Creating example-app_redis_1 ... done
Creating example-app_laravel.test_1 ... done
終了するときは’sail down’コマンドを実行します。
$ ./vendor/bin/sail down
Stopping example-app_laravel.test_1 ... done
Stopping example-app_redis_1 ... done
Stopping example-app_meilisearch_1 ... done
Stopping example-app_mailhog_1 ... done
Stopping example-app_mysql_1 ... done
Stopping example-app_selenium_1 ... done
Removing example-app_laravel.test_1 ... done
Removing example-app_redis_1 ... done
Removing example-app_meilisearch_1 ... done
Removing example-app_mailhog_1 ... done
Removing example-app_mysql_1 ... done
Removing example-app_selenium_1 ... done
Removing network example-app_sail
Larabel 8を使用するのであればsailで簡単にDocker環境を作ることが出来ました。