6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MySQLのDockerコンテナ作成時にDBのスキーマ、レコード作成を行う方法

Last updated at Posted at 2023-10-02

結論

スキーマやレコード作成を記述したSQLファイルと、そのSQLを実行するシェルファイルを用意し、Dockerfileでコピー、もしくはdocker-compose.ymlのvolumeマウントで用意したファイルをMySQLコンテナの/docker-entrypoint-initdb.d/に設置することで初回コンテナ起動時にシェルファイルが実行され、スキーマ、レコード作成を行うことができる。

docker-composeによる例

Dockerfile
FROM mysql:8.0.34

# SQLファイルをコピー(docker-compose.ymlでマウントする場合は不要)
# COPY /database/*.sql /database/

# # テストデータベース作成用のスクリプトをコピー(docker-compose.ymlでマウントする場合は不要)
# COPY /docker-entrypoint-initdb.d/init_db.sh /docker-entrypoint-initdb.d/

# # このフォルダにファイルをコピーして実行権限を付与しておけば初回コンテナ作成時に自動実行してくれる(docker-compose.ymlでマウントする場合は不要)
# RUN chmod +x /docker-entrypoint-initdb.d/init_db.sh

CMD ["mysqld", "--default-time-zone=Asia/Tokyo"]
docker-compose.yml
version: '3'

services:
  rdb:
    build: ./
    platform: linux/x86_64
    environment:
      LANG: C.UTF-8
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: user
      MYSQL_PASSWORD: user
      TZ: 'Asia/Tokyo'
    ports:
      - "3306:3306"
    volumes:
      - sample-mysql-data:/var/lib/mysql
      # DockerfileでCOPYする場合は以下の二行は不要
      - ./database/:/database/
      - ./docker-entrypoint-initdb.d/:/docker-entrypoint-initdb.d/

volumes:
  sample-mysql-data:
init.sh
mysql -h localhost -u root -proot < /database/create_schema.sql
mysql -h localhost -u root -proot < /database/create_row.sql
create_schema.sql
CREATE SCHEMA IF NOT EXISTS `sample_db` DEFAULT CHARACTER SET utf8 ;

USE `sample_db`;

CREATE TABLE IF NOT EXISTS `sample_tbl` (
  `id` CHAR(36) NOT NULL,
  `text` VARCHAR(50) NOT NULL,
  `created_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

create_row.sql
USE `sample_db`;

INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c91', 'text1', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c92', 'text2', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c93', 'text3', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c94', 'text4', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c95', 'text5', '2023-09-30 00:00:00');

ハマったこと

以下のケースに該当する場合はSQLファイルを更新して、コンテナを作り直してもスキーマなどが更新されません。

  • Dockerfileでコピーのみを行ない、マウントしていない場合はその都度イメージ作り直さなければならない。
  • ボリュームを作成し、/var/lib/mysqlをボリュームマウントしている場合はボリュームを削除しなければならない。
  • docker-compose.ymlでSQLファイルやスキーマファイルをマウントにより共有している場合はホストで実行権限を付与しておかなければならない。

最後に

上記のことから開発環境で利用する場合は作成したデータが消えないようにボリュームを作成してマウントし、スキーマの変更があった場合は直接コンテナにアタッチしてMySQLにログインし、変更を反映することがいいように思いました。
また、自動テストで利用する場合はボリュームを作成せずにコンテナを作り直しただけでスキーマが反映されるようにすることがいいように思いました。

6
4
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
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?