Did you know it is possible to run x86_64 Docker containers on an ARM-based M1 mac? It’s quite staightforward with Multipass and Docker (if you are new to Multipass, check out my Multipass for Docker containers on macOS post from a few months ago).
Things may change come macOS 13, which will allow Running Intel Binaries in Linux VMs with Rosetta!
Testing with Hello World
- Start Multipass.app
- If the Docker container has not been run before, then
multipass launch dockerfollowed by
multipass alias docker:dockerto setup an alias.
- If the container is already present but stopped, then either run
multipass start dockeror start it from the menu bar.
- Next run the hello-world sample with
multipass docker -- run --platform amd64 --rm hello-world
- Make sure hello-world reports that its running the
(amd64)image instead of
Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64).
Testing with IBM Db2
For another quick test, I thought I’d start up IBM Db2, which is compiled only for
s390x (Power and Z) but not ARM. FYI, I posted a detailed guide on Running Db2 Data Server Manager in a container a couple of years ago.
The commands in this test are executed in a Shell instance in the container directly,
multipass shell docker.
First, trying Db2 without the
docker run -itd --name db2x86 --privileged=true -p 50000:50000 \ -e LICENSE=accept -e DB2INST1_PASSWORD=1234 -e DBNAME=testdb \ ibmcom/db2
... will give the error:
docker: no matching manifest for linux/arm64/v8 in the manifest list entries.
Next, trying with the
--platform parameter... this time, Docker downloads the x86 images and manages to run Db2 properly:
docker run -itd --name db2x86 --privileged=true -p 50000:50000 \ -e LICENSE=accept -e DB2INST1_PASSWORD=1234 -e DBNAME=testdb \ --platform amd64 ibmcom/db2
You can check Db2 intialization progress with
docker logs -f db2x86, which should complete successfully with:
(*) All databases are now active. (*) Setup has completed.
Timeout Starting Docker
multipass start docker fails with this error:
start failed: The following errors occurred: docker: timed out waiting for response
Then it might be the “dreaded macOS firewall issue”. You can either try to:
- Add a Firewall exception to “Allow incoming connections” for
Multipass.app, from System Preferences > Security and Privacy > Firewall > Firewall Options
- Or disable the Firewall altogether, which works reliably for me...
This Issue #2387:Firewall randomly messing with Multipass networking on macOS has more details on this known issue.
Docker HTTP Timeout
If you are getting the error below upon
docker run or
docker: Error response from daemon: error parsing HTTP 408 response body: invalid character '<' looking for beginning of value: "<html><body><h1>408 Request Time-out</h1>\n Your browser didn't send a complete request in time.\n</body></html>\n".
Then it could be related to the Maximum Transmission Unit (MTU) network setting, and this Stack Overflow answer led me to the solution.
To determine the Ethernet interface in use for Internet connections, check the welcome message when the docker VM starts:
Welcome to Ubuntu 21.10 (GNU/Linux 5.13.0-46-generic aarch64) IPv4 address for docker0: xxx IPv4 address for enp0s1: yyy IPv6 address for enp0s1: zzz
enp0s1 is the route to the Internet, so the fix is:
sudo ip link set dev enp0s1 mtu 1400
I encountered this when my firewall was still turned on, so I do not know the root cause...