🙄

立ち上げたMySQLのDockerコンテナでAccess deniedされた時の対処

2022/01/24に公開

問題点: docker composeで立ち上げたMySQLコンテナのmysqlにログインできない

エラーの概要

docker-compose.ymlでログインするユーザーのパスワードを変更した際に以下のエラーがブラウザ上で発生した

Warning: mysqli::__construct(): (HY000/1045): Access denied for user 'user'@'ローカルホストIP' (using password: YES) in /var/www/html/index.php on line 3

MySQLを呼び出しているPHPのコード

index.php
<?php

$mysqli = new mysqli('db', 'user', 'hoge', 'test_db');

$result = $mysqli->query('select * from users');

while ($row = $result->fetch_assoc()) {
    echo "<p>{$row['name']}</p>";
}

$result->close();

$mysqli->close();
docker-compose.yml
version: '3.7'

services:
  web:
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    volumes:
      - ./src:/var/www/html
    ports: [ 8080:80 ]
    depends_on:
      - db

  composer:
    build:
      context: .
      dockerfile: ./docker/composer/Dockerfile

  db:
    build:
      context: .
      dockerfile: ./docker/mysql/Dockerfile
    volumes: [ project-name:/var/lib/mysql ]
    environment:
      MYSQL_ROOT_PASSWORD: admin
      MYSQL_DATABASE: test_db
      MYSQL_USER: user
      MYSQL_PASSWORD: hoge

volumes:
  project-name:

コンテナで直接userログインをしてみるも同様のエラーが発生する

user@b3427f76ea25:/# mysql -uuser -ppassword
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'user'@'localhost' (using password: YES)

結論: 既に同名のボリュームがあり、変更が適用されていない状態でコンテナが立ち上がったため

MySQLのimageでは既にdocker runでデータベースが作成されている場合にはそのデータベースを使用します。後で行われた環境変数に対する変更もデータベースが既存の場合には影響を及ぼしません。

When you start the mysql image, you can adjust the configuration of the MySQL instance by passing one or more environment variables on the docker run command line. 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.
official image documentation

エラーを解決するためにボリュームを削除し、コンテナを立ち上げ直します

  • ボリュームを削除し、コンテナを立ち上げ直す
$ docker compose down -v
$ docker compose up -d
$ docker exec -it 83dc58997932 bash
user@83dc58997932:/#
user@83dc58997932:/# mysql -uuser -p
Enter password:    # password
mysql>             # ログイン成功

再現

userのパスワードをpassに変更

index.php
- $mysqli = new mysqli('db', 'user', 'hoge', 'test_db');
+ $mysqli = new mysqli('db', 'user', 'pass', 'test_db');
docker-compose.yml
-     MYSQL_PASSWORD: hoge
+     MYSQL_PASSWORD: pass      

docker compose downを行う(ボリュームが削除されていない)

$ docker compose down
[+] Running 4/4
 ⠿ Container project-name_composer_1  Removed                                        0.1s
 ⠿ Container project-name_web_1       Removed                                        1.3s
 ⠿ Container project-name_db_1        Removed                                        1.5s
 ⠿ Network project-name_default       Removed

変更を反映させた状態でコンテナを立ち上げる

$ docker compose up -d
[+] Running 4/4
 ⠿ Network project-name_default       Created                                        0.3s
 ⠿ Container project-name_db_1        Started                                        0.9s
 ⠿ Container project-name_composer_1  Started                                        0.8s
 ⠿ Container project-name_web_1       Started                                        2.0s

mysqlにuserpassでログインを試してもエラーが発生する

$ docker exec -it 3ba0761a9ee7 bash
user@3ba0761a9ee7:/# mysql -uuser -ppass
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'user'@'localhost' (using password: YES)

コンテナの停止と一緒にボリュームを削除

オプション 概要
-v, --volumes Compose ファイルの volumes セクションの名前付きボリュームを削除。また、コンテナがアタッチしたアノニマス・ボリュームも削除
$ docker compose down -v
[+] Running 5/5
 ⠿ Container project-name_web_1                 Removed                              1.3s
 ⠿ Container project-name_composer_1            Removed                              0.1s
 ⠿ Container project-name_db_1                  Removed                              1.5s
 ⠿ Volume project-name_project-name-db  Removed                              0.0s
 ⠿ Network project-name_default                 Removed                              0.2s

コンテナを立ち上げ直す

$ docker compose up -d
# mysqlコンテナにuserのpassでログインが成功する
$ docker exec -it 4f93ecd4d08e bash
user@4f93ecd4d08e:/# mysql -uuser -ppass
mysql>

参考

stackoverflow
official image documentation
-vオプションについて

Discussion