lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

Docker ComposeでDB構築(MySQL 5.7)

概要

先日から続けているPHPの実行環境の下りでCRUDを実行したいのでDBサーバを構築します。
MySQLは5.7を使用してdocker-compose upでテーブル作成のSQLスクリプト流し込みまで行います。

DockerのMySQLイメージを使用したDBサーバの構築は過去にASP.NET Coreのアプリで使用したことがあります。 その時は、コンテナ作成時に引数与えて起動してSQL自体はEntityFramework Core(O/Rマッパ)を使用していたので書いていませんでした。

前回、Docker使ってMySQLでDB構築した記事はこちら

kitigai.hatenablog.com

目次

参考サイト様

環境

$ docker -v
Docker version 18.09.2, build 6247962
$ docker-compose -v
docker-compose version 1.23.2, build 1110ad01

Docker ComposeでMySQLのDBサーバ構築

DockerHubのドキュメントを参考にしつつ構築する。

構築時にパスの指定をミスってた以外は特につまりどころ無し。
DBデータはローカルにマウントして永続化します。

成果物

github.com

ディレクトリ構成

ディレクトリ構成は以下の通りです。
docker-configs/mysql配下にDBサーバ関連のあれこれを配置します。

docker-configs/mysql/dataはDBデータ用のディレクト
docker-configs/mysql/sqlはコンテナ起動時のSQLスクリプトです。

.
├── docker-compose.yml
├── docker-configs
│   ├── mysql
│   │   ├── data
│   │   └── sql
│   │       └── init.sql
│   ├── nginx
│   └── php-fpm
└── src
    └── index.php

docker-compose.ymlの作成

docker-compose.ymlにDBサーバの設定を定義します。

  • docker-compose.yml
version: "3.7"
services:
  # 省略
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: ${DATABASE}
      MYSQL_USER: ${USERNAME}
      MYSQL_PASSWORD: ${USERPASS}
      MYSQL_ROOT_PASSWORD: ${ROOTPASS}
    ports:
      - "33306:3306"
    volumes:
      - ./docker-configs/mysql/sql:/docker-entrypoint-initdb.d
      - ./docker-configs/mysql/data:/var/lib/mysql

imageセクション

任意のイメージを選択します。
今回はMySQLの公式イメージでタグでバージョン5.7を指定します。

image: mysql:5.7

environmentセクション

コンテナ起動時に作成される下記の4項目について任意の値を設定します。
${}.envファイルで与えてる環境変数です。直書きで構いません。

environment:
  MYSQL_DATABASE: SAMPLE
  MYSQL_USER: hogeuser
  MYSQL_PASSWORD: password
  MYSQL_ROOT_PASSWORD: password
  • MYSQL_DATABASE(オプション)
  • MYSQL_USER(オプション)
  • MYSQL_PASSWORD(オプション)
    • ユーザ名&パスワードを環境変数に持たせることでコンテナ起動時にユーザが作成される。
  • MYSQL_ROOT_PASSWORD(必須)
    • rootパスワードを指定する。

環境変数についてはDockerHubのドキュメントに記載があります。

portsセクション

ホスト側:コンテナ側でポートを指定します。

ports:
  - "33306:3306"

今回は無難にホスト側のポートを変更しておきました。

※補足
ホストのクライアントから接続する際には33306ポートを指定して接続するイメージ

volumesセクション

DBデータを永続化するためにDBデータのディレクトリをローカルにマウントします。
mysqlの設定は初期のままなので/var/lib/mysqlがデータディレクトリです。

volumes:
  - ./docker-configs/mysql/data:/var/lib/mysql

下記はコンテナ起動時に実行されるSQLスクリプトを配置したディレクトリをマウントします。
これで該当のディレクトリに配置したSQLがコンテナ起動時に実行されます。
/docker-entrypoint-initdb.dディレクトリについては後述します。

volumes:
  - ./docker-configs/mysql/sql:/docker-entrypoint-initdb.d

docker-entrypoint-initdb.dについて

下記のドキュメントに解説があります。

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. Files will be executed in alphabetical order.
You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data.
SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.

ガバ翻訳だけど下記のような感じです。

  • コンテナ初回起動時にdocker-entrypoint-initdb.dにあるファイルを実行する。
  • 対象ファイルの拡張子は.sh.sql.sql.gzの3つ
  • 起動時にMYSQL_DATABASEで指定されたスキーマを対象にSQLスクリプトを実行する。

はーん、なるほどねと言う感じ。
複数スキーマを対象にSQLスクリプト流してる例もありました。

こっちは各拡張子を試してます。

SQLスクリプト作成

コンテナ起動時に実行したいSQLスクリプトを作成します。
サンプル用のテーブルを作成しているだけなので省略します。

コンテナ起動&DB確認

準備が整ったのでコンテナを起動し、DBにテーブルが作成されているか確認します。

コンテナ起動

初回起動は時間がかかります。

$ docker-compose up

DBスキーマが正常に作成されていたらdocker-configs/mysql/data配下にDB関連のファイルが大量に作成されます。

DB接続確認

クライアントにはDBeaverを使用します。

f:id:HM_Atlas:20190505181043p:plainf:id:HM_Atlas:20190505181048p:plain

DB&テーブル確認

コンテナからコマンド発行していろいろ確認します。

$ docker-compose exec db bash
root@a05d13008010:/# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| SAMPLEDB           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.03 sec)

mysql> show tables from SAMPLEDB;
+--------------------+
| Tables_in_SAMPLEDB |
+--------------------+
| SAMPLETBL          |
+--------------------+
1 row in set (0.00 sec)

mysql> desc SAMPLEDB.SAMPLETBL;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| ID    | int(11)     | NO   | PRI | NULL    | auto_increment |
| NAME  | varchar(10) | YES  |     | NULL    |                |
| AGE   | int(11)     | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

init.sqlに記載したテーブルが作成されていることが確認できました。

※補足

mysql> select * from SAMPLEDB.SAMPLETBL;
ERROR 1146 (42S02): Table 'sampledb.sampletbl' doesn't exist

上記のエラーがでたら下記コマンドで設定値を確認。

show variables where variable_name='lower_case_table_names';

もうちょい調べて別記事にします。

雑感

ブログ書くのに時間かかりすぎ問題。
早くかけるようになりたい。
やっとPHPCRUDに取り掛かろうな?全然進捗でてないな?