【はじめてのwebアプリ開発】DockerでDBコンテナのヘルスチェック後にアプリコンテナを起動する

## はじめに

docker-composeで依存関係にあるコンテナでヘルスチェックを行うことで、コンテナの実行タイミングを制御する設定を行いました。

## 実現したいこと

docker-composeを使用してDBコンテナとアプリコンテナを起動しています。（[過去記事](https://qiita.com/mei2678/items/ebf2b3311965eb649a93)）

`depends_on`　でDBコンテナ起動後にアプリコンテナが起動するようにしたいのですが、下記の記述では、DBコンテナのサービスの準備が整う前にアプリが起動してしまい、

`jango.db.utils.OperationalError: (2002, "Can't connect to MySQL server on 'db' (115)”` というエラーになることがありました。

```yaml
version: '3.9'
services:
  db:
    container_name: mysql
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u $$MYSQL_ROOT_USER -p$$MYSQL_ROOT_PASSWORD || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    volumes:
      - db_data:/var/lib/mysql

  django:
    container_name: django
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_ROOT_USER: ${MYSQL_ROOT_USER}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      db:
        condition: service_healthy

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    platform: linux/amd64
    depends_on:
      db:
        condition: service_healthy
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_ROOT_USER: ${MYSQL_ROOT_USER}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    ports:
      - "3000:80"
    volumes:
      - ./phpmyadmin/sessions:/sessions

volumes:
  db_data:
```

## 結論

dbコンテナでヘルスチェックを実施し、ヘルスチェックの結果が正常であることを確認してから起動するよう `depends_on` を修正しました。

```yaml
version: '3.9'
services:
  db:
    container_name: mysql
    image: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    healthcheck: #追加
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u $$MYSQL_ROOT_USER -p$$MYSQL_ROOT_PASSWORD || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    volumes:
      - db_data:/var/lib/mysql

  django:
    container_name: django
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_ROOT_USER: ${MYSQL_ROOT_USER}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      db:
        condition: service_healthy #追加

volumes:
  db_data:
```

下記のようにDBコンテナのヘルスチェック実施後にアプリコンテナを実行するようになりました！
![スクリーンショット 2023-09-13 20.33.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219028/477e855f-0ec2-65ce-678a-e835b8382b0c.png)


## 参考サイト

[Docker の healthcheck を初めて使った話](https://zenn.dev/sun_asterisk/articles/b4b17681d08018)
[docker-compose の depends_on と healthcheck について](https://tech.actindi.net/2022/02/21/083000)