[Docker] docker composeで構築したMySQLに接続する3つの方法
docker compose
で構築したMySQLに接続する方法をまとめておこうと思います!
なお、本記事ではdockerについての詳しい説明はあまり行なっておりませんのでご了承下さい。
docker compose
で構築したデータベース
下記のdocker-compose.yml
を用意して、docker compose up -d
コマンドでDockerコンテナを作成します。
version: '3.9'
services:
database:
image: mysql:8.0.33
container_name: mysql-container
ports:
- '3006:3306'
environment:
MYSQL_DATABASE: employees
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: root
volumes:
- ./database/initialize:/docker-entrypoint-initdb.d
- ./database/config/my.cnf:/etc/mysql/conf.d/my.cnf
ポイント
- コンテナ名を
mysql-container
にしていること - Dockerのポートフォワード機能を利用して、ホストマシン(私の場合はローカルMac)のポート
3006
とDockerコンテナ内のポート3306
を結びつけ、ホストマシンのポート3006
へのアクセスをDockerコンテナ内のポート3306
に転送するようにしていること- 私のローカルマシンで既にMySQLがポート
3306
を使っている関係で、ホストマシンのポートに3306
を指定すると競合エラーが発生したため、ポート番号を3306以外にしています。
- 私のローカルマシンで既にMySQLがポート
-
environment:
にMySQLデータベースに関する情報を定義していること -
volumes:
でMySQLコンテナに対するカスタム設定を定義していること(データ初期化、文字化け対策)
コンテナ内のMySQLのデータベースを初期化しています。
// テーブル作成
CREATE TABLE IF NOT EXISTS EMPLOYEE (
EMPLOYEE_ID VARCHAR(10) NOT NULL PRIMARY KEY,
EMPLOYEE_NAME VARCHAR(256) NOT NULL,
GENDER VARCHAR(256) NOT NULL,
CREATE_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UPDATE_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
// データ登録
INSERT INTO EMPLOYEE (EMPLOYEE_ID, EMPLOYEE_NAME, GENDER) VALUES ('dummy', 'ダミー', 'FEMALE');
日本語が文字化けしないようにカスタム設定を追加します。
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
さて、DockerコンテナにMySQLを構築できましたので、接続方法を見ていきます。
MySQLクライアントを使用する方法
ホストマシン(私の場合はローカルMac)に、MySQLクライアントがインストールされていることが前提になります。
ターミナルで下記コマンドを実行したときにバージョン情報が表示されていればMySQLクライアントがインストールされています。
% mysql --version
mysql Ver 8.0.33 for macos12.6 on arm64 (Homebrew)
もし、下記のような表示になる場合はMySQLクライアントがインストールされていないか、もしくはシステムのパスが正しく設定されていないので、確認するようにして下さい。
mysql: command not found
さて、MySQLクライアントがインストールされている前提で進めます。
Dockerコンテナに構築したMySQLに、MySQLクライアントを利用して接続するためには下記のコマンドを実行します。
mysql -u user -p -h 127.0.0.1 --port 3006 -D employees
コマンドを叩くとEnter password:
が出るのでpasswordを入力すると接続できます。
--port 3006
を指定していること
ポイント① ポートに ここはDockerのポートフォワード機能を利用するためにdocker-compose.yml
で定義したports: - '3006:3306'
のホストマシン側のポート番号から来ています。
-h 127.0.0.1
を指定していること
ポイント② ホストに -
-h localhost
を指定するとERROR 1045 (28000): Access denied for user 'user'@'localhost' (using password: YES)
が発生します。 - これはMySQLにおける
localhost
はネットワーク経由ではなく、ホストマシンのOSが管理しているファイルシステム上のUNIXソケットを通じて接続することを意味しており、Dockerコンテナ内からはホストマシンのリソースに直接アクセスできないため失敗します。 - 一方
127.0.0.1
はネットワーク(具体的にはTCP/IP)を通じて接続を試みます。Dockerのポートフォワードは正常に作用し、ホストマシンの特定ポートからDockerコンテナ内のMySQLサーバーへの接続を可能にします。
docker exec
コマンドを使用する方法
docker exec -it mysql-container mysql -u user -p -D employees
docker exec
はDockerのコマンドの1つで、実行中のDockerコンテナ内でコマンドを実行するために使用されます。-it
は2つの略語オプション(-i
と-t
)を一緒に使ったものですが、そういうものなんだなという理解でいったん良い気がします。
mysql-container
を指定していること
ポイント① コンテナ名docker-compose.yml
で定義したcontainer_name: mysql-container
から来ています。コンテナ名ではなく、コンテナID(644cfa84b130
)を指定することもできます。
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
644cfa84b130 mysql:8.0.33 "docker-entrypoint.s…" 56 minutes ago Up 56 minutes 33060/tcp, 0.0.0.0:3006->3306/tcp mysql-container
ポイント② ホストやポートを指定していないこと
ここでは、MySQLクライアントと違い、ホストやポートを指定していません。
docker exec
は実行中のDockerコンテナ内でコマンドを実行するために利用することを説明しました。この『Dockerコンテナ内』というのがミソです。
ホスト名(-hオプション)やポート番号(--portオプション)を指定しない場合、mysqlコマンドはデフォルトでlocalhost(つまり、コマンドが実行されている同じシステム=ここではDockerコンテナ)のデフォルトのMySQLポート(通常は3306)に接続しようとします。
つまり、docker exec
を使ってDockerコンテナ内で実行している場合、localhostはそのコンテナ自体を指し、ポートはMySQLのデフォルトポート(3306)に自動的に接続してくれるため、ホスト名やポート番号を明示的に指定する必要はありません。
データベースのクライアントツールを使用する方法
『Dbeaver』を利用した接続方法をご紹介しますが、その他のデータベースクライアントツールでも同様の設定かと思います。
-
新しい接続を作成する -> 新しい接続タイプを選択する で「MySQL」を選択します。
-
MySQL接続設定で
docker-compose.yml
に定義したデータベース情報を入力します。(portは3006
にすること)
-
正常に接続されて、テーブルを参照できています。
参考
Discussion