はじめに
PHP と MySQL の環境構築を行っていた際、docker-compose up -d
でコンテナを作成し、動作させようとした。PHPのコンテナは正常に動いたが、MySQL のコンテナが build は正常にできたものの、動作がうまくいかなかった。
以下は、 docker-compose up -d
を実行した際にターミナルに表示された内容である。
[+] Building 0.0s (0/0)
[+] Running 2/0
✔ Container mysql-container Running 0.0s
Container php-container Starting
環境
- OS: Windows10
- PHP: 7.3-apache
- MySQL: 8.0
解決法(It works for me)
タスクマネージャーから、mysqld.exe を終了する。
原因
起動中の mysqld.exe がポート番号 3306 を既に使用していた。docker-compose.yml ファイルで MySQL のポート番号を 3306 に指定していたため、ポート番号が被っていた。
解決に至るまでに行ったこと
-
docker-compose up -d
実行、失敗
最初に書いた通り。コンテナの実行に失敗している。起動したが途中で強制終了したわけでもなさそうだった。 -
docker-compose
コマンドのログを表示して原因を特定
verbose オプションでログを表示。以下のコマンドを実行することで、docker-compose
コマンドのログをターミナル上に表示することができる。ログが止まった箇所がコンテナ構築を阻害している可能性が高い。(私の場合はdocker-compose up
コマンドで PHP 側のコンテナは起動できていたため、既に原因は特定できていた。)docker-compose --verbose build --no-cache
-
ポート番号 3306 でリッスンしているプロセスを調査
docker-compose.yml ファイルで 3306 番ポートを指定していたことを思い出す。ポートが既にバインドになっていることを疑い、3306 番のポート番号にリッスンするプロセスを探す。以下のコマンドを実行。netstat
コマンドでネットワークの接続状況や状態を確認する。
-a, -n, -o オプションでそれぞれ、すべてのアクティブなTCP接続の状態、アドレスとポート番号(数字)、接続に関連するプロセスID(PIDとも。ソケット・オプション統計情報、フラグ統計情報、 およびバッファー統計情報などの、ソケットに関する詳細なデータ。-a, -n オプションと併用)を表示する。netstat -ano | findstr ":3306"
実行した結果が以下のようになっており。ポート番号 3306 番のプロセスによって、プロセスID 5464 がアクティブになっていることがわかった。
TCP 0.0.0.0:3306 0.0.0.0:0 LISTENING 5464 TCP 0.0.0.0:33060 0.0.0.0:0 LISTENING 5464 TCP [::]:3306 [::]:0 LISTENING 5464 TCP [::]:33060 [::]:0 LISTENING 5464
-
プロセスIDが 5464 のプロセスを探す
tasklist
コマンドで、ローカルまたはリモートで実行中のプロセスの一覧を表示する。実行するコマンドは以下のようになる。tasklist /FI "PID eq 5464"
/fi オプションでフィルターを行う。後に続く "○○" が条件。今回は、PID = 5464 となるプロセスを探す。実行結果が、下のようになった。
イメージ名 PID セッション名 セッション# メモリ使用量 ========================= ======== ================ =========== ============ mysqld.exe 5464 Services 0 44,404 K
どうやらmysqld.exe というイメージ名のプロセスが PID 5464 となっており、ポート番号 3306 をバインドしている原因であるとわかった。
-
タスクマネージャーから mysqld.exe を終了
タスクマネージャー -> 「詳細」タブから、mysqld.exe を右クリックして終了。この後、docker-compose up
コマンドが動いた。
再発防止
今後同じ手順でこのプロセスを踏むのは面倒なので、docker-compose.yml ファイルの記述を変える。大人しく別のポート番号に変えるのが楽で確実。
変更前:
ports:
- '3306:3306'
変更後:
ports:
- '3307:3306'
docker-compose.yml ファイルの記述
PHP と MySQL の環境構築がうまくいった docker-compose.yml ファイルの記述を最後に記す。適宜 name などは変えてほしい。私は気象APIを叩くアプリケーションを開発するために環境構築をしたため、それに関係した名前となっている。
docker-compose.yml :
version: '3.7'
services:
app:
build:
context: ./docker/php
dockerfile: Dockerfile
container_name: php-container
image: php:7.3-apache
volumes:
- ./src:/var/www/html
ports:
- 8080:80
depends_on:
- db
db:
container_name: mysql-container
image: mysql:8.0
build:
context: ./docker/mysql
dockerfile: Dockerfile
volumes:
- ./docker/mysql/data:/var/lib/mysql
ports:
- '${FORWARD_DB_PORT}:3306'
environment:
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USER}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_HOST: '${DB_HOST}'
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_ROOT_HOST: '%'
TZ: '${TZ}'
環境変数をまとめた .env ファイル :
COMPOSE_PROJECT_NAME=docker-compose-mysql
DB_HOST=host_name
DB_DATABASE=database_name
DB_USER=user_name
DB_PASSWORD=password
TZ=Asia/Tokyo
FORWARD_DB_PORT=3306
おわりに
同じ症状でない場合でも、docker-compose up
コマンドがどこで止まっているかを特定するために、docker-compose --verbose build --no-cache
コマンドを実行するだけでも解決の糸口となるのではないだろうか。