AI can fly !!

AI がやりたい Web エンジニアのアウトプット (AI の知識は無い)

【Docker】初心者のための Docker Compose まとめ

docker-logo

はじめに

2021 年現在、本番環境や開発環境を問わず Docker (コンテナ技術) は当たり前のものとして使用されるようになりました。

いちエンジニアの立場としても、開発環境をコンテナでスピーディに構築するだけでなく、ちょっとしたお試し環境を用意したいときなど、手軽に環境を Scrap and build できる Docker はもはや無くてはならない存在です。

Docker Compose の詳細については Docker 公式ドキュメントの Docker Compose のページ を参照いただくとして、当記事では Docker 初心者が Docker Compose を使用するにあたり、よく使うんだけどまだちゃんと覚えていない…というような内容をまとめました。

当記事でゼロから Docker Compose を学ぶということではなく、 Docker Compose を一通り学んだ初心者がリファレンス的に使用することを想定しています。

慣れてしまえば難しいことはありませんが、そもそも Docker とは、コンテナ技術とは、という部分が不安な方は Docker 公式ドキュメント を一読することをお勧めします。

ただし、 Docker 公式ドキュメントを一読したなら、そもそもこの記事を読む必要は無いと思いますけどね…

動作環境

OS Version
Ubuntu 20.04 LTS

Windows 10 Pro の Windows Subsystem for Linux (WSL 2) を使用

Docker Products Version
Docker Desktop for Windows 3.5.2
Docker Engine 20.10.7
Docker Compose 1.29.2

Docker Compose まとめ

前述した通り、 Docker Compose についての詳細は Docker 公式ドキュメントをご参照ください。

docs.docker.com

ざっくりと超訳すれば、 Docker Compose は複数のコンテナをまとめて定義・管理することができる Docker のためのツールです。

Compose ファイル (docker-compose.yml)

version: '3.8'

services:
  [service_name]:
    build: [context_path]
    image: [image_name]:[tag_name]
    container_name: [container_name]
    command: [command]
    environment:
      [variable_name]: [value]
    volumes:
      - [volume_name]:[container_directory_path]:[mode]
      - [host_directory_path]:[container_directory_path]:[mode]
      - type: volume
        source: [volume_name]
        target: [container_directory_path]
      - type: bind
        source: [host_directory_path]
        target: [container_directory_path]
    networks:
      - [network_name]
    ports:
      - '[host_port]:[container_port]'
    tty: [boolean]
    restart: [restart_policy]
    depends_on:
      - [other_service_name]
  [other_service_name]:
    ...

volumes:
  [volume_name]:

networks:
  [network_name]:

Compose ファイルには、 Docker Compose で実行する Docker アプリケーションの設定を定義します。

ファイルは YAML 形式で記述しますが、 JSON 形式でも記述可能です。

コンテナ (services) だけでなく、各コンテナ間のネットワーク (networks) やボリューム (volumes) についても定義でき、各セクションの設定項目は多岐にわたります。

ここでは、 (僕が) よく使用する項目を中心に記載しました。

version (Compose ファイルフォーマットのバージョン)

version: "3.8"

Compose ファイルフォーマットのバージョンを指定します。

使用する Docker Engine のバージョン毎にサポートされる Compose ファイルフォーマットのバージョンが異なるので、 Docker Engine のバージョンに合わせて Compose ファイルのバージョンを指定する必要があります。

以下はその一例です。

Compose file format Docker Engine release
3.8 19.03.0+
3.7 18.06.0+
3.0 1.13.0+

※ 注意点として、 Compose ファイルのバージョンを指定する場合は、メジャーバージョンとマイナーバージョンの両方を明示的に記述 (version: "3.8") する必要があります。 もしメジャーバージョンのみを記述した場合、マイナーバージョンは最新バージョンではなくデフォルトの 0 が補完されます。 (version: "3.0")

docs.docker.com

services セクション

services:

サービス (コンテナ) を定義します。

services セクション直下に複数のサービスを列記することができます。

[service_name] (サービス名)

  [service_name]:

  # e.g.
  web:

サービスの名前を指定します。

後述する buildimage で構築される Docker イメージに名前を付けていない場合、構築されるイメージ名は [project_name]_[service_name] になります。

プロジェクト名 (project_name) が特に指定されていない場合は、 Compose ファイルが配置されているディレクトリ名がプロジェクト名になります。

build (Dockerfile)
    build: [context_path]

    # e.g.
    build: .

build の指定方法の一つとして、 Dockerfile を含むディレクトリのパスを指定します。

Dockerfile のファイル名やビルド引数などの詳細を指定する方法もありますが、今回は割愛します。

後述する image を指定することで、構築される Docker イメージに名前を付けることができます。

Dockerfile については 別記事 にまとめていますので、そちらをご覧ください。

