Open5
Docker Compose 小技
docker-compose.yml
を書くときによくやることを書く
環境変数を使う
プロキシだったり、ポート番号だったり、開発環境は様々
docker-compose.yml
version: "3.8"
services:
app:
build:
context: "."
args:
REQUIRED_VALUE: "${REQUIRED_VALUE:?required}"
HTTP_PROXY: "${HTTP_PROXY}"
HTTPS_PROXY: "${HTTPS_PROXY}"
image: "repo/name:${MYPJ_APP_TAG:-latest}"
ports:
- "${MYPJ_APP_PORT:-8080}:8080"
(リファレンス: Variable substitution)
解説
環境変数はshellの変数展開を使えるので、空のときにエラーにしたりデフォルト値を指定したりできる。が、あまり複雑なことはしないに越したことはない
-
${REQUIRED_VALUE:?required}
はREQUIRED_VALUE
が空の場合にrequired
とメッセージが出てエラーになる -
${MYPJ_APP_TAG:-latest}
はMYPJ_APP_TAG
が空の場合にlatest
を返す -
${HTTP_PROXY}
は任意入力だが、未指定の場合は警告が出るので、docker-compose
コマンドの出力結果をそのまま別のことに使っている場合は注意
アンカーを使う
同じ設定が重なりがちな場合に使う
docker-compose.yml
version: "3.8"
services:
app1:
build:
context: "."
args: &args
APP_VALUE: "app1"
REQUIRED_VALUE: "${REQUIRED_VALUE:?required}"
HTTP_PROXY: "${HTTP_PROXY}"
HTTPS_PROXY: "${HTTPS_PROXY}"
image: "repo/name:${MYPJ_APP_TAG:-latest}"
logging: &logging
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
app2:
build:
context: "."
args:
<<: *args
APP_VALUE: "app2"
image: "repo/name:${MYPJ_APP_TAG:-latest}"
logging: *logging
Extension fieldsを使う例
リファレンス: Extension fields
docker-compose.yml
version: "3.8"
x-logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
services:
app1:
build:
context: "."
args: &args
APP_VALUE: "app1"
REQUIRED_VALUE: "${REQUIRED_VALUE:?required}"
HTTP_PROXY: "${HTTP_PROXY}"
HTTPS_PROXY: "${HTTPS_PROXY}"
image: "repo/name:${MYPJ_APP_TAG:-latest}"
logging: *logging
app2:
build:
context: "."
args:
<<: *args
APP_VALUE: "app2"
image: "repo/name:${MYPJ_APP_TAG:-latest}"
logging: *logging
解説
- アンカーやエイリアスは、Docker Compose ではなく YAML の仕様
GitHub Actions でも使えてくれ -
&args
で指定したものは*args
で使える. - そのまま使う(
*logging
)他、マージして使うことも可能(<<: *args
)。この例の場合、*args
のAPP_VALUE
はapp1
からapp2
に上書きされる - パッと見でわかりやすい程度に抑える
プロジェクト同士をつなぐ
マイクロサービス同士で連携したいようなときに使う。
事前に docker network create
でネットワークを作成しておく
docker network create my_project_network
docker-compose.yml(一部)
# (略)
networks:
my_project_network:
external:
name: "my_project_network"
# (略)
project A の docker-compose.yml
docker-compose.yml
version: "3.8"
services:
app:
image: "repo/project-a:latest"
networks:
- "my_project_network"
networks:
my_project_network:
external:
name: "my_project_network"
project B の docker-compose.yml
docker-compose.yml
version: "3.8"
services:
app:
image: "repo/project-b:latest"
expose:
- 8080
networks:
my_project_network:
aliases:
- "app.project-b.local"
networks:
my_project_network:
external:
name: "my_project_network"
解説
-
my_project_network
に両方の project A のapp
と project B のapp
をつなぐ - この例では project A の
app
から project B のapp
にapp.project-b.local
というホスト名で接続できる(expose
を忘れずに)
Health Check をちゃんとやる
MySQL を例に
version: "3.8"
services:
app:
image: "alpine"
command: echo "hello world"
depends_on:
database:
condition: "service_healthy"
networks:
- "default"
database:
image: "mysql"
expose:
- 3306
environment:
MYSQL_ROOT_PASSWORD: "your-password"
healthcheck:
test:
["CMD-SHELL", "mysql -u root -pyour-password -e 'select 1;' || exit 1"]
interval: "1s"
timeout: "5s"
retries: 30
start_period: "3s"
networks:
- "default"
解説
- 上記
services.database.healthcheck
は「3s
経ってからtest
のコマンドを最大30
回実行する。1回ごとのタイムアウトは5s
で、次の実行まで1s
待つ」という意味になる