docker上でdjango+mysqlで環境構築すると、access deniedエラーになる件

Docker上でdjango+mysqlの環境構築をするとエラーになる件

環境

  • Macbook Air(M1)
  • Docker Desktop for Mac (ver.20.10.6)
  • Django == 3.0
  • Python3 (3.6-slim-buster)
  • MySQL 5.7

結論から言うと

MySQLイメージを使う場合は、{既存のDBファイルを含むローカルフォルダ}:/var/lib/mysqlとしてバインドするとハマります。 新しい名前付きボリュームor空ディレクトリをバインドすることで、このエラーを回避できます。

やりたいこと

Pythonイメージ内でdjangoプロジェクトをビルドし、djangoからMySQLをDBとして使用したいです。 その際、MySQLのデータを永続化させるために既にDB関連のデータを含んでいるローカルのフォルダ(下記のmysql/data_db)をマウントしようとしてハマりました。

はじめに試したディレクトリ構造は以下のようになっています。

my-docker-project/
|__django-project/
|     |__src/...
|     |__Dockerfile
|
|__mysql/
|    |__data_db/...
|    |__init_db/...
|
|__docker-compose.yml

また、docker-compose.ymlは下記の通りです。

version: "3"

services:
  mysql-db:
    image: amd64/mysql:5.7
    environment:
      - MYSQL_DATABASE=python_db
      - MYSQL_USER={ユーザー名}
      - MYSQL_PASSWORD={パスワード}
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - ./mysql/data_db:/var/lib/mysql
      - ./mysql/init_db:/docker-entrypoint-initdb.d
    privileged: true
    ports:
      - 3306:3306

  django-project:
    build: ./django-project
    restart: always
    command: bash -c "python3 /mysite/local_manage.py makemigrations && python3 /mysite/local_manage.py migrate && python3 /mysite/local_manage.py runserver 0.0.0.0:8000"
    ports:
      - 8000:8000
    volumes:
      - ./django-project/mysite/history:/mysite/history
      - ./django-project/mysite/media:/mysite/media
    depends_on:
      - mysql-db

以上の情報をもとに、django側のsettings.pyを以下の通りに設定しました。

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'python_db',
        'USER': 'root',
        'HOST': 'mysql-db',
        'PASSWORD': 'password',
        'PORT': '3306'
    }
}

症状

表記の通りの環境構築をDocker上で行いdocker compose up --buildすると、mysqlにアクセスできず以下のエラーに見舞われます。

django.db.utils.OperationalError: (1045, "Access denied for user 'root'@'192.168.32.3' (using password: YES)")

原因

調べて見ると以下の記事に行き当たりました。 stackoverflowの記事

上記の記事によると、 Do note that none of the variables below will have any effect if you start the container with a data directory that already contains a database: any pre-existing database will always be left untouched on container startup. とのことでした。すなわち、一度docker buildなどでDBファイルシステムが構成されてしまったディレクトリをバインドしようとすると、DBコンテナの初期化に失敗するらしいです。

対処法

docker-compose.yml内で/var/lib/mysqlに紐付けるフォルダを、docker compose up --buildする前に空にしておくことでうまくいきます。すなわち、

  1. $ rm -r ./mysql/data_dbでdata_dbを削除
  2. $ mkdir ./mysql/data_dbで再度ディレクトリ作成
  3. $ docker compose up --buildでビルド

という手順を踏むことになります。これはうまくいくことを確認しました。


戻る

About

IMAXおじさんが(主に)技術系記事を備忘録として残していくブログです.

Category

  1. Tech
  2. Daily
  3. Job
  4. Other