ai-can-fly.hateblo.jp

image (Docker イメージ名)
    image: [image_name]:[tag_name]

    # e.g.
    image: python-flask:latest

コンテナで起動する Docker イメージを指定します。

前述の build が指定されている場合は、 build で指定された Dockerfile から Docker イメージが構築され、そのイメージ名が image で指定した名前になります。

build を指定しない (Dockerfile からイメージを構築しない) 場合、ここで指定された Docker イメージからコンテナを作成しますが、指定した Docker イメージがローカルに存在しない場合は、 Docker Hub から Pull (取得) した上でコンテナが作成されます。

container_name (Docker コンテナ名)
    container_name: [container_name]

    # e.g.
    container_name: python-flask

構築された Docker イメージから作成されるコンテナの名前を指定します。

command (コマンド)
    command: [command]

    # e.g.
    command: flask run

Docker Compose でコンテナを開始する際に実行されるコマンドを指定します。

build セクションや image セクションの Dockerfile や Docker イメージで定義されている CMD に代わり、ここで指定したコマンドが実行されます。

environment (環境変数)
    environment:
      [variable_name]: [value]

    # e.g.
    environment:
      FLASK_ENV: development
      SECRET_KEY

コンテナで使用する環境変数を指定します。

環境変数名のみを指定した場合、 Docker Compose が起動しているシェルで定義されている同名の環境変数がコンテナへ渡されます。

注意点として、 build セクションで Dockerfile をビルドする際はここで指定した環境変数は使用できません。

ビルド時の環境変数build セクションのサブセクションである args セクションで指定します。

volumes (ボリューム)
    volumes:
      - [volume_name]:[container_directory_path]:[mode]
      - [host_directory_path]:[container_directory_path]:[mode]
      - type: volume
        source: [volume_name]
        target: [container_directory_path]
      - type: bind
        source: [host_directory_path]
        target: [container_directory_path]

    # e.g.
    volumes:
      - ./src:/src:rw

コンテナで使用するボリュームを指定します。

ボリュームの指定には、 type (ボリュームのマウント種類) などを省略して一行で書く方法と、詳細を複数行にわたって細かく指定する二通りの書き方があります。

type source target
volume volumes セクションで定義した名前付きボリューム ([volume_name]) を指定 ボリュームがマウントされるコンテナのパス ([container_directory_path]) を指定
bind ホストマシンのパス ([host_directory_path]) を指定 ボリュームがマウントされるコンテナのパス ([container_directory_path]) を指定
tmpfs - ボリュームがマウントされるコンテナのパス ([container_directory_path]) を指定

bind で指定するホストマシンのパス ([host_directory_path]) には、 Compose ファイルからの相対パス (./) やユーザのホームディレクトリからの相対パス (~/) が指定できます。

コンテナのパス ([container_directory_path]) に Docker イメージに存在しないディレクトリを指定した場合、自動的に当該ディレクトリ (親パス含む) が作成され、ボリュームがマウントされます。

一行で指定する場合の mode には、読み取り専用の ro と読み書き可の rw が指定でき、省略時のデフォルトは rw になります。

Bind mounts の注意点

マウントするホスト側のディレクトリとマウントされるコンテナ側のディレクトリのいずれかが空でない場合、ホスト側のディレクトリが優先されることになります。

Host side directory Container side directory Mounted result
空になる
空でない ホスト側のディレクトリ内のデータがマウントされる
空でない 空になる
空でない 空でない ホスト側のディレクトリ内のデータがマウントされる

簡単に言ってしまえば、一部の例外的な Docker イメージを除き、常にホスト側のディレクトリでコンテナ側のディレクトリが置き換わります。

これはディレクトリの統合 (merge) ではないため、たとえホスト側のディレクトリが空であっても、コンテナ側のディレクトリ内のファイル有無に関わらず、結果としてコンテナ内のマウント先ディレクトリは空になります。

誤ってマウント先のファイルを消してしまうことがないように注意しましょう。

ただ、間違った設定をしてしまったとしても、 Compose ファイルを修正して再度コンテナを作成すれば問題ありません。

これも Scrap and build が容易な Docker の良いところです。

networks (ネットワーク)
    networks:
      - [network_name]

コンテナが接続するネットワークを指定します。

後述する最上位の networks セクションで定義したネットワークを指定することで、明示的にコンテナが接続するネットワークを選択できます。

独自のネットワーク設定を行わなかった場合、コンテナは既定のネットワーク ([project_name]_default) に接続され、各サービスのコンテナ間は [service_name] をホスト名としてアクセスすることができます。

ports (ポート)
    ports:
      - "[host_port]:[container_port]"

    # e.g.
    ports:
      - "5000:5000"

ホスト側ポートとコンテナ側ポートのマッピングを指定します。

