🦔

【Docker】【MySQL】コンテナ初回起動時にスクリプトを実行させる

2022/02/13に公開
3

はじめに

【Docker】MySQLを簡単に構築
MySQL環境まで構築しました。

これだけでも使い出すのには十分だけど、コンテナを作成するたびにテーブルを作り直す必要があったり、テストデータのinsertもあって…わりかし面倒。

こういったところも、コンテナ起動と同時に実行し、楽したい。

詳細は公式ドキュメントを参照

目的

  • 初回コンテナ起動時に、任意のSQLまたはシェルスクリプトが実行できること

環境

【Docker】MySQLを簡単に構築
で作った環境を流用しています。

docker-compose.ymlファイル 修正

概要

内容としては簡単で、コンテナ内の/docker-entrypoint-initdb.dに配置するだけで、.sh.sqlを実行してくれます。

ディレクトリ構成

mysql
 ∟ conf
  ∟ my.cnf
 ∟ script
  ∟ initShell.sh  # ★ 作成
  ∟ initDb.sql    # ★ 作成
 ∟ .env
 ∟ docker-compose.yml

yamlファイル修正

docker-comose
version: '3'

services:
  db:
    image: mysql:8
    container_name: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      TZ: ${TZ}
    ports:
        - ${DB_PORT}:3306
    volumes:
        - db-store:/var/lib/mysql
        - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf
        # ★ ローカルのscriptディレクトリにマウントします
        - ./script:/docker-entrypoint-initdb.d 
volumes:
  db-store:

実行スクリプト

今回scriptディレクトリに配置したのは、下記のような感じの物。

.shファイル
echo "### initialize start ####"
mkdir /tmp/test
touch /tmp/test/aaaa
echo "### initialize end   ####"
.sqlファイル
create table sample1(
    id int auto_increment,
    col1 text,
    col2 text,
    primary key (id)
) ;

insert into sample1(col1, col2)values('aaa', '1111');
insert into sample1(col1, col2)values('bbb', '2222');
insert into sample1(col1, col2)values('ccc', '3333');
insert into sample1(col1, col2)values('ddd', '4444');

実行スクリプト作成での補足

  • docker-entrypoint-initdb.d 内に複数のスクリプトが存在する場合、名前順で実行
  • 実行タイミングは、/var/lib/mysqlがない場合に実行される(後述に記載)
  • .sqlファイルは、yamlの環境変数MYSQL_DATABASEで指定したユーザへインポート
  • .shはmysqlユーザで実行(root権限で実行できないため、任意のパッケージをインストールしたい場合は、下記のようにDockerfileを作成してインストールする)

root権限が必要な操作について(.sh)

docker-entrypoint-initdb.d内のスクリプトは、mysqlユーザの権限で実行されるため、パッケージのインストールをやりたい場合は、Dockerfileを作成して実行。

【個人的な所感】
DBコンテナとして利用する想定のため、root権限が必要なshellを自動で実行させるという想定がなかなか思い浮かばない。
あるとしたら、調査しやすいようにviとかコマンドのインストールぐらいかなと

Dockerfile
FROM mysql:8

RUN echo "##### command install ##########"
RUN apt-get update
RUN apt-get install -y vim

# CMD ["/startup.sh"] ★ CMDは上書きしてはならない

★ 公式配布のimageはもともと、CMDでmysqldを実行しているが、上記のようにするとそれを上書きしてしまう。
最後に複数コマンドを実行させたい場合など、.shファイルにまとめて記載しその中でMySQLを起動するmysqldを改めて呼べばいいやと考えたが、シェルファイル経由で呼び出すと権限周りでうまくコンテナが起動しなくなる…

docker-comose.yml
services:
  db:
    build:
      context: .               # ★Dockerfileへのパス指定
      dockerfile: Dockerfile   # ★Dockerfileへのパス指定
    container_name: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      TZ: ${TZ}
    ports:
        - ${DB_PORT}:3306
    volumes:
        - db-store:/var/lib/mysql
        - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf
        - ./script:/docker-entrypoint-initdb.d 
volumes:
  db-store:

コンテナの起動と確認

実行

docker-compose up -d

確認

ログ確認

[Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running~の行で実行されていることが確認できます。

mysql  | 2022-02-13 11:52:14+09:00 [Note] [Entrypoint]: Giving user user access to schema hoge-db
mysql  | 
mysql  | 2022-02-13 11:52:14+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/initDB.sql
mysql  | 
mysql  | 
mysql  | 2022-02-13 11:52:14+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/initShell.sh
mysql  | ### initialize start ####
mysql  | ### initialize end   ####
mysql  | 
mysql  | 2022-02-13 11:52:14+09:00 [Note] [Entrypoint]: Stopping temporary server
mysql  | 2022-02-13T02:52:14.791132Z 14 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.28).
mysql  | 2022-02-13T02:52:16.878878Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.28)  MySQL Community Server - GPL.
mysql  | 2022-02-13 11:52:17+09:00 [Note] [Entrypoint]: Temporary server stopped
mysql  | 
mysql  | 2022-02-13 11:52:17+09:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.

また、.shファイルに記載したechoの内容が出力されていることも確認できました。

DB確認

テーブルが作成できデータも追加されていることが確認できました。

スクリプトファイルの起動は、本当にコンテナ起動時なのか?

タイトルでは、コンテナの初回起動時と記載したが…正確には/var/lib/mysqlのDBファイル有無で判定している模様。

なので、tmpfs:へマウントしている場合や、マウントしていたvolumeを消した場合はコンテナを消していなくても毎回実行してくれる。

Discussion

shuuuunshuuuun

yamlファイル修正

★ ローカルのscriptディレクトリにマウントします
の部分ですが
./script:ではなく、./conf/script:のような気がしますがいかがでしょうか?

ましろましろ

コメントありがとうございます!
ディレクトリ構成のインデントが少しずれていたので、修正しました。

scriptディレクトリは、docker-compose.ymlと同階層にあることを想定してyamlファイルを作成していますので、./script:の表記のままで正しいです。

shuuuunshuuuun

そうでしたか!失礼いたしました。
とても参考になりました、ありがとうございます。