はじめに
先日、私自身が経験したことではあるのですが
- Intel Mac で元々
mysql5.7-debian
のイメージを使って業務をしていた - (諸事情で)一時的にM1 Macを使わねばならなくなり、同じdockerfileを使って環境を作ろうとした
- 爆死した。
はて…dockerってローカルの環境差を埋めて、誰でも彼でも同じ環境で開発ができる素敵クジラちゃんじゃないのか?
解決策はググれば結構転がっているのだけど、何故そうなるのかよく分からなかったのでちょっと探求してみました。
とりあえず、爆死しがちなパターンとその解決策
なんかの間違いでdocker mac m1
でググってここにたどり着いてしまった方に申し訳ないので
とりあえず、爆死パターンと解決策。(を転記)
爆死しがちなのは、利用者もきっと多いmysql 5.x系
ですね。5.6とか5.7とか。
私が今回爆死したのも上述の通りmysql 5.7-debian
です。
で、爆死するときはこんな感じ。(M1 Macは手放したので、参照記事からまんまぶっこ抜かせてもらいました。)
$ docker-compose up -d --build
〜略〜
=> ERROR [internal] load metadata for docker.io/library/mysql:5.6 2.4s
------
> [internal] load metadata for docker.io/library/mysql:5.6:
------
failed to solve with frontend dockerfile.v0: failed to create LLB definition: no match for platform in manifest sha256:~~~~~~ not found
ERROR: Service 'db' failed to build : Build failed
解決策としては色々あるのですが、私自身これでいけましたっていうのが
platform: linux/amd64
ってオプションを差してあげること。
# ##### mysql #####
mysql:
image: mysql:5.7
platform: linux/amd64 #これを入れるだけで何とかなったりする
build:
context: .
dockerfile: ./docker/mysql/Dockerfile
container_name: foo_project_mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=foo
- MYSQL_USER=bar
- MYSQL_PASSWORD=hogefuga1111
- TZ=Asia/Tokyo
これを差せば大丈夫っていう理由がよく分かりません。
CPU アーキテクチャとDocker Image
そもそも、このplatformオプション
は何を指しているのか。linux/amd64
って何よ?についてもう少し。
linux/amd64 って何よ?
CPUアーキテクチャ のことを指すようです。
ここでいうアーキテクチャは、命令セットアーキテクチャ(Instruction Set Archtecrure) のことを指し、CPUに命令する機械語の仕様を定めたものです。
amd64 ってのはそのアーキテクチャの一種(通称)で、Intel Macはこのamd64というアーキテクチャのCPUが乗っています。(厳密に言ってしまうと色々語弊があるっぽいですがamd64 = intelのCPU
というイメージで大体OK)
じゃあM1 Macはどうなのかというと、arm64という、ほとんどのスマホやタブレットで使用されている米ARM社仕様のCPUが乗っています。
そのため、Intel Mac とM1 Macとでは、そもそもマシンを動かす機械語の仕様レベルで異なるわけです。
こういう俺様仕様なところ、本当appleって気持ち悪いから嫌い。Lightning端子とか早々に滅びろ。
dockerのマルチアーキテクチャサポート機能
dockerでは、イメージをpullしてくるときに、マシンのOSに対応するイメージを選択してpullしてくれる機能が備わっています。本筋のLinuxはもちろん、mac / windowsなど様々なCPUやOSでの利用者を想定してのことでしょう。たぶん。
たとえばこんなん。
linux/amd64 と linux/arm64 の2種があります。
普段はまったく意識しないと思いますが、docker側でOSやアーキテクチャを判定してその環境に合ったイメージをpullしてくれます。
さて問題のmysql5.7
はどうでしょう。
amd64(Intel系)しかありません。残念です。
M1 Macでmysql5.7が爆死する理由
ここまでのことを踏まえると、M1 Macにmysql5.7のイメージをpullしようとするとエラーが出る原因は
- M1 / Intel ではそもそもCPUアーキテクチャが違うので、根本的にマシンの動かし方が違う
- dockerでは、マルチアーキテクチャサポート機能により、マシンに合わせて自動でイメージをpullしようとする
- しかし、mysql5.7にはarm64用のイメージが存在しないため、うわぁぁぁぁ!!!!ってなる
- 爆死する。
というように考えられそうです。
お待たせしましたplatformオプション
もう大体お察しと思いますが、platformオプション
はpullしてくるイメージのアーキテクチャを指定するオプションです。
なので、M1環境ではあれどamd64用(しかないから仕方なく)のイメージをpullしてねとdocker-compose.ymlに記載してあげることで何とか環境が立ち上がるということのようです。
# ##### mysql #####
mysql:
image: mysql:5.7
platform: linux/amd64 # M1=amd64環境だけど、amd64用のイメージをpullするぜ!を指定。
build:
context: .
dockerfile: ./docker/mysql/Dockerfile
container_name: foo_project_mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=foo
- MYSQL_USER=bar
- MYSQL_PASSWORD=hogefuga1111
- TZ=Asia/Tokyo
ちなみに。
マシンのアーキテクチャとdockerイメージのアーキテクチャが異なっている(今回の場合amd64 と arm64)のに問題なく動くの?という疑問が残りますが、ここはdocker側の方でよしなに動くようにしてくれているようです。
(ソースを見つけることができませんでしたホントすみません)
以前は、QEMUなどのエミュレータを入れてあげる必要があったようですが。
参考リンク