Dockerで初期データを投入してMySQLコンテナを起動する
DockerでMySQLコンテナを立ち上げた時の手順、および初期データ投入時に注意することのメモ。
MySQL on Docker
現在はさまざまなソフトウェアがコンテナ化されていますが、MySQLも当然ながらコンテナ化されています。
今までは、ちょっといじってみたい時でもローカルPCにインストールしてセットアップする作業がありましたからね。ありがたいことです。
ちなみに、MySQL以外のDBMSとしては↓のようなものがあります。コンテナを使えば何でも試せますね!
MySQLコンテナを使ってみる
実際にMySQLをコンテナで起動してみます。
DockerコマンドからとDockerfile/docker-compose.ymlに定義してからの起動の2通りで試します。
Dockerコマンドから起動する
まずは一番簡単な方法であるDockerコマンドで、MySQLを起動してみます。
といっても何も難しいことはなく、Docker Hubにも起動コマンドが載っています。
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
docker runコマンドで起動します。ローカルにコンテナイメージが存在しない場合でも、runコマンドであればイメージの取得から処理されるので本当にこれだけで起動できてしまいます。
使うオプションの意味は↓になります。
option | 意味 |
---|---|
--name | 起動するコンテナに明示的に名前を指定する |
-e | 環境変数を設定する |
-d | コンテナをバックグランドで実行する |
上記を踏まえて、以下のコマンドで実際に実行してみます。今回はMySQL5.7を使用するため、Tagで"5.7"を指定します。
$ docker run --name mysql_test -e MYSQL_ROOT_PASSWORD=password -d mysql:5.7
私の環境では既にローカルPCにMySQL:5.7のイメージが存在していたため、イメージのpullは行われていませんが、問題なく起動しました。
試しにexecコマンドでbashを起動して、MySQLに接続してみます。
$ docker exec -it mysql_test bash root@399409de641b:/# mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 Server version: 5.7.25 MySQL Community Server (GPL) Copyright (c) 2000, 2019, 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>
database一覧↓
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec)
良い感じですね。あとは適当にDB・テーブル作って色々試せます。
ただ、このままだとデータの永続化をしておらずコンテナを削除した場合データがふっとんでしまいます。。
また、コマンド実行というのは、構成管理できず基本的にはイケてない方法なのでファイルに定義したやり方を次に試したいと思います。
Dockerfile/docker-compose.ymlから起動する
次に、コマンドから起動ではなく、定義ファイルからのコンテナ起動を行います。
ついでに、コンテナを削除してもデータが消えないように、データの永続化をするようにもしてみます。
フォルダ構成は以下。
mysql │ docker-compose.yml │ Dockerfile │ my.cnf │ └─InitData init.sql
まずはdocker-compose.ymlを定義します。
version: '3' services: db: build: . container_name: mysql_test ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: testdb TZ: Asia/Tokyo volumes: - db-data:/var/lib/mysql command: mysqld volumes: db-data:
環境変数をセットできるenvironment
でMYSQL_DATABASE
とTZ
を指定しています。
MYSQL_DATABASE
は設定することでイメージの初回起動時にDBを作成してくれます。
TZ
はタイムゾーン指定です。
トップレベルのvolumes
で"db-data"というボリュームを作成するようにしています。それをdb
以下のvolumes
でコンテナの"/var/lib/mysql"を"db-data"にマウントします。
これにより、mysqlコンテナを削除してしまってもvolumeのdb-dataにデータが保持されているのでデータが消し飛ぶことがなくなります。
次にDockerfile↓
FROM mysql:5.7 # MySQLの設定 COPY ./my.cnf /etc/mysql/conf.d/my.cnf # 初期投入データ COPY ./InitData/init.sql /docker-entrypoint-initdb.d
文字コード設定のために用意したMySQL設定ファイルの"my.cnf"をコンテナの"/etc/mysql/conf.d/my.cnf"へコピーします。
続けて初期投入データ用のinit.sqlをコンテナの"/docker-entrypoint-initdb.d"へコピーします。
初期データですが、docker-entrypoint-initdb.dへ~.sql, ~.sh, ~sql.gz
を拡張子にもつファイルをコピーしておくと、コンテナ初回起動時に自動で実行してくれます。
When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d.
my.cnfにはutf8を使うよう文字コードの設定を記載しておきます↓
[mysqld] character-set-server=utf8 [mysql] default-character-set=utf8 [client] default-character-set=utf8
CREATE TABLE sample_table ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(30) NOT NULL, comment TEXT NOT NULL, createdAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updatedAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id) ); insert into sample_table (name, comment) values ('テストName1', 'テストcomment1'), ('テストName2', 'テストcomment2'), ('テストName3', 'テストcomment3'), ('テストName4', 'テストcomment4'), ('テストName5', 'テストcomment5'), ('テストName6', 'テストcomment6');
これで必要なファイルがそろったので、起動してみます。
docker-compose.ymlがある場所で以下のコマンドを実行します。
最初にビルドしてイメージを作成します。
$ docker-compose build
バックグラウンドでコンテナを起動します。
$ docker-compose up -d
ビルド後、コンテナが正常に起動できていることを確認できました。
init.sql
が実行されているか確認してみます。
execコマンドからコンテナでbashを起動し、MySQLへ接続して確認します。
$ docker exec -it mysql_test bash
ちゃんとinit.sqlに定義したsqlが実行されていることが確認できました!
また、volumeによってデータの永続化もできているので、コンテナを削除してもMySQLのデータが消えることはありません。
ただし、当たり前ですが、volumeを削除すると消えてしまうので注意してください。
特に、docker-compose down
コマンドはファイルに定義したコンテナを一度に停止・削除までやってくれるので便利ですが、docker-compose.ymlに定義されたvolumeまで削除されてしまうので注意してください。
初期データ投入の条件
MySQLコンテナはdocker-entrypoint-initdb.d
にsqlファイルをコピーしておくと、コンテナ初回起動時に自動実行してくれます。
ですが、volumeを使っている場合に1点注意することがあります↓
マウントしたvolumeにMySQLのデータが存在すると、コンテナが初回起動の場合でも、初回起動とみなされず"docker-entrypoint-initdb.d"にあるsqlは実行されません。
当たり前といえば当たり前ですが、私は最初、この挙動についてあまり理解しおらずだいぶはまりました。。 これからやる人はぜひ気を付けてください。。
Dockerコマンド
今回はDockerコマンドについてあまり詳しく説明しませんでしたので関連および公式ドキュメントをリンクしておきます。