lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

Dockerで稼働するMySQLの文字コードを設定する話

概要

ASP.NET Core MVCを使用した簡単なことをTwitterにつぶやくモノを作っていて
開発環境のDBにDocker上で稼働するMySQLを使っています。

つぶやく際にTweet内容をDBに登録しており文字化けが発生してしまったのでMySQL文字コードを変更して対応したメモです。

目次

環境

  • MacOS Mojave Version 10.14.3
  • .Net Core SDK Version 2.2.104
  • Docker Version 18.09.2
    • Docker image : MySQL 5.7(公式)

参考サイト様

事象

下記のようなFormにツイート内容を記入しツイートします。 その過程でツイートの記録を残すためDB上にデータを残しています。
しかし、DBに登録されたデータが文字化けしてしまうと言う事象です。

  • 参考画像
    下記のようなFormからツイート内容を登録します。 f:id:HM_Atlas:20190303201535p:plain

  • DBデータ
    上記の画面から登録/更新を行ったデータが下記です。
    (まあ、登録時点で文字化けしてるので更新もクソもないですが...)

mysql> select * from TODOAPP.Task;
+----+---------+-------+---------------+
| id | task    | state | TweetResultid |
+----+---------+-------+---------------+
|  5 | ?       |     1 |             1 |
|  6 | ?       |     1 |             1 |
|  7 | ?       |     0 |             1 |
|  8 | ?       |     0 |             1 |
|  9 | ??????? |     0 |             2 |
+----+---------+-------+---------------+
  • 該当のツイート
    ツイート+該当データをDBに登録すると言う動作なので問題ないですが
    該当データを更新する際にDBからデータを取得すると文字化けしたデータしか取得できないので下記のような文字化けしたツイートになってしまいます。

原因

MySQL文字コード設定がUTF-8となっていないため。

DcokerのMySQL公式イメージを使用しているのですがMySQLの設定を何もしていなかったために文字コード設定が下記の様に初期値となっていました。

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

参考:Latin-1について

ラテン文字用の文字コードらしい。詳しくは調べてない。

ISO/IEC 8859-1 - Wikipedia

対策

通常であればmy.cnf文字コードを指定して、再起動してやればいいのですがDockerで動かしてるのでそうも行きません。
(コンテナ内でviとかnanoが使えなかったので諦めた。)

Dockerイメージからコンテナを作成する際にホスト側にMySQL用の.cnfファイルを用意しファイルを配置したディレクトリをマウントします。
(DockerHubのMySQLイメージのページを確認すると起動オプションでも指定できるようですが私は確認していません。)

DockerのMySQL公式イメージはコンテナ起動時に/etc/mysql/conf.d配下の.cnfファイルを読み込んでくれるようです。
そこでホスト(ローカル)にcustom.cnfを用意して起動時にマウントします。

.cnfファイルの用意

  • /tmp/dockerdir/custom.cnf
[mysql]
default-character-set=utf8

[mysqld]
character-set-server=utf8

ディレクトリをマウントしてMySQLコンテナを起動

$ docker run -v /tmp/dockerdir:/etc/mysql/conf.d/ --name twe-todo -e MYSQL_ROOT_PASSWORD=password -d -p 33306:3306 mysql:5.7

マウントする際は-v <ホストパス>:<コンテナパス>で指定します。

文字コード設定の確認

文字コードが変更されていることが確認できました。

mysql> show variables like "%char%";
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

DB再作成

手順は省きますがスキーマを作成しdotnet efコマンドを使用してテーブルを作成します。

動作確認

文字化けせずにツイートできたことが確認できました。
また、データ上も文字化けせずに登録されていることが確認できます。

mysql> select * from Task;
+----+-----------------------------+-------+---------------+
| id | task                        | state | TweetResultid |
+----+-----------------------------+-------+---------------+
|  2 | 文字コードとの戦い          |     1 |             1 |
+----+-----------------------------+-------+---------------+

トラブルシュート

dockerコンテナ起動時のログ確認

custom.cnf文字コード設定を追加した後、dockerコンテナがエラーで起動していませんでした。
起動時のログは下記コマンドで確認可能です。

# コンテナID確認
$ docker ps -a
# ログ確認
$ docker logs <コンテナID>

課題

業務でもmy.cnfをいじることはあったんですがすでに設定されている設定値を変更したり手順書があったりで全然身についてませんでした。

正直ググったまま書いてあることを忠実に実行した感じなので文字コードの設定に関して理解できたわけじゃない。 と言うより各項目の公式リファレンスを見つけることができなかった。

雑感

やっと開発環境が整った感じがします...