Skip to content
Dockerワークショップパート7: Docker Compose を使用する

Docker Compose を使用する

Docker Compose は、マルチコンテナアプリケーションを定義して共有するのに役立つツールです。Composeを使えば、サービスを定義するYAMLファイルを作成し、1つのコマンドでアプリケーション全体を立ち上げたり、終了させたりできます。

Composeを使う大きなメリットは、アプリケーションスタックをファイルで定義し、それをプロジェクトリポジトリのルートに置いてバージョン管理できることです。これにより、他の人がプロジェクトに簡単に参加できるようになります。誰かがリポジトリをクローンして、Composeを使ってアプリケーションを起動するだけで済むようになります。実際、多くのプロジェクトがGitHubやGitLabでこの方法を採用しています。

Composeファイルを作成する

getting-started-app ディレクトリ内に、compose.yaml というファイルを作成します。

├── getting-started-app/
│ ├── Dockerfile
│ ├── compose.yaml
│ ├── node_modules/
│ ├── package.json
│ ├── spec/
│ ├── src/
│ └── yarn.lock

アプリサービスを定義する

パート6 では、次のコマンドを使ってアプリケーションサービスを起動しました。

$ docker run -dp 127.0.0.1:3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:18-alpine \
  sh -c "yarn install && yarn run dev"

これを compose.yaml ファイルでサービスとして定義します。

  1. テキストエディタやコードエディタで compose.yaml を開き、実行する最初のサービス(またはコンテナ)の名前とイメージを定義します。名前は自動的にネットワークエイリアスとなるため、MySQLサービスを定義するときに役立ちます。

    services:
      app:
        image: node:18-alpine
  2. 通常、commandimage 定義の近くに置かれますが、順序に決まりはありません。compose.yaml ファイルに command を追加します。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
  3. 次に、-p 127.0.0.1:3000:3000 の部分を ports を使って定義します。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
  4. 続いて、作業ディレクトリ (-w /app) とボリュームマッピング (-v "$(pwd):/app") を working_dirvolumes で定義します。

    Docker Composeのボリューム定義の利点の1つは、現在のディレクトリから相対パスを使用できることです。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
  5. 最後に、環境変数定義を environment キーを使って移行します。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: secret
          MYSQL_DB: todos

MySQLサービスを定義する

次に、MySQLサービスを定義します。このコンテナで使用したコマンドは次の通りです。

$ docker run -d \
  --network todo-app --network-alias mysql \
  -v todo-mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=todos \
  mysql:8.0
  1. 新しいサービスを定義し、名前を mysql にして自動的にネットワークエイリアスを取得します。また、使用するイメージも指定します。

     
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
  2. 次にボリュームマッピングを定義します。docker run を使用してコンテナを実行したとき、Dockerは自動的に名前付きボリュームを作成しましたが、Composeで実行する場合にはそれが自動的には行われません。トップレベルの volumes: セクションでボリュームを定義し、サービス設定でマウントポイントを指定する必要があります。ボリューム名だけを指定すると、デフォルトのオプションが使用されます。

    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
     
    volumes:
      todo-mysql-data:
  3. 最後に、環境変数を指定します。

    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: secret
          MYSQL_DATABASE: todos
     
    volumes:
      todo-mysql-data:

ここで、compose.yaml 全体は次のようになります。

services:
  app:
    image: node:18-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 127.0.0.1:3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos
 
  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos
 
volumes:
  todo-mysql-data:

アプリケーションスタックを実行する

compose.yaml ファイルができたので、アプリケーションを起動できます。

  1. 最初に、他のコンテナが実行されていないことを確認してください。docker ps を使ってコンテナを一覧表示し、docker rm -f <ids> で削除します。

  2. docker compose up コマンドを使ってアプリケーションスタックを起動します。-d フラグを追加してバックグラウンドで実行します。

    $ docker compose up -d

    コマンドを実行すると、以下のような出力が表示されます。

    Creating network "app_default" with the default driver
    Creating volume "app_todo-mysql-data" with default driver
    Creating app_app_1   ... done
    Creating app_mysql_1 ... done

    Docker Composeがボリュームやネットワークを作成していることに注目してください。デフォルトでは、Docker Composeはアプリケーションスタック専用のネットワークを自動的に作成します(Composeファイルでネットワークを定義しなかったのはこのためです)。

  3. docker compose logs -f コマンドを使ってログを確認します。各サービスからのログが1つのストリームに交互に表示されます。タイミングに関連する問題を監視する場合に非常に便利です。-f フラグはログをフォローするため、生成されるとすぐにライブ出力が得られます。

    コマンドを実行すると、以下のような出力が表示されます。

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000

    行の先頭にサービス名が表示されており、(色分けされている場合があります)メッセージを区別しやすくなっています。特定のサービスのログだけを表示したい場合は、docker compose logs -f app のように、ログコマンドの末尾にサービス名を追加します。

  4. この時点で、http://localhost:3000 でアプリケーションを開き、動作を確認できるはずです。

Docker Dashboardでアプリスタックを確認する

Docker Dashboardを見ると、getting-started-app という名前のグループがあることがわかります。これはDocker Composeからのプロジェクト名で、コンテナをグループ化するために使用されます。デフォルトでは、プロジェクト名は compose.yaml が存在するディレクトリの名前になります。

スタックを展開すると、Composeファイルで定義した2つのコンテナが表示されます。名前も少し説明的になり、<サービス名>-<レプリカ番号> というパターンに従っています。これにより、どのコンテナがアプリで、どのコンテナがMySQLデータベースかをすぐに見分けることができます。

すべてを削除する

すべてを削除する準備ができたら、単に docker compose down コマンドを実行するか、Docker Dashboardでアプリ全体のゴミ箱アイコンをクリックします。コンテナは停止し、ネットワークが削除されます。

警告

デフォルトでは、Composeファイルに記載された名前付きボリュームは、docker compose down コマンドを実行しても削除されません。ボリュームを削除したい場合は、--volumes フラグを追加する必要があります。

Docker Dashboardでアプリスタックを削除しても、ボリュームは削除されません。

まとめ

このセクションでは、Docker Composeについて学び、マルチサービスアプリケーションを定義し、共有する方法を簡単にする方法を学びました。

関連情報:

次のステップ

次は、Dockerfileを改善するためのベストプラクティスについて学びます。