LoginSignup
9
5

More than 3 years have passed since last update.

”Docker Compose、チョットわかる”になるために知っておきたい頻出オプション - Compose file version 3(3.8) reference -

Posted at

要旨

  • 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 , リポジトリからイメージを指定できる

buildimageを併記した場合

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については勉強不足)

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 or npipe
  • source: ソースとなるhost側のpath, もしくはnamed volume, tmpfs mountには適応できない
  • target: コンテナ側のパス、どこにマウントするのか
  • volume: nocopyvolumeを作成するときにコンテナ側からデータをコピーすることを許可しない(ちょっと使い所がわからない)
  • 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 FILEenv_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メッセージを伴って終了
9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5