まくまくDockerノート
Docker Compose の基本 (Hello World)
2022-07-03

Docker Compose とは

Docker Compose (docker compose) を使うと、複数の Docker コンテナをまとめてコントロールすることができます。 各コンテナの起動時に必要となるパラメーターや連携方法を docker-compose.yml という YAML ファイルにまとめて記述できるため、すべてのコンテナの起動を docker compose up というシンプルなコマンドで行うことができます。

Docker Compose は複数のコンテナをコントロールすることを想定していますが、単一のコンテナを起動するときにも便利です。 例えば、Dockerfile を使ったイメージビルド、ポート番号のマッピング、ネットワークの定義などを docker-compose.yml で定義しておいて、docker compose up コマンド一発で実行できます。

docker-compose.yml の中では環境変数の値を参照(${APP_PORT} など)できるため、環境ごとに異なる値をハードコードしなくて済みます。 また、docker compose up コマンドは、環境変数を定義した .env ファイルを自動的に読み込んでくれます。

単一のコンテナを起動してみる

Docker Compose で簡単な nginx サーバーを立ち上げてみます。 Docker Compose は、デフォルトで カレントディレクトリ名をプロジェクト名として使用します-p オプションで任意のプロジェクト名を付けることもできます)。 ここでは、myproject というディレクトリを作って、その中に Compose ファイル (docker-compose.yml) を配置することにします。

$ mkdir myproject
$ cd myproject

次のようなシンプルな Compose ファイルを作成します。

docker-compose.yml

services:
  web:
    image: nginx
    ports:
      - "80:80"

各サービス(コンテナ)の定義は、services プロパティの下に記述していきます。 この例では、web という名前のサービスを 1 つだけ定義しており、その下の image プロパティで nginx のイメージを使うよう指示しています。 さらに、ports プロパティで、ホストの 80 番ポートへのアクセスをコンテナの 80 番ポートへ転送しています。 この定義で生成されるコンテナの名前は web ではなく、プロジェクト名や連番が付加された myproject-web-1 という名前になります。

Compose ファイル (docker-compose.yml) のあるディレクトリで docker compose up コマンドを実行すると、コンテナを作成&起動できます。

$ docker compose up

停止したいときは、Ctrl-C を入力するとすべてのコンテナが停止します(今回は 1 コンテナだけですが)。 初回起動時には、nginx のイメージなどがダウンロードされるため少し時間がかかりますが、しばらくすると myproject-web-1 コンテナが起動し、http://localhost/(あるいは http://127.0.0.1/)で Web ページにアクセスできるようになります。

別のターミナル(端末)を開いて次のように実行すると、myproject-web-1 というコンテナが起動していることを確認できます。

$ docker container ls
CONTAINER ID  IMAGE  COMMAND                 CREATED         STATUS        PORTS               NAMES
cf2aa5a2b831  nginx  "/docker-entrypoint.…"  10 minutes ago  Up 5 minutes  0.0.0.0:80->80/tcp  myproject-web-1

応用

Dockerfile からイメージをビルドする

独自の Dockerfile を使ってイメージを構築してコンテナを起動したいときは、サービスの定義の中で image プロパティの代わりに build プロパティを使用します。 設定する値は、Dockerfile があるディレクトリのパスです。 次の docker-compose.yml は、カレントディレクトリ (.) にある Dockerfile を使ってイメージをビルドし、コンテナを起動します。

services:
  web:
    build: .
    ports:
      - "3000:3000"

複数のコンテナを起動する

services プロパティ以下には、複数のサービスを定義することができます。 次の docker-compose.yml では、webredis の 2 つのサービスを定義しています。

services:
  web:
    build: .
    ports:
      - "3000:3000"
  redis:
    image: "redis:alpine"

web サービスは独自の Dockerfile からイメージをビルドし、redis サービスは Docker Hub レジストリ上の redis:alpine イメージを使うよう指定しています。 redis サービスは同一の Docker ネットワーク内にある web サービスから参照できればよいので、ports プロパティによるポート転送設定は必要ありません。

docker compose up を実行すると、次のような名前の 2 つのコンテナが起動します。

  • <PROJECT-NAME>-web-1
  • <PROJECT-NAME>-redis-1

ひとつの Compose ファイルで定義したサービスは同一の Docker ネットワーク(例: myproject_default)に配置されるため、それぞれのコンテナは互いにコンテナ名で参照することができます。 上記の例でいうと、web サービスの中では、redis というホスト名で Redis サービスを参照できます。 Web アプリの実装の中から、Redis コンテナに割り当てられた IP アドレスを意識しなくて済みます(逆に言うと、変化しやすい IP アドレスをもとに通信すべきではありません)。

2022-07-03