コンテナ側のポート番号のみを指定した場合、ホスト側のポート番号は空ポートが自動的に割り当てられます。

注意点として、設定にもよりますが、コンテナ内で起動した開発サーバなどが localhost (127.0.0.1) からの接続のみを許可している場合、ホスト側から localhost (127.0.0.1) で接続することができないことがあります。

これはホスト側からポートフォワードされた際、 localhost (127.0.0.1) がコンテナ内の OS の IP アドレスに変換され、外部 (localhost (127.0.0.1) 以外) からのアクセスと判断されてしまうためで、解決策としてコンテナ内で起動するサーバへのアクセス制限を無くす必要があります。

tty (疑似 TTY)
    tty: [boolean]

疑似 TTY の割り当てを指定します。

true を指定すると、コンテナを開始時に疑似 TTY が割り当てられます。

restart (サービス再起動ポリシー)
    restart: [restart_policy]

サービスの再起動ポリシーを指定します。

ここでは、 Docker を起動した際にコンテナを自動的に開始するかどうかを制御することができます。

Restart policies Description
"no" 自動でコンテナを開始しない (既定値)
always 常にコンテナを開始する
on-failure エラー発生によりコンテナが終了した場合、コンテナを開始する
unless-stopped コンテナを手動等で停止した場合を除き、常にコンテナを開始する

いずれの場合も、手動でコンテナを停止した直後にコンテナが再起動することはありません。

alwaysunless-stopped の違いは、手動でコンテナを停止した後、 Docker の (再) 起動時にコンテナが自動的に開始されるかどうかになります。

depends_on (サービス間の依存関係)
    depends_on:
      - [other_service_name]

サービス間の依存関係を定義します。

ここで他サービスを指定した場合、 docker-compose up コマンドによるコンテナの開始時、依存する他サービス ([other_service_name]) のコンテナを開始してから当サービス ([service_name]) のコンテナを開始します。

また、 docker-compose stop コマンドによるコンテナの停止時も、依存する他サービスのコンテナが停止してから当サービスのコンテナを停止します。

volumes セクション

volumes:
  [volume_name]:

サービスで使用するボリュームを定義します。

volumes セクション直下に列記した名前付きボリュームは、前述した services セクションの各サービスの volumes に指定して使用できます。

詳細な設定については、今回は割愛します。

networks セクション

networks:
  [network_name]:

サービスで使用するネットワークを定義します。

networks セクション直下に列記したネットワークは、前述した services セクションの各サービスの network に指定して使用できます。

詳細な設定については、今回は割愛します。

Docker Compose CLI

docker-compose [options] [command] [arguments]

Compose ファイルに定義された複数のサービスは、 docker-compose コマンドで一括、または個別に操作することができます。

既定ではカレントディレクトリにある docker-compose.yml を Compose ファイルとして使用しますが、以下の -f オプションを使用すれば、任意の場所にある Compose ファイルを指定することができます。

Options Description Example
-f [compose file] 任意の Compose ファイルを指定。 -f ./others/docker-compose-sub.yml
--compatibility 各サービスの deploy セクションの内容を読み取り、 Compose ファイルのバージョン 2 のパラメータとして変換・実行する。 --compatibility

build (イメージ構築)

docker-compose build [options] [service]

Compose ファイルに定義された各サービスの Docker イメージを構築します。

サービスの Dockerfile やイメージ構築時のディレクトリ構成・内容を変更した場合は、 docker-compose build コマンドでイメージを再構築する必要があります。

Options Description
--no-cache イメージ構築時に、イメージのキャッシュを使用しない。

run (コンテナを開始してコマンド実行)

docker-compose run [option] [service] [command] [arguments]

Compose ファイルに定義されたサービスのコンテナを開始し、開始したコンテナ内でコマンドを実行します。

run サブコマンドではサービスの指定は必須です。

イメージが存在しない場合は、合わせて構築されます。

オプションを指定しない場合、デフォルトでは以下の動作となります。

  • Compose ファイルのサービスで定義されたコマンドを実行するが、 run コマンドで実行するコマンドを指定した場合、コンテナ内で実行されるコマンドを上書きすることが可能
  • Compose ファイルのサービスで定義されたポートを作成しない
  • 疑似ターミナル (TTY) が割り当てられる
Options Description Example
--name 開始するコンテナに名前を設定。 --name container_name
-d コンテナをバックグラウンドで実行。 -d
--rm コンテナを実行後に削除。バックグラウンドで実行した場合は無視される。 --rm
--service-ports Compose ファイルで定義したポートを作成。 --service-ports
-p, --publish コンテナのポートをホストへ公開。 -p 8080:80
-T 疑似ターミナル (TTY) を割り当てしない。 -T

start (コンテナ開始)

