要旨
- dockerを使ってRailsやLaravelといったFWを使用した開発環境構築をいくつかやってみた
- その中で頻出だったオプションについて、公式ドキュメントレベルの理解をまとめてみた
この記事の内容を知ると
- なんとなく書いていた内容の理解が深まった
- より読みやすく、変更しやすい
docker-compose.yml
が書ける気がした - 他人が書いた
docker-compose.yml
を見て、"さっぱりわからん" -> "少し読める"に貢献できるかもしれません
保守のモチベーションになりますので改善コメント、LGTMお願いいたします
Reference
Docker公式ドキュメント
Compose file version 3 reference | Docker Documentation
Compose file format
2020.9.4現在 version 3.8が最新です
(Docker Engine 19.03.0+ 対応)
version: "3.8"
最新は以下で確認ください
Compose file versions and upgrading | Docker Documentation
Services
dockerイメージを実行する単位がservice
Composeではserviceごとにオプションを指定し、複数のserviceを管理実行できる
Dockerイメージのビルドに関わるオプション
build
context
Dockerfileのpathを指定する
services:
webapp:
build: ./dir
以下は上記に同じ
buildするソースをpathで指定、URLやgitレポジトリも使えるらしい
Either a path to a directory containing a Dockerfile, or a url to a git repository.
Compose file version 3 reference | Docker Documentation
services:
webapp:
build:
context: ./dir
dockerfile
Dockerfile以外の任意のファイル、ここでは./dir/Dockerfile-alternate
でbuildする場合
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args
buildプロセスでのみ使用可能な環境変数を定義する
imageのバージョンなどをdocker-compose.yml
に記述できると見通しが良くなりそう
docker-compose.yml
で定義して
build:
context: .
args:
- RUBY_VERSION="2.7.1-alpine"
Dockerfile
で呼び出す
ARG RUBY_VERSION
FROM ruby:$RUBY_VERSION
image
dockerイメージからコンテナを起動する
image name, tag, image ID , リポジトリからイメージを指定できる
build
とimage
を併記した場合
image
単独で使用する場合と挙動が異なる
./dir
のsource (Dockerfile)からbuildし、buildされたimageはwebapp
という名前になり、
tag
でタグ付けされる
build: ./dir
image: webapp:tag
別のサービスでこのイメージを再利用する場合に
Dockerfileから再ビルドする時間が短縮できて便利そう
services:
app:
build: ./dir
image: app
...
webpacker:
image: app # ここではbuildされたイメージを再利用
コンテナの起動やプロセスの実行に関わるオプション
command
dockerfileで指定したdefaultコマンドをoverrideする
command: bundle exec thin -p 3000
dockerfileのようなformatでも書ける
以下は上記と同じ
command: ["bundle", "exec", "thin", "-p", "3000"]
depends_on
-
docker-compose up
の際にdepends_on
に基づいた順でサービスをスタートさせる(db -> app) -
docker-compose up SERVICE
とした場合、depends_on
で指定したサービスも自動的に含まれる(docker-compose up app
としたときに, "db"も起動する) -
docker-compose stop
とした場合、依存関係に基づいてサービスを終了する(app -> db)
services:
app:
build: .
depends_on:
- db
db:
image: postgres
注意
-
depends_onはサービスの開始順を定義しているだけで、サービスが利用可能になるのを待っているわけではない。これには別の配慮が必要。
Control startup and shutdown order in Compose | Docker Documentation -
deploying a stack in swarm mode
ではdepends_on
の内容が無視される(deploying a stack in swarm modeについては勉強不足)
stdin_open, tty
stdin_open: true
tty: true
ボリュームとマウントに関わるオプション
tmpfs
コンテナ内に temporary file system
をマウントする
- hostのメモリ上にマウントされ高速可が期待できる
- コンテナをstopするとこのマウントは開放される
Use tmpfs mounts | Docker Documentation -
deploying a stack in swarm mode
ではこのオプションは無視される
tmpfs: /tmp
tmpfsのサイズ上限を指定できる(単位: byte)
- type: tmpfs
target: /app
tmpfs:
size: 1000
volumes
Hostのパスを指定しマウントする(コンテナから扱えるようにする)
volumesの概要
以下少し自身の解釈を書きます
- コンテナ内のデータはコンテナの停止とともに消失してしまう
- コンテナ内のデータに対して、hostや、他のコンテナはアクセスすることができない
これを解消するためにvolumeでマウントする工程が必要
volumesマウントは三種類
-
/var/lib/postgresql/data
パスだけ書いてある場合、
コンテナ内のパスを示しており、指定されたパスをボリュームとしてマウントしデータを永続化する。 -
host_path: container_path
の形式で書いてある場合、
host_pathをボリュームとしてマウントしコンテナ内で扱えるようにする - volume_name: container_pathの形式で書いてある場合、
コンテナ内のpathを名前付きボリュームとしてマウントする。名前付きボリュームは他のコンテナと共有してアクセスすることができる。
(自己解釈おわり)
Top-level optionとしてのvolumes
と、Servicesのsuboptionとしてのvolumes
- 各サービスのsub-optionsとしてパスを指定する場合、当該のサービスのみに定義される
- その場合、top-levelのvolumes keyで再度指定する必要はない
- ただし、複数のサービスでボリュームを再利用したい場合は、top-levelのvolumes keyで名前付きvolumeを使う
ちょっとわかりにくいが
そのサービスでしかそのボリュームを使わない場合
-
services
以下のオプションとして書く - path or named volumeのいずれで書いても良い
- named volumeで書くならtop-level = servicesと同列のvolumes: keyにも記述が必要
他のサービスでもそのボリュームを使う場合
- top-level = servicesと同列のvolumes: keyにnamed volumeで書こう
version: "3.8"
services:
web:
image: nginx:alpine
#services のサブオプションとしてのvolumes key (新書式 Added in version 3.2 file format.)
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
db:
image: postgres:latest
volumes:
#pathで書くならtop-levelのvolumes:に書かなくて良い (旧書式)
- "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
#"dbdata"はdbしか使っていないが、named volumeはtop-levelのvolumes:に書く
- "dbdata:/var/lib/postgresql/data"
volumes: #top-levelのvolumes
mydata:
dbdata:
SHORT SYNTAX(従来の書式)
- [SOURCE:]TARGET[:MODE]で記述
- 相対パス、絶対パスでどちらも指定可
- 相対パスは
docker-compose.yml
に対しての相対パスで指定
volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql
# Specify an absolute path mapping
- /opt/data:/var/lib/mysql
# Path on the host, relative to the Compose file
- ./cache:/tmp/cache
# User-relative path
- ~/configs:/etc/configs/:ro
# Named volume
- datavolume:/var/lib/mysql
LONG SYNTAX(Added in version 3.2 file format.)
version: "3.8"
services:
web:
image: nginx:alpine
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
volumes:
mydata:
-
type
: マウントするタイプvolume
,bind
,tmpfs
ornpipe
-
source
: ソースとなるhost側のpath, もしくはnamed volume, tmpfs mountには適応できない -
target
: コンテナ側のパス、どこにマウントするのか -
volume: nocopy
volumeを作成するときにコンテナ側からデータをコピーすることを許可しない(ちょっと使い所がわからない) -
tmpfs: size
: tmpfs mountのサイズを指定 (bytes) -
consistency
: 後述
consistency
host - container間の同期性を犠牲にして、ボリュームマウントのパフォーマンスを向上させる
(Docker Desktop for Macでのみ適応される)
-
consistent
: defaultではこれ。host - container間は完全に一致。 -
cached
: host側の変更をコンテナから見たときに同期に遅延が生じうる -
delegated
: コンテナ側の変更をhostから見て同期に遅延が生じうる
cachedはよく使っていますが、いまのところ問題になるような同期のズレはない
version: "3.8"
services:
php:
image: php:7.1-fpm
volumes:
- .:/var/www/project:cached
ネットワークに関わるオプション
expose
サービス間でのポート開放を定義、host - コンテナ間ではない
expose:
- "3000"
- "8000"
ports
host - container間でポートマッピングする
-
HOST:CONTAINER
の書式で書く - もしくはコンテナ内のポートだけ記述する(この場合exposeと同じ?コンテナの外からアクセスできないことは確認しました)
- HOST側のポートは60より小さくできない
ports:
- "3000"
- "8000:8000"
- "127.0.0.1:80:80"
環境変数に関わるオプション
env_file
- fileから環境変数を追加する
-
docker-compose -f FILE
でenv_file
を指定することも可能 -
env file
の中身はVAR=VAL
(変数名=値)で記述
env_file: .env
複数ファイルも可
呼び出し順に注意、変数名が重複している場合最後に呼び出されたものを採用
env_file:
- ./common.env
- ./apps/web.env
environment
docker-compose.yml
に直接環境変数を定義できる
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
以下上記に同じ
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
SESSION_SECRET:
のようにkeyのみが指定されている場合、host側の環境変数を値として採用する
Environment variables with only a key are resolved to their values on the machine Compose is running on, which can be helpful for secret or host-specific values.Compose file version 3 reference | Docker Documentation
Note
ここで定義する環境変数はbuild中は使用できない。buildプロセスで環境変数を使用したい場合は上述の"arg"オプションを使用する
環境変数について補足
composeではdocker-composeが動いているシェルの環境変数が使える
POSTGRES_VERSION=9.3
が定義されているならば
以下のように呼び出せる
書式は$VARIABLE
と ${VARIABLE}
どちらでも可
db:
image: "postgres:${POSTGRES_VERSION}"
この例でPOSTGRES_VERSIONが定義されていない場合
${POSTGRES_VERSION}は空、Copmoseから見るとimage: "postgres:"
になるので注意
.env
に記述することで環境変数のデフォルト値を指定する事ができる
Composeは自動的に.env
を参照し、シェルに環境変数が定義される場合はそれが優先される。
インラインでデフォルト値を指定することも可能(added in 2.1 file format)
-
${VARIABLE:-default}
:VARIABLE
が未定義、もしくは空ならばdefault
を採用 -
${VARIABLE-default}
:VARIABLE
が未定義ならばdefault
を採用
Similarly, the following syntax allows you to specify mandatory variables:
-
${VARIABLE:?err}
:VARIABLE
が未定義、もしくは空ならばerr
メッセージを伴って終了 -
${VARIABLE?err}
:VARIABLE
が未定義ならばerr
メッセージを伴って終了