0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ホストからDockerのMySQLコンテナに接続する時の権限エラーを解消する

Last updated at Posted at 2024-09-29

はじめに

Dockerでローカル環境に構築したMySQLコンテナへ、ホストマシン上のアプリから接続しようとした際に以下のような権限エラーになりました。MySQLへ接続時のホストはlocalhostを指定しています。

(1130, "Host '172.18.0.1' is not allowed to connect to this MySQL server")

コンテナ起動時にユーザ作成・権限の設定を行うことで上記エラーを解消することができたので、本記事はその備忘録です。

環境

  • Windows11
  • docker desktop(WSL使用)
  • DockerHubのMySQL公式イメージ(mysql/mysql-server:8.0)を使用。(mysql 8.0.32)

結論(解消方法)

MySQLコンテナの/docker-entrypoint-initdb.dフォルダにDockerネットワークのゲートウェイ(上記エラーの環境では'172.18.0.1')からの接続を許可する初期化クエリを追加します。
MySQL公式のコンテナイメージでは、/docker-entrypoint-initdb.d配下に配置されたクエリがコンテナ初回起動時に実行されます。

以下、docker composeでコンテナ起動する際の例です。

フォルダ構成

.
├ docker-compose.yml
└ mysql-init # 任意の名称
  └ init.sql  # 任意の名称

docker-compose.yml

volumes:にてmysql-initフォルダをMySQLコンテナの/docker-entrypoint-initdb.dへバインドマウントしています。

docker-compose.yml
services:
  mysql:
    image: mysql/mysql-server:8.0
    container_name: mysql-container
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: test_db
    volumes:
      - ./mysql-init:/docker-entrypoint-initdb.d # bindマウントでコンテナへ初期化クエリを配置
      - mysql:/var/lib/mysql

volumes:
  mysql:

初期化クエリ

コンテナの初回起動時に以下クエリが実行されます。

以下は全ホストを対象としたユーザー'root'@'%'を作成して、全権限を付与しています。
必要に応じて、ホスト、権限を絞ってください。

init.sql
CREATE USER 'root'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

コンテナ起動

docker compose up -d

ホストマシン上のアプリから接続

以下pythonの例。

import pymysql

conn = pymysql.connect(
    host="localhost",
    port=3306,
    user="root",
    password="password",
    database="test_db",
)

コンテナ停止

ボリュームをマウントして既に起動している場合は、ボリュームを削除して再度コンテナを立ち上げないと、初期化クエリが実行されないので注意ください。

docker compose down -v # ボリュームごと削除

エラーの原因

dockerでコンテナを構築した場合、dockerネットワーク上にコンテナが作成され、dockerネットワークのゲートウェイを経由してコンテナへアクセスされます。
このdockerネットワークのゲートウェイをホストとしたMySQLのユーザーが作成されていないことが原因です。

dockerネットワーク

エラー文からもわかるように、アプリからlocalhost(127.0.0.1)に対して接続しているにもかかわらず、ホストが'172.18.0.1' になっています。

これは、dockerでコンテナを構築した場合、dockerネットワーク上にコンテナが作成され、dockerネットワークのゲートウェイを経由してコンテナへアクセスされるためです。
ゲートウェイのIPは、上記エラー発生時の環境では'172.18.0.1'に指定されていました。

dockerネットワークに関しては、以下記事がわかりやすいです。

ゲートウェイのIPの確認方法

docker inspect {コンテナID}を実行します。コンテナIDはdocker psコマンドで確認できます。
長いので必要な個所のみ抽出していますが、"Gateway": "172.18.0.1"となっているのがわかります。

docker inspect {コンテナID}
[
    {
        ...
        "NetworkSettings": {
            ...
            "Networks": {
                "{dockerネットワーク名}": {
                    ...
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    ...
                }
            }
        }
    }
]

dockerネットワーク名の箇所は、ネットワークを指定せず起動した場合、docker composeでは{フォルダ名}_defaultのようなネットワーク名で自動作成されます。docker runで起動した場合は、デフォルトで用意されているbridgeネットワークが使用されます。

docker network lsでネットワークの一覧確認、docker network inspect {ネットワークID}でネットワークの詳細確認も可能です。

MySQLのユーザー、権限

デフォルトでは、以下のようにホストをlocalhostとするユーザーのみ存在しています。
そのためdockerネットワークのゲートウェイのIPからの接続は許可されていません。

# docker exec でコンテナに乗り込み
PS > docker exec -it {コンテナID} sh

# mysqlへ接続
sh-4.4# mysql -u root -p
Enter password:

# ユーザーリスト表示
mysql> SELECT host, user FROM mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| localhost | healthchecker    |
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+

一方で、上記初期化クエリを設定した場合は、以下のように全てのホスト(%)に対するユーザーrootが作成されています。

mysql> SELECT host, user FROM mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| %         | root             |
| localhost | healthchecker    |
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+

ユーザーに設定されている権限は、show grants for 'ユーザー名'@'ホスト名'で確認できます。

参考記事

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?