⑨１日１０分で理解するコンテナ技術入門 - Docker Composeを使ったスケーリング -

[前回](https://qiita.com/goroneko/items/4dcd00488e47b77ac217)は、docker composeのネットワーク（dockerのネットワーク）について説明しました。今回はdocker composeを使ったコンテナのスケーリングについて紹介します。
コード->https://github.com/sogawa-yk/simple-knowledge-sharing-platform/tree/9-article
# Docker Composeを使ったスケーリング
Docker Composeでのスケールは、`docker compose up`コマンドに`--scale`オプションを付与するだけです。ですが、前回の`docker-compose.yaml`から少し修正をする必要があります。前回の`docker-compose.yaml`配下のような内容でした。
```yaml:前回のdocker-compose.yaml
version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=flask_app
    networks:
      - flask-net
    volumes_from:
      - web
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ppassword || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    build: .
    container_name: web
    ports:
      - "8080:5000"
    networks:
      - flask-net
    volumes:
      - ./uploads:/app/uploads
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DATABASE_HOST=db
      - DATABASE_USER=root
      - DATABASE_PASSWORD=password
      - DATABASE_NAME=flask_app
    restart: unless-stopped

networks:
  flask-net:
    driver: bridge

volumes:
  web-data:
    driver: local
```
この中で、`services.web.container_name`と、`services.web.ports`を少し編集します。
## services.web.container_nameの編集
ここに設定した値は、`docker compose up`コマンド実行時に起動するコンテナ（webのコンテナ）の名前になります。コンテナの名前は一意にする必要があるので、ここで名前を設定しているとスケールした際に複数のコンテナの名前が同じになってしまい、エラーになってしまいます。そのため、この項目を削除し、docker側に名前を付けてもらいます。
## services.web.portsの編集
ここに設定した値は、起動したコンテナのポートをホストのポートにポートフォワーディングします。現在はコンテナの5000番ポートをホストの8080番ポートにポートフォワーディングする設定になっています。スケールして複数のコンテナを立てる場合、この設定のままだと複数のコンテナのポートをホストの8080番ポートにフォワーディングすることになり、エラーになってしまいます。そのため、ここにはコンテナ側のポートのみを記載し、ホストのポートの割り当てはdocker側に任せます。
## 編集後のdocker-compose.yaml
編集後は以下のようになります。
```yaml:編集後のdocker-compose.yaml
version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=flask_app
    networks:
      - flask-net
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ppassword || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    build: .
    ports:
      - "5000" # コンテナ側のみ指定
    networks:
      - flask-net
    volumes:
      - ./uploads:/app/uploads
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DATABASE_HOST=db
      - DATABASE_USER=root
      - DATABASE_PASSWORD=password
      - DATABASE_NAME=flask_app
    restart: unless-stopped

networks:
  flask-net:
    driver: bridge

volumes:
  web-data:
    driver: local
```
## --scaleオプションを指定して起動
以下のコマンドでスケールします。
```bash
docker compose up -d --build --scale web=3
```
`--scale`オプションを指定し、その引数として`<サービス名>=<スケール数>`を指定します。今回、web側をスケールするので、`web=3`としています。

実行後、`docker container ps`コマンドでコンテナの状態を確認します。
```bash
docker ps
CONTAINER ID   IMAGE                                   COMMAND                  CREATED          STATUS                    PORTS                                         NAMES
63de071cd5cd   simple-knowledge-sharing-platform-web   "python app.py"          13 seconds ago   Up 2 seconds              0.0.0.0:32771->5000/tcp, :::32771->5000/tcp   simple-knowledge-sharing-platform-web-2
d78a80f85eb8   simple-knowledge-sharing-platform-web   "python app.py"          13 seconds ago   Up 2 seconds              0.0.0.0:32772->5000/tcp, :::32772->5000/tcp   simple-knowledge-sharing-platform-web-3
a7cd71d1544c   simple-knowledge-sharing-platform-web   "python app.py"          13 seconds ago   Up 2 seconds              0.0.0.0:32773->5000/tcp, :::32773->5000/tcp   simple-knowledge-sharing-platform-web-1
686747966ca0   mysql:8.0                               "docker-entrypoint.s…"   13 seconds ago   Up 13 seconds (healthy)   3306/tcp, 33060/tcp                           mysql
```
webのコンテナが3つ立ち上がっていることが分かります。それぞれ、ホスト側の32771, 32772, 32773番にポートフォワーディングされています。

実際にそれぞれのコンテナにアクセスしてみます。
それぞれ下記のように同じページが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532202/1bdc6098-70f7-5cc3-a2ab-82779284ad42.png)

ポート32771で待ち受けているコンテナ側で記事を追加してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532202/0a2a6c63-85cf-85fc-0813-7e7c0a5acc9a.png)
記事の中身は以下のような記事です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532202/98ad52e6-b942-ea5c-67c5-c5e7bf5f8aa3.png)

ポート32772で待ち受けているコンテナ側で確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532202/67f9ba95-9dcd-d795-4748-7eed6f446015.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532202/2d4f17fb-a49d-acb0-c571-4187387c87b4.png)
このように、記事を投稿したコンテナとは別のコンテナからでも記事を確認することができます。これは、どのwebコンテナでもすべて同じmysqlのコンテナを参照しているためです。

# まとめ
今回は、`docker compose`コマンドを使ったスケーリングについて紹介しました。次回は、ここまで紹介したdocker composeの機能の振り返りを行いたいと思います。