Archive for 3月, 2016

MySQL on Docker with UTF-8 CHARSET

ちょっとした自分用メモです。
以前、デモで MySQL の Docker コンテナを作成した際、オフィシャルの Docker イメージを利用した場合、たとえ、下記を /etc/mysql/conf.d/charset.cnf に指定しても作成した DB のテーブルが latin1 になってしまう問題にあいました。

     [mysqld]'; 
      skip-character-set-client-handshake
      character-set-server=utf8
      collation-server=utf8_general_ci
      init-connect = SET NAMES utf8
      [client]
      default-character-set=utf8

そこで、docker-entrypoint.sh を追記して、DB 作成時に明示的に utf8 を渡すように変更しました。
(docker-entrypoint.sh の追記箇所)

# 前略
# 引数で書く所をファイル中に記載
DATADIR="/var/lib/mysql"
MYSQL_ROOT_PASSWORD="supersecret"
MYSQL_DATABASE="artist-db"
MYSQL_USER="mysql"
MYSQL_PASSWORD="mysql"
MYSQL_CHARSET="utf8"

# 中略 
                if [ "$MYSQL_DATABASE" ]; then
                        echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ${MYSQL_CHARSET:+CHARACTER SET $MYSQL_CHARSET} ;" >> "$tempSqlFile"
                fi
# 後略

これで、Docker コンテナの MySQL で UTF-8 を扱えるようになるかと思います。

MySQL 用の Dockerfile

FROM mysql:5.7

RUN { \
      echo '[mysqld]'; \
      echo 'skip-character-set-client-handshake'; \
      echo 'character-set-server=utf8'; \
      echo 'collation-server=utf8_general_ci'; \
      echo 'init-connect = SET NAMES utf8'; \
      echo '[client]'; \
      echo 'default-character-set=utf8'; \
    } > /etc/mysql/conf.d/charset.cnf

COPY ./docker-entrypoint.sh /tmp/entrypoint.sh
COPY ./start-up.sh /tmp/start-up.sh
RUN chmod a+x /tmp/entrypoint.sh
RUN chmod a+x /tmp/start-up.sh

ENTRYPOINT ["/tmp/start-up.sh"]
EXPOSE 3306
CMD ["mysqld"]

DB を作成するためのスクリプトファイル(docker-entrypoint.sh)

#!/bin/bash
set -e

# if command starts with an option, prepend mysqld
if [ "${1:0:1}" = '-' ]; then
        set -- mysqld "$@"
fi
# 引数で書く所をファイル中に記載
DATADIR="/var/lib/mysql"
MYSQL_ROOT_PASSWORD="supersecret"
MYSQL_DATABASE="artist-db"
MYSQL_USER="mysql"
MYSQL_PASSWORD="mysql"
MYSQL_CHARSET="utf8"

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 'Initializing database'
                mysqld --initialize-insecure=on --datadir="$DATADIR"
                echo 'Database initialized'
                
                # 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
                        -- What's done in this file shouldn't be replicated
                        --  or products like mysql-fabric won't work
                        SET @@SESSION.SQL_LOG_BIN=0;
                        
                        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\` ${MYSQL_CHARSET:+CHARACTER SET $MYSQL_CHARSET} ;" >> "$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"
                
                set -- "$@" --init-file="$tempSqlFile"
        fi
        
        chown -R mysql:mysql "$DATADIR"
fi

exec "$@"

MySQL の起動用スクリプト(start-up.sh)

#!/usr/bin/env bash
/tmp/entrypoint.sh mysqld --datadir=/var/lib/mysql --user=mysql 

ファイルを作成したのち、Dockerfile を保存している場所で下記のコマンドを実行して Docker イメージを作成

$ docker build -t tyoshio2002/mysql:5.7 .

作成した Docker イメージを起動

$ docker run -d -p 3306:3306 tyoshio2002/mysql:5.7

で MySQL を起動できるかと思います。

※ オフィシャルのイメージに対して、文字コードを指定できるようにしてほしいというリクエストが多数上がっているので、オフィシャル側で対応してほしいですね。他に良い方法をご存知の方がいらっしゃったら教えてください。

2016年3月7日 at 2:02 午後 2件のコメント


Java Champion & Evangelist

Translate

ご注意

このエントリは個人の見解であり、所属する会社の公式見解ではありません

カレンダー

2016年3月
 123456
78910111213
14151617181920
21222324252627
28293031  

カテゴリー

clustermap

ブログ統計情報

  • 1,288,547 hits

Feeds

アーカイブ