LoginSignup
4

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メッセージを伴って終了

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
What you can do with signing up
4