docker-compose start [service]

サービスのコンテナを開始します。

stop (コンテナ停止)

docker-compose stop [service]

稼働中のサービスのコンテナを削除せずに停止します。

停止したサービスのコンテナは、 start コマンドで再度開始できます。

restart (コンテナ再起動)

docker-compose restart [service]

停止中・実行中にかかわらず、 Compose ファイルで定義されたサービスのコンテナすべてを再起動します。

注意点として、 Compose ファイルを変更して restart コマンドを実行しても、変更内容はコンテナには反映されません。

rm (コンテナ削除)

docker-compose rm [option] [service]

Compose ファイルで定義された停止中のサービスのコンテナを削除します。

デフォルトでは、コンテナにアタッチした匿名ボリュームは削除されません。

Options Description
-v コンテナにアタッチした匿名ボリュームを削除。

up (イメージ構築、コンテナ作成・開始・アタッチ)

docker-compose up [option] [service]

Compose ファイルで定義されたサービスのイメージの構築、コンテナの作成・開始・アタッチを行います。

もし、既に存在するコンテナのサービスの設定やイメージが変更されていた場合、設定を反映するためにコンテナの停止・再作成が行われます。

Options Description
-d コンテナをバックグラウンドで実行。
--force-recreate Compose ファイルや使用されるイメージに変更が無くても、コンテナを再作成。
--no-recreate コンテナが存在する場合、再作成しない。
--no-build イメージを構築しない。イメージが存在しない場合はエラー。
--build イメージを構築後、コンテナを開始。イメージに変更があれば、コンテナは再作成される。
--no-start コンテナを開始しない。

down (コンテナ停止・削除)

docker-compose down [options]

Compose ファイルで定義されたサービスのコンテナを停止し、 up コマンドで作成されたイメージ・コンテナ・ネットワーク・ボリュームを削除します。

オプションを指定しなければ、デフォルトで削除されるのは以下のコンテナとネットワークのみです。

  • Compose ファイルで定義されたサービスのコンテナ
  • Compose ファイルの network セクションで定義されたネットワーク
  • default ネットワーク(使用している場合のみ)
Options Description Example
--rmi [type] イメージを削除。 type に all を指定するとすべてのイメージを、 local を指定すると image フィールドにカスタムタグのないイメージだけを削除します。 --rmi all
-v, --volumes volumes セクションの名前付きボリューム、および、コンテナにアタッチした匿名ボリュームを削除。 -v

exec (稼働中のコンテナでコマンド実行)

docker-compose exec [options] [service] [command] [arguments]

Compose ファイルで定義されたサービスの稼働中のコンテナ内で、指定したコマンドを実行します。

コンテナが開始していない場合は、コマンドは実行されません。

exec サブコマンドではサービスの指定は必須です。

オプションを指定しない場合、デフォルトでは疑似ターミナル (TTY) が割り当てられます。

Options Description Example
-d, --detach コマンドをバックグラウンドで実行。 -d
-T 疑似ターミナル (TTY) を割り当てしない。 -T
-e, --env 環境変数を設定。 -e KEY=value
-w, --workdir コマンドを実行するディレクトリを指定。 -w /path/to/workdir

ps (コンテナ一覧表示)

docker-compose ps [options] [service]

Compose ファイルで定義されたサービスのコンテナを一覧表示します。

オプションを指定しなければ、デフォルトで表示されるのは稼働中のコンテナのみです。

Options Description
-q, --quiet コンテナ ID のみを表示。
--services コンテナのサービス名を表示。
-a, --all 停止中のコンテナを含んだすべてのコンテナを表示。

logs (ログ表示)

docker-compose logs [options] [service]

Compose ファイルで定義されたサービスのログを表示します。

Options Description
-f, --follow ログを出力し続けます。ログ出力の停止は Ctrl + C で行います。
-t, --timestamps ログにタイムスタンプを出力します。

おわりに

とりあえず Docker Compose を使用するだけなら今回まとめた内容で事足りると思いますが、 Docker Compose は Dockerfile ほどではないにせよ奥が深く、より効率良く運用するためには Docker 公式ドキュメント をしっかり理解する必要があります。

また、 Docker が登場してから既に 8 年以上が経過し、その間、既に非推奨になった内容や新たに追加された仕様も複数存在します。

今回は Docker 公式ドキュメントを参考にしつつ 2021 年 8 月現在の最新情報でまとめたつもりなので、これから Docker Compose を本格的に使用しようと考えている方は、いったんここで最低限必要な内容を押さえ、あとは使いながら深い内容をキャッチアップしていっていただければと思います。

と、これまでさも知っている風に色々書いてきましたが、僕が Docker を使い始めたのは今年からになります。

はい、僕も完全に初心者ですね。イキりました。すいません _(┐「ε¦)_