docker-composeでのMySQL環境構築(M1 Mac対応版)

はじめに

以前、docker-composeでMySQLのサーバーを建てる記事を書きました。

p5750-tech.hateblo.jp

しかし、これはM1 Macでは動作しません。今回はM1 Mac/Intel Macの両方で動作するようなdocker-compose.ymlに修正していきます。

まずはエラーの確認

M1 Macで以前の記事のコードを実行してみます(MySQLのバージョンだけ最新に変えてます)。

FROM mysql:8.0.28
RUN apt-get update && \
    apt-get install -y tzdata locales && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen
ENV LANG en_US.UTF-8

CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
version: '3.8'
services:
  db:
    build: ./docker/mysql
    env_file:
      - .env
    ports:
      - "${MYSQL_PORT}:3306"
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
$ docker compose build
[+] Building 0.9s (3/3) FINISHED
 => [internal] load build definition from Dockerfile                    0.0s
 => => transferring dockerfile: 32B                                     0.0s
 => [internal] load .dockerignore                                       0.0s
 => => transferring context: 2B                                         0.0s
 => ERROR [internal] load metadata for docker.io/library/mysql:8.0.28   0.8s
------
 > [internal] load metadata for docker.io/library/mysql:8.0.28:
------
failed to solve: failed to solve with frontend dockerfile.v0: failed to create LLB definition: no match for platform in manifest sha256:fc77d54cacef90ad3d75964837fad0f2a9a368b69e7d799665a3f4e90e600c2d: not found

ぱっと見て何がいけないのかわかりにくいので、docker runでミニマムに実行してみます。

$ docker run -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.28
Unable to find image 'mysql:8.0.28' locally
8.0.28: Pulling from library/mysql
docker: no matching manifest for linux/arm64/v8 in the manifest list entries.
See 'docker run --help'.

no matching manifest for linux/arm64/v8 in the manifest list entries.

とあるので、arm64/v8用のイメージが存在しないことによるエラーであるとわかります。

公式イメージをM1 Macで動かす

FROMのオプションに --platform=linux/x86_64 をつけることで、x86_64環境用のイメージを使います。

--- a/docker/mysql/Dockerfile
+++ b/docker/mysql/Dockerfile
@@ -1,4 +1,4 @@
-FROM mysql:8.0.28
+FROM --platform=linux/x86_64 mysql:8.0.28
 RUN apt-get update && \
     apt-get install -y tzdata locales && \

これで起動できました。

参考にした記事には5.7の場合はLinux Native AIO interfaceのエラーが発生するのでもうひと手間加える必要があると書いてありましたが、今(2022年4月26日) mysql:5.7.37 で試してみたところ普通に動作しました。不思議。

別のイメージを使う

ここまで使ってきた mysql は Docker 公式のイメージですが、 mysql/mysql-server というMySQL公式のイメージもあり、こちらは --platform オプションなしでも動作しました。

こちらはタイムゾーンロケール環境変数で変更できるので、 mysql イメージのときのように Dockerfile でtzdataやlocalesをインストールする必要はありません。これらを変更するだけであればDockerfileを書く必要がないのもメリットですね。

version: '3.8'
services:
  db:
    image: mysql/mysql-server:5.7.37-1.2.7-server
    environment:
      MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
      MYSQL_DATABASE: "${MYSQL_DATABASE}"
      MYSQL_USER: "${MYSQL_USER}"
      MYSQL_PASSWORD: "${MYSQL_PASSWORD}"
      MYSQL_ROOT_HOST: "%"
      TZ: "Asia/Tokyo"
      LANG: "en_US.UTF-8"
    command: [ mysqld, --character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci ]
    ports:
      - "${MYSQL_PORT}:3306"
    volumes:
      - ./docker/mysql/data:/var/lib/mysql

TZタイムゾーンLANG で言語を設定しています。 MYSQL_ROOT_HOST はrootに別のコンテナから接続するのに必要な設定です。

特にplatformを指定しなくても、これだけで正常に起動できます(5.7はx86_64しかないようですが、8.0にはarm64用のイメージもありました)。

おわりに

M1 MacMySQLのコンテナを立てる方法として

  • 公式イメージで --platform オプションを使う方法
  • mysql/mysql-server を使う方法

の2つを試しました。

MySQL5.7の場合はmysqlmysql/mysql-serverx86_64用イメージになるのでどちらでもいいかもしれませんが、MySQL8の場合は mysql/mysql-server を使うとハードウェアに合ったイメージを使うことができてよさそうです。

個人的には mysql/mysql-server だと Dockerfile 不要なのが棚ぼた的に嬉しかったのもあり、こちらに乗り換えています。

余談

私がM1 Macを購入した当時はM1でMySQLを使う記事があまり見つからなくて苦労したのですが、気づけば結構増えていますね。

参考文献

zenn.dev

gihyo.jp