今日のテーマ
suzuki_hoge さんの Zenn 記事「実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本」で学習した内容を自分用にまとめたものです。
バインドマウントとは
ホストマシンの任意のディレクトリをコンテナにマウントする仕組み。
ホストマシンでファイルを変更するとコンテナに即時反映される。開発時のソースコード共有に向いている。
ボリュームとの違い
| ボリューム | バインドマウント | |
|---|---|---|
| 実体の管理 | Docker が管理 | 自分(ホストマシン上) |
| 使い分け | DBのデータなど、コンテナ内で変更されるデータ | ソースコードなど、ホストマシンで変更したいもの |
| 事前作成 | 必要 | 不要(既存のディレクトリをそのままマウント) |
COPY との違い
| COPY | バインドマウント | |
|---|---|---|
| 対象 | イメージ | コンテナ |
| 変更の反映 | image build の再実行が必要 | 即時反映 |
| 向いている用途 | 設定ファイルなど滅多に変えないもの | 開発中のソースコードなど |
バインドマウントの書き方
--volume オプション
--volume $(pwd)/src:/src
-
$(pwd)→ 現在のディレクトリの絶対パス -
:の左側をボリューム名ではなく絶対パスにするとバインドマウントと判断される
--mount オプション
--mount type=bind,src=$(pwd)/src,dst=/src
-
type=bind→ バインドマウントと明示する -
src→ ホスト側のパス -
dst→ コンテナ内のマウント先
App コンテナにソースコードをマウントして起動
docker container run \
--name app \
--rm \
--detach \
--interactive \
--tty \
--mount type=bind,src=$(pwd)/src,dst=/src \
--publish 18000:8000 \
docker-practice:app \
php -S 0.0.0.0:8000 -t /src
-
php -S 0.0.0.0:8000 -t /src→/srcをドキュメントルートとして PHP の組み込み Web サーバーを起動 -
--publish 18000:8000→ ホストの 18000 番ポートとコンテナの 8000 番ポートをつなぐ
DB コンテナに初期化クエリをマウントして起動
mysql:5.7 イメージはコンテナ起動時に /docker-entrypoint-initdb.d にある .sql を自動実行する。
初期化クエリ(docker/db/init.sql)をバインドマウントすることで、コンテナ起動時に自動でテーブルを作成できる。
docker container run \
--name db \
--rm \
--detach \
--platform linux/amd64 \
--env MYSQL_ROOT_PASSWORD=rootpassword \
--env MYSQL_USER=hoge \
--env MYSQL_PASSWORD=password \
--env MYSQL_DATABASE=event \
--mount type=volume,src=docker-practice-db-volume,dst=/var/lib/mysql \
--mount type=bind,src=$(pwd)/docker/db/init.sql,dst=/docker-entrypoint-initdb.d/init.sql \
docker-practice:db
※ 初期化クエリはデータが既に存在する場合は実行されないため、ボリュームを削除・再作成してから起動する必要がある。
ポートの公開
--publish ホスト側ポート:コンテナ側ポート でホストマシンとコンテナのポートをつなぐ。
--publish 18000:8000 # ブラウザで localhost:18000 にアクセスできる
--publish 18025:8025 # MailHog の Web UI にアクセスできる
公開するポートと公開しないポートの使い分け
MailHog は 8025(Web UI)と 1025(SMTP)の2つのポートを持っている。
- 8025 を公開する → ブラウザで届いたメールを確認するため
- 1025 を公開しない → メールを送るのは App コンテナだけで、Mac から直接送ることはないため。コンテナ間はネットワーク内で通信できるので公開不要。
ポートの競合
同じポートを複数のコンテナで使おうとするとエラーになる。
Bind for 0.0.0.0:18000 failed: port is already allocated
対処法:
- 使っているコンテナを停止する
- または別のポート番号を指定する
ネットワーク
コンテナをネットワークに接続する
--network docker-practice-network
同じネットワークに接続したコンテナ同士はコンテナ名やエイリアスで通信できる。
ネットワークエイリアスの設定
--network-alias db-host
コンテナにホスト名(別名)を設定する。IP アドレスは起動するたびに変わるが、エイリアスは常に同じ名前でアクセスできる。
App コンテナの DB 接続設定にこのエイリアスを指定することで、IP アドレスを気にせず接続できる。
ネットワークの確認
# ネットワークのサブネット確認
docker network inspect docker-practice-network | jq '.[].IPAM.Config'
# コンテナのネットワーク情報確認
docker container inspect app | jq '.[].NetworkSettings.Networks'