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 を起動できるかと思います。
※ オフィシャルのイメージに対して、文字コードを指定できるようにしてほしいというリクエストが多数上がっているので、オフィシャル側で対応してほしいですね。他に良い方法をご存知の方がいらっしゃったら教えてください。
Entry filed under: Microsoft Azure. Tags: docker, MySQL, utf8.
1.
Shinichi Akiyama (@shakiyam) | 2016年3月7日 10:01 午後
https://hub.docker.com/_/mysql/ の Using a custom MySQL configuration file に記述にあるように、自分で書いた設定ファイルをマウントしてあげれば簡単にできますよ。
2.
Yoshio Terada | 2016年3月8日 10:50 午前
そうなんですね、ありがとうございます。
自分がやった時は作成された DB だけが latin1 になっていたので、作成時も明示し回避しました。