趣味で作っているアプリに、データベースを使ってみたかったので、Dockerを利用して起動してみました。
基本的には以下のサイトを参考にしています。
フォルダ構造
基本的には、前述のサイトと同様になっています。
しかし、将来的に別コンテナで動かすプログラムからDBにアクセスしたいと考えているので、
docker
フォルダ内でさらにmysql
とapp
フォルダに分けています。
.
├── docker
│ ├── app/
│ ├── docker-compose.yml
│ └── mysql/
│ ├── Dockerfile
│ ├── conf.d/
│ │ └── config-file.cnf
│ └── initdb.d/
│ ├── schema.sql
│ └── testdata.sql
├── log/
│ └── mysql/
├── run.sh
└── stop.sh
設定ファイル
各ファイルの内容を記載します。
上記したフォルダ構造の上から順に説明します。
docker/docker-compose.yml
Docker-composeの設定ファイルになります。
version: '3.3'
services:
db:
build: ./mysql
image: mysql:5.7
restart: always
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: sample_db
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpassword
ports:
- "3314:3306"
volumes:
- ./mysql/initdb.d:/docker-entrypoint-initdb.d
- ./mysql/conf.d:/etc/mysql/conf.d
- ../log/mysql:/var/log/mysql
docker/mysql/Dockerfile
MySQLのイメージデータ用のDockerfileです。
FROM mysql:5.7
RUN touch /var/log/mysql/mysqld.log
docker/mysql/conf.d/config-file.cnf
最初に紹介したサイトでは、docker/mysql/conf.d/my.cnf
となっていたものです。
しかし、MySQLのDocker Hubを見てみると、config-file.cnf
が適切に設計されています。
[mysqld]
character-set-server=utf8mb4
explicit-defaults-for-timestamp=1
general-log=1
general-log-file=/var/log/mysql/mysqld.log
[client]
default-character-set=utf8mb4
参考
mysqlDocker Hub
docker/mysql/initdb.d/schema.sql
ここでは初期化処理として、テーブルの作成を行っています。
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL,
email VARCHAR(32) NOT NULL,
PRIMARY KEY (id)
);
docker/mysql/initdb.d/testdata .sql
前に定義したテーブルにデータを入れる処理です。
INSERT INTO users (id,name,email) VALUES (1, 'TOM','xxxx@mail.co.jp');
run.sh
僕はコマンドを覚えるのが苦手なので、docker-composeの起動なども全てシェルスクリプトで行います。
これは起動用のシェルスクリプトです。
ポイントは、起動後に60秒間待っていることです。
ここでは、MySQLの起動と初期化処理が完了するのを待っています。
#!/bin/bash
cd docker && \
docker-compose up -d --build
echo "Waitting for setting up MySQL...." && sleep 60 && echo "OK!"
stop.sh
このスクリプトでは、サービス停止命令を行います。
#!/bin/bash
cd docker && \
docker-compose stop # サービスを停止させる
docker-compose down # コンテナの停止、削除、さらにネットワーク、記憶領域を全て削除
起動!!
まずはシェルスクリプトに実行権限を付与します。
$ chmod +x run.sh
$ chmod +x stop.sh
早速、MySQLを起動しましょう。
$ ./run.sh
Creating network "docker_default" with the default driver
Building db
Step 1/2 : FROM mysql:5.7
---> b46ebd15a443
Step 2/2 : RUN touch /var/log/mysql/mysqld.log
---> Running in d48d912c665f
Removing intermediate container d48d912c665f
---> 86e2e1aecfd0
Successfully built 86e2e1aecfd0
Successfully tagged mysql:5.7
Creating docker_db_1 ... done
Waitting for setting up MySQL.... (ここで1分ほど待つ)
OK!
起動できたので、接続を行って、データベースの状態を確認しましょう。
$ mysql --host 127.0.0.1 --port 3314 -u user -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.18 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use sample_db; # 使用するデータベースを指定
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables; # 初期処理で作成されたテーブルを確認
+---------------------+
| Tables_in_sample_db |
+---------------------+
| users |
+---------------------+
1 row in set (0.01 sec)
mysql> select * from users; # データが入れられているか確認
+----+------+-----------------+
| id | name | email |
+----+------+-----------------+
| 1 | TOM | xxxx@mail.co.jp |
+----+------+-----------------+
1 row in set (0.01 sec)
mysql>
ここまでで、MySQLへの接続を確認することができました!
また、log/mysql/mysqld.log
というMySQLのログファイルが作成されたことも確認できます。
最後に、遊び終えたらきれいにしましょう。
$ ./stop.sh
Stopping docker_db_1 ... done
Removing docker_db_1 ... done
Removing network docker_default
トラブルシューティング
少しエラーが発生したことについて、直し方を書いておきます。
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0
ホスト側から、コンテナ上のMySQLにアクセスしようとしたときに発生しました。
$ mysql --host 127.0.0.1 --port 3314 -u user -p
Enter password:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0
これに関しては、コンテナ内のMySQLが完全に起動していないために発生しました。
(このサイトを見ているときに、気付きました)
なので、数分を置いて再度、接続を試みることで解決します。
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(/usr/local/Cellar/mysql/5.7.21/lib/plugin/caching_sha2_password.so, 2): image not found
前節でのエラーが解決したら、次のエラーが発生しました。
% mysql --host 127.0.0.1 --port 3314 -u user -p
Enter password:
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(/usr/local/Cellar/mysql/5.7.21/lib/plugin/caching_sha2_password.so, 2): image not found
これは、MySQLのDockerHubに書いてあるように、docker-compose.yml
にcommand: --default-authentication-plugin=mysql_native_password
を追加することで解決します。
(公式サイトちゃんと見ろってやつですねw)
具体的には、docker-compose.yml
を以下のようにしました。
version: '3.3'
services:
db:
build: ./mysql
image: mysql:5.7
restart: always
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: sample_db
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpassword
ports:
- "3314:3306"
volumes:
- ./mysql/initdb.d:/docker-entrypoint-initdb.d
- ./mysql/conf.d:/etc/mysql/conf.d
- ../log/mysql:/var/log/mysql
まとめ
いかがだってしょうか?
僕もDockerを使って、DBを操作することは初めてだったので、いろいろつまりながら作業を行いました。
とにかく、1次情報である公式サイトの書いてあることはしっかりと読みましょう!