MySQL道普請便り

第167回 M1搭載MacのDockerでMySQLを動かしてみる

この記事を読むのに必要な時間:およそ 3 分

2020年11月に発表されたMacBook Airから搭載されているM1チップというCPUがあります。こちらは従来のMacに搭載されていたCPUがx86/64の命令セットとは異なり,ARMアーキテクチャを採用しているという違いがあります。発売から1年以上たち,インテル製のCPUを搭載したMacがラインナップから無くなったので,次もしMacを購入するとなるとM1チップ搭載のMacを購入することになります。

今回は,その際に問題が起こりがちなDockerでの開発環境の構築について,紹介していきたいと思います。

DockerでMySQLを動かしてみる

まずは,dockerコマンドでMySQLを指定して動かしてみようと思います。

% docker run  -p 3307:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:latest
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
docker: no matching manifest for linux/arm64/v8 in the manifest list entries.
See 'docker run --help'.
% 

このようにエラーになってしまいました。エラーの内容としては,⁠mysqlのdockerイメージにはlinux/arm64/v8用のコンテナがありません」という内容になります。

M1向けのDocker for Macでは,linux/amd64向けのコンテナを動かすことができるので,platformオプションを使用して実行してみましょう。

% docker run --platform linux/x86_64 -p 3307:3306 -e MYSQL_ROOT_PASSWORD=password-d mysql:latest
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
〈省略〉
%mysql -h127.0.0.1 -uroot -ppassword -P3307
mysql>

すでに3306ポートで動いているMySQLがいると,そちらにつながった場合に勘違いしてしまうため,今回は3307をホストのportとして指定をしています。mysqlクライアントで接続が確認できたので,立ち上がったことがわかります。ちなみに1回linux/x86_64向けのimageをpullしておくと,次回以降は空気を読んで起動をしてくれます。

% docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=password -d mysql:latest
  WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

表示されている警告は「linux/arm64/v8用のCPUが載っているPC上で,linux/amd64用のコンテナを動かしていてCPUの命令セットが一致してません」という内容になります。警告が常に出続けているような環境だと,本当に大事な警告を見落とすことにも繋がりかねないので,--platform linux/x86_64を指定するようにしたほうが良いでしょう。

ということで,簡単にDockerでMySQLのコンテナを建てることができました。

Docker Composeでのplatform指定に関して

Docker Composeは,Dockerと合わせて開発環境の中でよく使われる事が多いと思います。Docker Composeで指定するときは以下のような形で追加します。

version: '3'
services:
  mysql:
    image: mysql:latest
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 127.0.0.1:3308:3306

platform指定を入れても既存のLinuxユーザやインテルMacのユーザやWindowsユーザは影響を特に受けないので,platform指定を導入するだけで対応ができます。

MySQL5.7を起動してみる

続いて、latestではなくて,MySQL 5.7を起動してみましょう。

version: '3'
services:
  mysql:
    image: mysql:5.7
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 127.0.0.1:3308:3306

docker-compose upをしてみます。

% docker-compose up
〈省略〉
mysql_1  | information that should help you find out what is causing the crash.
untitled_mysql_1 exited with code 2

何やらerrorが出て終了してしまいました。たくさん出ているログを眺めていると,以下のようなエラーログが出力されていることがわかります。

mysql_1  | 2022-03-10T23:41:09.939403Z 0 [ERROR] InnoDB: Linux Native AIO interface is not supported on this platform. Please check your OS documentation and install appropriate binary of InnoDB.

Linux Native AIO interfaceがM1向けのDockerでは準備されていないため,エラーが発生しているみたいです。

というわけで,公式ドキュメントでこの設定をoffにする設定を調べたところ,--innodb-use-native-aioオプションが該当しました(公式ドキュメントはこちら⁠。

my.cnfに配置するのでも良いのですが,一旦試してみたいため,commandを下のように書き換えて実行してみましょう。

version: '3'
services:
  mysql:
    image: mysql:5.7
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 127.0.0.1:3308:3306
    command: mysqld --innodb_use_native_aio=0

ディスクが中途半端に残っている可能性もあるので,一旦docker-compsoe down -vをしてボリュームを消してから実行します。

% docker-compose down -v
% docker-compose up
〈省略〉
mysql_1  | Version: '5.7.37'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

ということで,5.7のイメージを立ち上げることができました。

ちなみに,8のイメージでも同様のエラーは発生していて,自動的にdisabledになっている模様です。

mysql_1  | 2022-03-10T23:33:20.291472Z 1 [ERROR] [MY-012585] [InnoDB] Linux Native AIO interface is not supported on this platform. Please check your OS documentation and install appropriate binary of InnoDB.
mysql_1  | 2022-03-10T23:33:20.291775Z 1 [Warning] [MY-012654] [InnoDB] Linux Native AIO disabled.

このメッセージはMySQL 5.7でも同様に出ているのですが,5.7のイメージではうまく動いていないようです。

別のイメージを使用する

今回は起動オプションを変更することで対応しましたが,別のイメージを使用することで回避をすることもできます。

MySQL公式が用意しているDockerイメージがあり,こちらを使用すると,MySQL 8.0を使用する場合は,linux/amd64とlinux/arm64/v8のイメージがあるので,お使いのplatformに合わせたイメージをpullしてきて使用することができます。

version: '3'
services:
  mysql:
    image: mysql/mysql-server:latest
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 127.0.0.1:3308:3306

また,こちらのイメージは5.7系も設定を弄ることなく,起動することができます。以下のように設定をしてみましょう。

version: '3'
services:
  mysql:
    image: mysql/mysql-server:5.7
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 127.0.0.1:3308:3306

この設定でdocker-compose upをしてみましょう。

% docker-compose down -v
% docker-compose up
〈省略〉
mysql_1  | 2022-03-11T00:07:29.650417Z 0 [Note] /usr/sbin/mysqld: ready for connections.
mysql_1  | Version: '5.7.37'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server (GPL)

ということで,簡単に現在サポートされているMySQLのバージョン(8.0と5.7系)を立ち上げることができました。MySQL 5.7系を利用されている方はイメージの移行を検討してみてはいかがでしょうか。

まとめ

今回はM1チップが搭載されたMac上でDockerを動かす方法を紹介しました。MySQL 8は意外と簡単に動かせたのではないかと思います。

MySQL 5.7系を使用されている方は,本番でmysql系のイメージを使っていて変更するのが難しく,どうしても本番と開発で同じイメージを使えないと困るといった場合以外は,Dockerイメージ自体の移行を検討しても良いかもしれません。難しい場合は文中で紹介した--innodb-use-native-aioの設定をmy.cnfに入れるか,コマンドを書き換えてオプションに追加するなどの方法を取りましょう。

著者プロフィール

木村浩一郎(きむらこういちろう)

株式会社オプティム 技術統括本部のエンジニア。最近はミドルウェア・インフラ周りのことも少しずつ学習しています。趣味は将棋。好きな戦法は四間飛車。

Twitter:@kk2170