💽

docker-compose upと同時にDBに初期データを入れ込む

2023/02/17に公開

やりたいこと

  • Docker compose でアプリケーションとデータベースのコンテナを立ち上げた時に,アプリ側からアクセスするデータをdocker-compose up時に自動で入れ込みたい.

やったこと

  • 必要なデータファイルをコンテナにVolumeする.
  • データベースを作成+テーブルの作成
  • データファイルをテーブルに入れ込む
  • ダンプファイルを作成
  • コンテナ起動時に読み込む

手順

  1. サンプルファイル作成
    今回はAPIからとってきたデータを一旦CSVファイルとして保存した.
    data/test.csv
name,company_id,description,foundation_date,industry
"TK corp", 123, "データ詳細", "2022-02-12", "software"
"TK corp2", 124, "データ詳細", "2022-02-13", "welfare"

このファイルをdocker-compose.yamlにて
/docker-entrypoint-initdb.d/にマウントさせる記述を行う.

2.1 コンテナ準備
docker-compose.yaml

version: '3'

services:
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}

    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./mysql/my.cnf:/etc/my.cnf
      - ./data:/docker-entrypoint-initdb.d/
volumes:
  mysql-data:

2.2 Let's get into the container!

docker compose up -d
docker exec-it xxxxx bash
  1. データ作成
    コンテナ内に入り込んだ後にMySQLに接続.
    この際にMySQL8 以降ではファイルの読み込みがデフォルトでは禁止されてるので,
mysql --local-infile=1 -u root -p

としてログインする.

データベース作成からテーブルの作成.

SET GLOBAL local_infile=1;
CREATE SCHEMA if not exists test;

USE test;

CREATE TABLE if not exists companies
(
    name TEXT,
    company_id int,
    description TEXT,
    foundation_date TEXT,
    industry TEXT
);
  1. CSVファイルをDBに写す
load data local infile '/docker-entrypoint-initdb.d/test.csv' into table companies FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES;

ここでローカルのdataディレクトリ内に作ったtest.csvを
docker-compose.yaml内でdocker-entrypoint-initdb.dディレクトリにマウントしている.

- ./data:/docker-entrypoint-initdb.d/

ので,
ここで/docker-entrypoint-initdb.d/test.csvでコンテナ内のCSVファイルのパスを指定している.

  1. ダンプファイルの作成.
    一旦exitした後に
mysqldump -u root -p --lock-all-tables --all-databases --events > mysql_dump.sql

現在の全てのテーブルのダプリケーションを行うためにsqlファイルを作成する.
これをローカルに反映させるために/docker-entrypoint-initdb.dディレクトリ内に移動させる.

cp mysql_dump.sql /docker-entrypoint-initdb.d/

これでローカルにも保存される.
(
コンテナ内の/docker-entrypoint-initdb.d/配下にある.sql, .sql.gz, .shの拡張子を持つファイルはコンテナ起動時に実行される.
);

従って今作ったmysql_dump.sqlファイルはコンテナ起動時に実行されDBに初期データを投入してくれるというしくみ.

おまけ
日本語を入れた時に,文字化けが起こることがある.これはMySQLのデフォルトの文字コードはutf-8になってないため起こっているらしい.ので,
/etc/my.cnfに以下のコードを追加するとデフォルトの文字コードをutf-8に設定できる.今回はローカルからこのファイルをマウントさせているのでコンテナ内では自動でutf-8になるようにした.

[mysql]
default-character-set=utf8

Discussion