M1 mac で MySQL コンテナを使う方法

つい先日、我が家にM1 Macが届きました。
「Dockerまわりがつらいよ」という話は聞いていましたが、私もしっかりと MySQL のコンテナが立ち上がりませんでした。
軽くググっても「むむ・・・?🤔」と思う結果だったので、自分でしっかりまとめてみようと思います。

そもそもの問題

M1 MacDocker 公式の MySQL コンテナをそのまま使おうとすると、以下のエラーが出て使用できません。

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

これは雑に説明すると、「このコンテナは ARM64 に対応してないよ」ということです。
そして、 M1 チップは ARM64 アーキテクチャを採用しています。

解決する方法

色々と調べてみると、主に3つの方法があるようです。

  • arm64v8/mysql イメージを使用する
  • mysql/mysql-server イメージを使用する
  • --platform linux/amd64 オプションを使用する

順番に見ていきましょう。

MySQLのみを使いたいなら arm64v8/mysql

Docker の公式リポジトリに、 AMD64 (Intel の CPU のアーキテクチャ) 以外のプラットフォームの案内があります。

github.com

それによると、

Some images have been ported for other architectures, and many of these are officially supported (to various degrees).

とあり、程度差はありますが、公式にサポートされているイメージがあることがわかります。
そして、その MySQL のイメージが arm64v8/mysql です。

hub.docker.com

使い方は公式の MySQL イメージとほぼ同じなので、イメージを書き換えるだけで使用できます。

チーム開発をしていて、 Intel CPU の人と M1 チップの人の両方がいる場合、 docker-compose.override.yml を使用すると便利です。

# docker-compose.yml

version: '3'  
services:  
    mysql:  
        # デフォルトでは mysql イメージを使う  
        image: 'mysql:8.0'  
        ports:  
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:  
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'  
            MYSQL_DATABASE: '${DB_DATABASE}'  
            MYSQL_PASSWORD: '${DB_PASSWORD}'  
            MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'  
        volumes:  
            - 'sailmysql:/var/lib/mysql'
        networks:  
            - sail
        healthcheck:  
            test: ["CMD", "mysqladmin", "ping"]  

    some_other_containers:  
        ...  
# docker-compose.override.yml

version: "3"  
services:  
    mysql:  
        # M1 チップの人は arm64v8/mysql で上書きする  
        image: 'arm64v8/mysql:8.0-oracle'  

一方で、 mysql はOSの選択肢が debianoracle があるのに対し、 arm64v8/mysqloracle しかありません。
なので、 監視ツールなどで Debian でしか動かないツールを使いたい場合には使用できません。
また、本番は Debian のコンテナで動いていて、なるべく本番に近い環境で開発したい場合も向きません。

設定ファイル差異をなくすなら mysql/mysql-server

Docker 公式のイメージは ARM64 をサポートしていませんが、 MySQL 公式のイメージは ARM64 をサポートしています。
MySQL 公式のイメージが mysql/mysql-server です。

hub.docker.com

このイメージを使用すれば、M1 チップでも (docker-compose.override.yml を書かずとも) 同じ docker-compose.yml で動かすことができます。

一方で、 Docker 公式のイメージではないため、 MYSQL_PASSWORD のような環境変数による初回設定には対応していないようです。
そのため、既存で Docker 公式のイメージを使用しており、環境変数による初回設定を行っている場合は、mysql/mysql-server へのマイグレーションはコストがかかりそうです。

MySQL コンテナをカスタマイズしてるなら --platform linux/amd64

MySQL コンテナで MySQL 以外のミドルウェアをインストールしていたり、込み入った設定をしていたりなど、他イメージに移行することが難しい場合があります。
その際に有効なのが --platform linux/amd64 オプションです。

Docker for Mac の公式ページに、以下のように書かれています。

docs.docker.com

Not all images are available for ARM64 architecture. You can add --platform linux/amd64 to run an Intel image under emulation. In particular, the mysql image is not available for ARM64. You can work around this issue by using a mariadb image.

雑に和訳すると、「全部のイメージが ARM64 で動くわけじゃないよ。 --platform linux/amd64 オプションを付ければ Intel イメージをエミュレーション上で動かすことができるよ。特に mysql イメージは ARM64 じゃ動かないよ。 mariadb のイメージを使って解決することもできるよ。」
といった感じでしょうか。

docker-compose.yml を使用する場合は、以下のように書くといけます。

# docker-compose.yml

version: '3'  
services:  
    mysql:  
        image: 'mysql:8.0'  
        platform: 'linux/amd64'  

ひとつ気になることがあります。
docker-compose file v3 では、ドキュメントから platform オプションが消えています。 (v2 にはあります。)
ですが、リリースノートを見ても「 platform オプションを消した」という記述は見当たりません。
現状サポートされているのか、 非推奨な機能なのかわからない状態です。

ところで、このオプションを指定するとエミュレーション上で動作するということが重要です。エミュレーションをするということは、以下のことを指します。

なので、 --platform linux/amd64 オプションを使用するのは、最終手段にすることをおすすめします。