docker-composeでMySQL認証エラーが出た時の対応

背景

以前の記事でdocker-composeを利用してDjango+MySQLの環境を作成しました。

今回、別のプロジェクトでDjango+MySQLのアプリケーションを作成することにしたので、久々環境を構築したところ、以下のエラーにハマったので備忘録として記載します。

エラー内容

エラーはこんな感じでした。

1
django-web-1  | django.db.utils.OperationalError: (1044, "Access denied for user 'django'@'%' to database 'django'")

認証に失敗しているようです…

docker-compose.ymlの確認

まずMySQLコンテナの認証を設定しているdocker-compose.ymlを確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
version: '3'

services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: 'django'
MYSQL_PASSWORD: 'django'
MYSQL_DATABASE: 'django'
ports:
- 3306:3306
volumes:
- mysql:/var/lib/mysql
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
- site-packages:/usr/local/lib/python3.10/site-packages
- usr-local-bin:/usr/local/bin
ports:
- "8000:8000"
links:
- db

volumes:
site-packages:
driver: local
usr-local-bin:
driver: local
mysql:
driver: local

問題なさそうです。

Djangoのデータベース接続設定の確認

次に接続に行っているDjango側の設定を確認します。プロジェクト配下のsettings.pyを確認します。

1
2
3
4
5
6
7
8
9
10
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'USER': 'django',
'PASSWORD': 'django',
'HOST': 'db',
'PORT': 3306,
}
}

こちらも問題なさそうです。

原因

だいぶ長い間ハマって気づいたのは、mysqlのvolumeが意図しない動作を引き起こしているのではないかということでした。

一度volumeを削除してみます。

1
$ docker volume rm 該当のvolume

(volumeの確認はdocker volume lsで行いました)

削除後にdocker-compose upを行うと、認証のエラーはなくなり、無事アプリケーションが起動しました。

公式ドキュメントを確認

MySQLコンテナのドキュメントEnvironment Variablesを確認するとちゃんと書いてありました。

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.

Google翻訳にすると

すでにデータベースが含まれているデータディレクトリでコンテナを起動した場合、以下の変数はいずれも効果がないことに注意してください。既存のデータベースは、コンテナの起動時に常に変更されません。

ということなので、認証情報を変更する場合は毎回volumeを削除する必要があるということでした。

まとめ

MySQLコンテナはvolumeを使っている場合、認証情報は環境変数で変更することはできないことがわかりました。(最初の1回だけ環境変数で指定)

認証情報だけではなく、データベース名なども変更する場合は、既存のvolumeを削除してから起動すると、環境変数で指定した値が反映されます。