M1macとDocker。


まえがき

前提として、M1Macとは、AppleSiliconを搭載したArm64アーキテクチャCPUのPCである。

つまり、基本的にamd64/x86_64系アーキテクチャのバイナリは読めないし、M1Macでコンパイルしてうまくいったプログラムを配布しても、M1Mac以外では動かないと言ったことが当然起こる。

そこら辺はまぁ、コンパイラとかのオプションで同じソースから別のバイナリを作成すれば問題ない。結構簡単な話ではある。

だが、話は変わってDockerだったらどうだろうか?DockerはZembutsu氏のこちらの資料をみるとこう書かれている。

(なお、CPU amd64/x86_64 用にコンパイルしたバイナリは実行できますが、他の CPU アーキテクチャ向けのバイナリは amd64/x86_64 上では実行できません。例えば Raspberry Pi は ARM というアーキテクチャですので、この hello バイナリは Raspberry Pi でそのまま動きません。バイナリとして実行できない以上、仮に Docker イメージに入れたとしても、この次のセクションで説明する Docker コンテナとして実行はできません。Docker はハードウェアのエミュレーションを行いませんし、ハードウェアを仮想化するような技術でもありません。)

なるほど、やはり動かないと言うことらしい。

なら、実際動かしてみてどうなるか実験してみようじゃないか。

M1MacにDockerDesktopをインストール

M1MacにDockerDesktopをインストールするには、こちらのリンクを踏んでダウンロードする必要がある。

さらに、Rosetta2もインストールしなければならないため、以下のコマンドをShellに叩く

Rosetta2 install
softwareupdate --install-rosetta

すると、しっかりインストールされ、動くようになる。

実際に試す。

以下を試してみた。

docker run
docker run -it python:3.9-alpine python

すると、

なんだ、しっかり動作するじゃないか。
なぜだろう。

...実は単純な話でARMアーキテクチャ用にビルドされたものがDockerHubにちゃんと上がっているのだ。

実際にDockerHubで調べてみた。

なるほど、結構そもそも対応してるのね。と言う結論に。

M1macでビルドしたものをPushしても動かない?

M1Macでビルドしたものはどうなるのだろう。

そりゃまぁPullの時点でアーキテクチャが選択された上で層を重ねていくのだから、
いくらFROM python:3.9-alpineと指定した時点でARMイメージが決定するので、それに層を足してPushしてもリモートのLinuxサーバでは動かすことはできない可能性が高い。(まだ試したことはないが)

これに対する解決策

JenkinsやGoogleCloudBuildとかに任せる

リモートにJenkinsのビルドサーバを建てて、そこからBuildすると言う形がいいかと思われる。
そうすれば、リモートで主に使用されているamd64/x86_64 archの対応ができるので、それで回避すると言う手がある。
普通に考えたらこれでいい気がする。というかそもそもローカルでビルドなんかしたくない。

buildxコマンドを使用する

コンパイラと同様、アーキテクチャ別にbuildしてくれる機能をもつコマンドが実際に実装されているとのこと。
それがbuildxコマンド。詳細はこちら。

Docker Buildx

あとがき

ちなみに、ラズパイとかの関係もあって、正味ARMアーキテクチャなど、さまざまなデバイスで動くようにもう基盤がある程度整っていて、Macが突然M1になったからと言って全然未対応な感じではなかった。なので、M1Macを買ってDockerとかどうしよう...みたいに考えている方でも、安心して欲しい。

あと、基本Rosetta2がなんとかしてくれるし、ここで重い動作させるわけでもないんだし、M1Macだからと言う理由で何か不都合が起こることは、正味このDockerPushが直でできないくらいなものだった。あとはなんとかなる基盤が今の時代全て揃っているので、M1macでも開発環境上、何も問題ないと言える。

やはりコード化と言う原理は最強だった...我々はコードだけを扱えばいいので、下のレイヤーは最悪気にしなくていい。そんな基盤ができている現代社会に感謝したい。