LoginSignup
1
0

Docker ComposeでDjango + MySQLが動作しない問題【healthcheck】

Last updated at Posted at 2024-04-30

はじめに

最近,研究の一環でWebアプリを作ることになりました.ところが経験不足が故にかなり詰まった箇所があったので,この記事が同じようにこれから頑張ろうという方の参考になれば幸いです.

TL; DR

  • Djangoのエラー
    • django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'mysql:3306' (111)")
    • MySQLは正常に起動
  • 対処方法
    • healthcheckの導入

環境

今回,Webアプリのために使用したフレームワークはDjango + Vue.jsで,DBにMySQLを使用しています.また,この実行のために,Docker Composeを使用しています.

failed_docker_compose
version: '3'

services:
  vuejs:
    ~~~
    depends_on:
      - mysql 
    networks:
      - app_net

  django:
    container_name: django
    build:
      context: ./django
      dockerfile: Dockerfile.django
    ports:
      - 127.0.0.1:18000:8000
    tty: true
    volumes:
      - ./django/src:/app
    command: python manage.py runserver 0.0.0.0:8000
    depends_on:
      - mysql
    networks:
      - app_net

  mysql:
    image: mysql:8.3
    ~~~
    networks:
      - app_net

networks:
  app_net:
    name: app_net
    driver: bridge

症状

今回遭遇した症状を箇条書きで示します.

  • docker compose upを実行しても,Djangoが無事に動作する時としない時がある
    • エラーメッセージはdjango.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'mysql:3306' (111)")
  • 上記のエラーメッセージで検索すると以下の2点に異常があるらしい
    • DjangoのDB設定
    • MySQLの起動

DjangoのDB設定にも,MySQLの起動・設定にも異常がないことを確認したものの改善せず……

結論

色々と試したのですが,それらは他の記事様にお任せするとして,今回の症状への対処法は,Docker Composeのhealthcheckを使用する,というものでした.

今回の症状は,直接的には,MySQLが立ち上がる前にDjangoが起動してしまったことが原因のようです.浅薄な理解でdepends_onを使えば良いと考えていたために,かなり時間を取られてしまいました.
あくまでdepends_onは「コンテナ」の起動順序を指定するのみで,コンテナ内の「プロセス」までは管理してくれないようです.

今回の環境のログファイルを確認すると以下の順序になっていました.

上記の図のように,Djangoが起動してMySQLとの接続を求めたときにはMySQLが立ち上がっておらず,これが原因でした.

そこで,コンテナ内のプロセスが起動したことを確認してから次のコンテナを起動するようにしたいのですが,これを提供する機能がhealthcheckというものです.実際にhealthcheckを追加したdocker-compose.ymlファイルを以下に示しておきます.

docker-compose_with_healthcheck
version: '3'

services:
  vuejs:
    ~~~
    depends_on:
      mysql: 
        condition: service_healthy
    networks:
      - app_net

  django:
    container_name: django
    build:
      context: ./django
      dockerfile: Dockerfile.django
    ports:
      - 127.0.0.1:18000:8000
    tty: true
    volumes:
      - ./django/src:/app
    command: python manage.py runserver 0.0.0.0:8000
    depends_on:
      mysql:
        condition: service_healthy
    networks:
      - app_net

  mysql:
    image: mysql:8.3
    ~~~
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 1s
      timeout: 3s
      retries: 30
    networks:
      - app_net

networks:
  app_net:
    name: app_net
    driver: bridge

以上のように設定を行うことで,無事に起動が確認できました.

最後に

調べ方が悪かったのか,あるいは,Webアプリ開発者のコミュニティの中では当たり前のことなのか,先述のエラーメッセージに対して確認すべきと指定されている項目の中に,本記事のような記述は見当たらなかったため紹介しました.
初学者の助けになれば幸いです.

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0