Although I’m a Linux user, I also recently bought a Mac Air M1, and I wanted to use Docker (a big part of my TDD book) to ensure that my projects based on Docker work on m1 as well.
I then went to the Docker website for macOS and downloaded the version for the Apple m1 chip:
Then, I continued with the installation:
Let’s start it. Although m1 is fast, starting Docker Desktop takes some time.
Although I’m already familiar with Docker (on Linux), I decided to follow the “getting started” tutorial, which is well done:
At least, I’m sure that Docker is working on this machine.
The desktop app is well done, with a few sections to inspect Images, Containers, etc.
And, of course, there’s the “Preferences” section. For the moment, I stick with the defaults.
From the terminal, I ran the usual “hello-world” image:
I also tried to run a Ubuntu container. Inside the container, I verified that it’s running an “aarch64” version instead of the x86 one (“amd64”).
I also installed “file” to verify that it’s using aarch64 binaries (“arm64”):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
bettini@MacBook-Air ~ % docker run -it ubuntu bash Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu 56a2caa6b2c6: Pull complete Digest: sha256:7cfe75438fc77c9d7235ae502bf229b15ca86647ac01c844b272b56326d56184 Status: Downloaded newer image for ubuntu:latest root@1a39080bfd2b:/# uname -a Linux 1a39080bfd2b 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux root@1a39080bfd2b:/# ls bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var root@1a39080bfd2b:/# file /bin/sh bash: file: command not found root@1a39080bfd2b:/# apt update ... root@1a39080bfd2b:/# apt install file ... The following additional packages will be installed: libmagic-mgc libmagic1 The following NEW packages will be installed: file libmagic-mgc libmagic1 ... Get:1 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 libmagic-mgc arm64 1:5.41-3 [257 kB] Get:2 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 libmagic1 arm64 1:5.41-3 [85.0 kB] Get:3 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 file arm64 1:5.41-3 [21.6 kB] ... root@1a39080bfd2b:/# file /bin/sh /bin/sh: symbolic link to dash root@1a39080bfd2b:/# file /bin/dash /bin/dash: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=dbaa633ef3cec5113c7513a028b74e595e0012a7, for GNU/Linux 3.7.0, stripped root@1a39080bfd2b:/# exit |
From the Desktop application, you can quickly enter a container with a terminal:
Now, it’s time to verify that my Java projects based on Docker work as expected.
Java & Maven
This is a simple Maven example (a pom.xml file) that uses the https://github.com/fabric8io/docker-maven-plugin to start and stop a MySql container:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>example-docker-mysql</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <pluginManagement> <plugins> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.40.0</version> <extensions>true</extensions> <configuration> <showLogs>true</showLogs> <images> <image> <alias>database</alias> <name>mysql:8.0.29</name> <run> <wait> <log>MySQL init process done. Ready for start up.</log> <time>200000</time> </wait> <env> <MYSQL_ROOT_PASSWORD>apasswd</MYSQL_ROOT_PASSWORD> <MYSQL_DATABASE>adatabase</MYSQL_DATABASE> <MYSQL_USER>auser</MYSQL_USER> <MYSQL_PASSWORD>anotherpasswd</MYSQL_PASSWORD> </env> <ports> <port>${mysql.port}:3306</port> </ports> </run> </image> </images> </configuration> </plugin> </plugins> </pluginManagement> </build> </project> |
Run “mvn docker:start” to start a MySql container with a random mapped port. The command will wait for the container to be ready (it looks for a “ready” string within 20 seconds). After the command succeeds, the container will be running in the background. Run “mvn docker:stop” to stop the started container.
To avoid errors in this shape:
1 2 |
[ERROR] : could not get native definition for type `POINTER`, original error message follows: java.lang.UnsatisfiedLinkError: Unable to execute or load jffi binary stub from `/var/folders/5c/90l1wfls2xl7_xvqxqvnm3jw0000gn/T/`. Set `TMPDIR` or Java property `java.io.tmpdir` to a read/write path that is not mounted "noexec". [ERROR] Can't load library: /Users/bettini/tmp/tdd-book-docker/docker-compose-java-example/jffi12716628233976915029.dylib |
You need a recent version of the https://github.com/fabric8io/docker-maven-plugin. For example, 0.38.1. It also works with the current latest version, 0.40.2.
Actually, the first time I tried this project, it did not work (not because of the above error), but after a recent update, it started to work, maybe because of this added link:
1 2 |
ls -l /var/run/docker.sock lrwxr-xr-x 1 root daemon 38 Nov 9 07:48 /var/run/docker.sock -> /Users/bettini/.docker/run/docker.sock |
Note that not all the images are available for this architecture “aarch64”. For example, if you try to use this older version of “mysql”, you get this error:
1 2 3 |
docker pull mysql:5.7 5.7: Pulling from library/mysql no matching manifest for linux/arm64/v8 in the manifest list entries |
However, you can force the intel architecture for an image, as documented here https://docs.docker.com/engine/reference/commandline/run/, e.g., with this environment variable correctly set:
1 |
DOCKER_DEFAULT_PLATFORM="linux/amd64" |
For example, for the above Maven project:
1 2 3 4 5 6 7 8 9 |
DOCKER_DEFAULT_PLATFORM="linux/amd64" mvn docker:start [INFO] Scanning for projects... [INFO] [INFO] ------------------< com.example:example-docker-mysql >------------------ [INFO] Building example-docker-mysql 0.0.1-SNAPSHOT [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- docker-maven-plugin:0.40.0:start (default-cli) @ example-docker-mysql --- [WARNING] DOCKER> The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested |
If you now enter the container, you can verify that you’re running an x86_64 image:
1 2 3 |
sh-4.2# uname -a Linux cf9d5b28744a 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux sh-4.2# |
However, such images will run slower because they are emulated:
Testcontainers
I also use Testcontainers to start Docker containers from the JUnit tests in my projects.
For example, I’m using this example from my TDD book, https://github.com/LorenzoBettini/it-docker-mongo-example, and it works out of the box.
Eclipse Docker Tooling
Currently, the Eclipse plugin for Docker, Docker Tooling, does not work: it cannot connect to Docker. This has been reported (https://github.com/eclipse-linuxtools/org.eclipse.linuxtools/issues/61), and a patch is available to make it work: follow the instructions detailed here https://github.com/eclipse-linuxtools/org.eclipse.linuxtools/issues/61#issuecomment-1326838270. I tested it, and it works:
To summarize, using Docker on macOS m1 seems to work fine! 🙂
I came across your post. It is very well written. It was able to get me through a few issues I had with my Mac Mini M1. The only outstanding issue I still see with running Docker on a M1 or M2 is the lack of USB pass through from host to container. This support works perfectly well on a Windows or Linux host. But for whatever reason Docker for M1/M2 does not support it.