背景
docker-composeを利用するときに、コンテナ・ホスト名・データボリューム・ネットワーク名などの名前を指定しないと、自動的に名前が生成される。
あくまでも個人的な見解だが、ルールを覚えない限りは以下のような面倒な点があると考える。
- 作成されたものの名前を確認する必要がある。
- 意図せずにデフォルトネットワークが作られる。
- コンテナ間通信するときのFQDNはコンテナ名がわからない。(これについては別ページで別途記載するが、サービス名でも通信できた)
- 自動生成されたデータボリュームがわからないので紐づけを確認する必要がある。
コンテナとデータボリュームの関係を確認するには以下の方法があるが、どちらもコマンド自体覚えるのが面倒。(他にもあるかもしれないし、alias作れと言われればその通りだが、ある程度覚えておかないと新しい環境で再度aliasの設定内容を調べないといけない)docker inspect ${コンテナ名} | jq .[0].Mounts
docker ps --format "table {{.Names}}\t{{.Mounts}}"
docker-compose.ymlのバージョン3.5からネットワーク名も指定してできるようになって、全部解消したのでここにまとめます。
目的(ゴール)
- 基本的に作成されるものの名前は全部、docker-compose.ymlで事前に定義できるようにする。
- docker-composeコマンド実行時に作成されていないデータボリュームやネットワークが自動生成されること。
- 意図しないデフォルトネットワークなどが作成されないこと。
前提とする環境
- DockerホストOS:CentOS7
- Docker version 18.09.6, build 481bc77156
- docker-compose version 1.24.0, build 0aa59064
- docker-compose.ymlのバージョン:3.5
シンプルな定義で作成される名前
docker-composeを利用する場合に特に名前を指定しないと、以下のようになる。
- コンテナ名 => ${プロジェクト名}${サービス名}${連番}
- ホスト名 => CONTAINER ID
- データボリューム名 => 任意のID(たぶんuuidのハイフン無し版)
- ネットワーク名 => ${プロジェクト名}}_default(networksを定義しない場合)
※1.プロジェクト名とは、、、
- デフォルトではdockse-compose.ymlのカレントディレクトリ名
-
docker-compose -p ${プロジェクト名}
で上書きできる。 - 環境変数"COMPOSE_PROJECT_NAME"で上書きできる。
※参考:
以下に違いをわかりやすくするために、シンプルなもので作成してみた結果を記載する。
version: '3.5'
services:
web:
image: nginx:stable-alpine
db:
image: postgres:alpine
作成結果を確認する。
[docker-user@docker-host test]$ docker-compose up -d
Creating network "test_default" with the default driver
Creating test_web_1 ... done
Creating test_db_1 ... done
[docker-user@docker-host test]$ docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Networks}}\t{{.Mounts}}"
CONTAINER ID NAMES IMAGE NETWORKS MOUNTS
3b4634c1b885 test_web_1 nginx:stable-alpine test_default
09ab8eb433a8 test_db_1 postgres:alpine test_default 4f6e06816684d8…
[docker-user@docker-host test]$ docker volume ls
DRIVER VOLUME NAME
local 4f6e06816684d8e22994e30e7b4bbdce9a51a889e1b021c021f33a0326c36709
[docker-user@docker-host test]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
18b99de55ca4 bridge bridge local
09fbaf5da94d host host local
b5252395c879 none null local
ff1019402a0f test_default bridge local
[docker-user@docker-host test]$
無いものを自動生成してくれるのはありがたいが、勝手に名前が付くとdocker
コマンドで作ったものなのか、自動生成されたものなか、何で使われているのかをいちいち調べるのが面倒!!
2023/11追記
と記載しましたが、名前を固定化することによるデメリットもあるので追記します。
名前を固定化すると、複数の開発案件を同時進行で開発をしたり、他の人が開発したものをレビューを兼ねて動作確認をするときに現在の環境を汚さずに動作確認をするために、プロジェクトを分けて別の環境(コンテナ郡)を同一ホストに用意したい場合には名前が重複してエラーになることがあります。
おそらくですが、こういった用途も想定して動的にプロジェクト名で名前が決まるような仕様になっていると思われるので、深く考えずに以下の名前を固定化する方法を採用すると複数のアプリバージョンの実行環境を作成したいときに問題になります。
名前を明示的に指定しつつ、複数環境を用意したい場合は、追加で用意する側ではdocker-compose.override.ymlなどを用意して必要な部分をオーバーライドして用意するとよいでしょう。
すべての名前を明確に定義する方法(結論)
いろいろ過去の経緯を書こうと思ったが、面倒なので結論だけ書きます。
以下、サービス名とコンテナ名/ホスト名、docker-compose.yml上のボリューム識別子・ネットワーク識別子などは名前を同じにした方が理想的ですが、わかりやすくするためにあえて、別の名前にしています。
version: '3.5'
services:
web:
image: nginx:stable-alpine
# コンテナ名を明示的に指定する
container_name: web-container
# ホスト名を明示的に指定する
hostname: web-server
ports:
- 80:80
restart: always
# 明示的に所属するネットワークを指定する
networks:
# ここに指定するのは実際のネットワーク名ではなく、↓のnetworksの識別子
- container-link
db:
image: postgres:alpine
# コンテナ名を明示的に指定する
container_name: db-container
# ホスト名を明示的に指定する
hostname: db-server
ports:
- 5432:5432
restart: always
# 明示的に所属するネットワークを指定する
networks:
# ここに指定するのは実際のネットワーク名ではなく、↓のnetworksの識別子
- container-link
volumes:
# ここに指定するのは実際のボリューム名ではなく、↓のvolumesの識別子
- postgres-data-volume:/var/lib/postgresql/data:rw
# ネットワーク定義
networks:
# docker-composeで勝手にデフォルトネットワークが生成される予防。(自動で全コンテナが所属するbridgeを指定)
default:
# external:
# name: bridge
# => docker-composeのあるバージョンから「WARN[0000] network default: network.external.name is deprecated. Please set network.name with external: true 」というWARNINGが表示されるようになりました。以下にように書き換えてください。
external: true
name: bridge
# コンテナ間通信用のネットワークセグメント
container-link:
# これが作成されるネットワーク名(同名がなければ自動生成される)
name: docker.internal
# 以下は書かなくてもよい(サンプルとして)
driver: bridge
ipam:
driver: default
config:
- subnet: "172.20.100.0/24"
volumes:
# postgresコンテナのデータ永続化用のデータボリューム(同名がなければ自動生成される)
postgres-data-volume:
name: postgres-data
driver: local
作成結果を確認する。
起動する。
[docker-user@docker-host test]$ docker-compose up -d
Creating network "docker.internal" with driver "bridge"
Creating volume "postgres-data" with local driver
Creating web-container ... done
Creating db-container ... done
コンテナ・ネットワーク・データボリュームが作られた。
コンテナを確認する。
[docker-user@docker-host test]$ docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Networks}}\t{{.Mounts}}"
CONTAINER ID NAMES IMAGE NETWORKS MOUNTS
12749a07b048 web-container nginx:stable-alpine docker.internal
9e6356b75522 db-container postgres:alpine docker.internal postgres-data
コンテナのホスト名を確認する。
[docker-user@docker-host test]$ docker exec web-container hostname
web-server
[docker-user@docker-host test]$ docker exec db-container hostname
db-server
データボリュームを確認する。
[docker-user@docker-host test]$ docker volume ls
DRIVER VOLUME NAME
local postgres-data
[docker-user@docker-host test]$ docker volume inspect postgres-data
[
{
"CreatedAt": "2019-05-23T13:04:36+09:00",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "test",
"com.docker.compose.version": "1.24.0",
"com.docker.compose.volume": "postgres-data"
},
"Mountpoint": "/var/lib/docker/volumes/postgres-data/_data",
"Name": "postgres-data",
"Options": null,
"Scope": "local"
}
]
ネットワークを確認する。
[vagrant@docker-host test]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
18b99de55ca4 bridge bridge local
60ecb2f64e55 docker.internal bridge local
09fbaf5da94d host host local
b5252395c879 none null local
[vagrant@docker-host test]$ docker network inspect docker.internal | jq .[0].Containers
{
"12749a07b048f8135e0f6e0d80269f04c5ed8f7f6652703566076d478d31ef37": {
"Name": "web-container",
"EndpointID": "c93123b6c2e1005857753f4508a7bdb40c5a73d5211932de9e0cc80854809f00",
"MacAddress": "02:42:ac:14:64:03",
"IPv4Address": "172.20.100.3/24",
"IPv6Address": ""
},
"9e6356b75522ed423ec561a0d2c9dc4a1d3b5056c00f5f781800b1891d0e4a11": {
"Name": "db-container",
"EndpointID": "6c83fd8ec9b3080d928cc73cda6f26da639172be40116ef7118bc2806be19879",
"MacAddress": "02:42:ac:14:64:02",
"IPv4Address": "172.20.100.2/24",
"IPv6Address": ""
}
}
コンテナ間通信を確認する。
[vagrant@docker-host test]$ docker exec web-container ping -c 1 db-container.docker.internal
PING db-container.docker.internal (172.20.100.2): 56 data bytes
64 bytes from 172.20.100.2: seq=0 ttl=64 time=0.062 ms
--- db-container.docker.internal ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.062/0.062/0.062 ms
[vagrant@docker-host test]$ docker exec db-container ping -c 1 web-container.docker.internal
PING web-container.docker.internal (172.20.100.3): 56 data bytes
64 bytes from 172.20.100.3: seq=0 ttl=64 time=0.060 ms
--- web-container.docker.internal ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.060/0.060/0.060 ms