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
する前に空にしておくことでうまくいきます。すなわち、
$ rm -r ./mysql/data_db
でdata_dbを削除$ mkdir ./mysql/data_db
で再度ディレクトリ作成$ docker compose up --build
でビルド
という手順を踏むことになります。これはうまくいくことを確認しました。