LoginSignup
25
24

More than 5 years have passed since last update.

Docker公式のmysqlイメージを使いつつ初期データも投入する

Last updated at Posted at 2015-02-16

メモです。

Docker公式のmysqlを使いつつ、初期データ投入するのに
少し手間取ったのでメモします
(全部自前で書けばいいじゃん…というのは置いといて)

ディレクトリ構造

ざっくりこんな感じを想定。

APP_ROOT/
    app/
        db/
            setup.sql   >  create文とかinsert文とか
    fig.yml
    fig/
        app/
            Dockerfile
        mysql/
            Dockerfile  > ここから /app/db のSQLを使いたい
    ...

やりたいこととしては、
app用とfig用のディレクトリがあって、
mysql用Dockerfileからapp用のディレクトリ配下にあるSQLファイルを使って
初期テーブル作ったりデータ投入したい。

実現している方法

fig/mysql/Dockerfile

FROM mysql:5.6

# utf8サポート
RUN { \
    echo '[mysqld]'; \
    echo 'character-set-server = utf8'; \
} > /etc/mysql/conf.d/charset.cnf

# setupを追記したentrypoint
COPY docker-entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

fig/mysql/docker-entrypoint.sh

これは 公式のentrypoint.sh にパッチ当ててる感じ。

#!/bin/bash
set -e

if [ "${1:0:1}" = '-' ]; then
    set -- mysqld "$@"
fi

if [ "$1" = 'mysqld' ]; then
    # read DATADIR from the MySQL config
    DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')"

    if [ ! -d "$DATADIR/mysql" ]; then
        if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then
            echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set'
            echo >&2 '  Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?'
            exit 1
        fi

        echo 'Running mysql_install_db ...'
        mysql_install_db --datadir="$DATADIR"
        echo 'Finished mysql_install_db'

        # These statements _must_ be on individual lines, and _must_ end with
        # semicolons (no line breaks or comments are permitted).
        # TODO proper SQL escaping on ALL the things D:

        tempSqlFile='/tmp/mysql-first-time.sql'
        cat > "$tempSqlFile" <<-EOSQL
            DELETE FROM mysql.user ;
            CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ;
            GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ;
            DROP DATABASE IF EXISTS test ;
        EOSQL

        if [ "$MYSQL_DATABASE" ]; then
            echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" >> "$tempSqlFile"
        fi

        if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
            echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" >> "$tempSqlFile"

            if [ "$MYSQL_DATABASE" ]; then
                echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" >> "$tempSqlFile"
            fi
        fi

        echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile"

        ###########################################################
        # ここを追加してる
        # setup
        echo "use $MYSQL_DATABASE;" >> "$tempSqlFile"
        # createやらinsertやら
        cat /db/setup.sql >> "$tempSqlFile"
        ###########################################################
        # start mysql
        set -- "$@" --init-file="$tempSqlFile"
    fi

    chown -R mysql:mysql "$DATADIR"
fi

exec "$@"

fig.yml

app:
  build: ./fig/app
  ...

mysql:
  build: ./fig/mysql
  ports:
    - '3306:3306'
  volumes:
    - ./app/db:/db
  environment:
    MYSQL_USER: username
    MYSQL_PASSWORD: xxx
    MYSQL_ROOT_PASSWORD: xxx
    MYSQL_DATABASE: dbname

やっていることはmysqlコンテナのvolumesで app/db 以下をマウントし、
entrypoint.sh内で その下にあるファイルを実行しているだけ。

APP_ROOTから fig build && fig up すると、初期化されたテーブルやデータが作られているはず。


もっといい方法があれば教えて下さい><

25
24
1

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
25
24