Django

【Django×Docker】"Can't connect to MySQL server on"の原因と解決方法

環境

  • docker 20.10.8
  • docker compose 1.29.2
  • django 3.1
  • mysql 8.0

エラー内容

settings.pydocker-compose.ymlが下記設定内容の状態でdocker-compose upでコンテナを起動しようとすると、 Can't connect to MySQL server on 'db'とエラーが出る

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "sky_port",
        "USER": "username",
        "PASSWORD": "password",
        "HOST": "db",
        "PORT": "3306",
    }
}
version: "3"

services:
  db:
    container_name: db
    image: mysql:8.0
    platform: linux/x86_64
    ports:
      - 3306:3306
  web:
    container_name: web
    build: .
    command: python3 manage.py runserver 0:8000
    volumes:
      - .:/code
    ports:
      - 8000:8000
      - 8001:8001
    depends_on:
      - db

原因

depends_on は起動順は指定できるが、稼働順は指定できないため、mysql 起動直後、稼働前に django アプリケーションが起動して接続しようとしてしまっていたため

解決策

wait-for-itを利用して mysql コンテナが稼働するまで django アプリケーションコンテナの起動を待たせる 手順は以下の通りです

  1. wait-for-it.shをダウンロード
  2. 権限を変更
  3. django アプリケーション起動コマンドを修正

wait-for-it.shをダウンロード

curl -O https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh

権限を変更

chmod 755 wait-for-it.sh

django アプリケーション起動コマンドを修正

version: "3"

services:
  db:
    container_name: db
    image: mysql:8.0
    platform: linux/x86_64
    ports:
      - 3306:3306
  web:
    container_name: web
    build: .
    command: sh -c "./wait-for-it.sh db:3306; python3 manage.py runserver 0:8000" # ここ
    volumes:
      - .:/code
    ports:
      - 8000:8000
      - 8001:8001
    depends_on:
      - db

参考

-Django