TL;DR
DockerでRailsとDBのコンテナを作成しWebアプリケーションを作成してたところ
ブラウザ上では日本語が文字化けしないがdbコンテナの中に入ってmysqlにログインすると ????
に文字化けしている現象に遭遇した。
対象読者 or 前提条件 or 環境
- DockerでMySQLコンテナを使用するマルチバイトなひと
まずは調査
「Docker mysql 文字化け」でぐぐってみるとどうやら character_set_server=utf8
でないと発生するという記事が大量にヒットする。
Docker公式イメージのMySQLで文字コードを指定するのエントリを参考に過去にdocker-compose.ymlには対応を実装していたのでどうやらこれが問題ではなかった。
そもそもなにが原因で文字化けしてるのかがわからなかったので調べてみた。
$ mysql
mysql> status;
--------------
mysql Ver 14.14 Distrib 5.7.19, for Linux (x86_64) using EditLine wrapper
Server characterset: utf8
Db characterset: utf8
Client characterset: latin1
Conn. characterset: latin1
となっていた。
この逆パターン(Server&DBがlatin1、Client&Connがutf8)はあったがこの状態を解決する記事は結局見つけられなかった。
ただ原因はclientとconnが問題で、だからこそターミナルでmysqlにログインしたときだけ日本語が文字化けしていたのだということがわかった。
問題解決
さて問題はどうやってこのlatin1をutf8に変更するか?だがいろいろ調べた結果どうやらコマンドでは変更することができないらしいという結論に達した。
ではどうするか?となったときに対処方法は最早1つしか思いつかなかった、つまりmy.cnf
を/etc/mysql/conf.d/
以下にマウントするのだ。
実は/etc/mysql/my.cnf
があってこのmy.cnf
内では/etc/mysql/conf.d/*
以下のcnfファイルを参照する記述がある。
よって以下の内容になるようにmy.cnf
をマウントすることで設定を上書きしてもらうという寸法である。
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
そしてこの状態をdocker-compose.yml
に以下のように指定したところ上手くマウントされMySQLにログインしても文字化けしなくなった。
version: '2'
services:
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
volumes:
- ./data:/var/lib/mysql
- ./my.cnf:/etc/mysql/conf.d/my.cnf
environment:
MYSQL_DATABASE: [データベース名]
MYSQL_USER: [DBユーザ]
MYSQL_PASSWORD: [DBパスワード]
MYSQL_ROOT_PASSWORD: [ルートパスワード]
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/www/[サービス名]
ports:
- '3000:3000'
depends_on:
- db
redis:
image: redis:latest
ports:
- "6379:6379"
command: redis-server --appendonly yes
本来はDockerfileに切り出してそちらでCOPY
かADD
するのが多分いちばんスマートというか問題がない。