How to build Intel Docker containers on Mac M1

Lima is a tool that is very often described as the containerd for Mac. With it you can
run a linux operating system alongside your Mac. It features automatic port forwarding,
seemless file sharing, and supports various linux distributions such as AlmaLinux,
Alphine, Arch Linux, Debian, Fedora, SUSE, Oracle Linux, Rocky and Ubuntu. By default
it comes with containerd and nerdctl, but you can use Lima for non-container tasks
as well.

Mac computers with Apple sillicon

Late 2020 Mac released their first systems with Apple Silicon, a custom designed
Arm-based chip for Mac. The most recent editions of the Macbook pro uses the M1
Apple Silicon processor, whereas it used to be an Intel processor. Their new
custom chipset is unable to process Intel instructions without the aid of additional
software. Applications that have been built for Intel can still be used on a Mac
with the use of emulation software that Apple has made available: “Rosetta 2”.

The Rosetta 2 software, however, has some limitations as to what it can process.
In particular it’s often incompatible with virtual machine applications, which brings
us to the next topic: Docker.

Challenges with Docker using the new M1 processor

A significant portion of developers use Docker for their local development work.
By default Docker does support emulating amd64 by specifying the --platform linux/amd64
flag for building and running containers. Most images and packages are available for amd64,
but not every package has transitioned. I recently had a use case where I absolutely needed
an Intel architecture for a container. The options I had were either building the image on
my old Macbook, or spin up a virtual machine with the correct architecture.

Setting up Lima to build docker images

And in comes Lima. My goal was to set up an environment in which I could build Docker
containers as I was used to, without having to transfer files to another system or
resort to my old Macbook. Lima is the perfect tool to do so.

You can install lima on MacOS using brew: brew install lima.
Once it’s installed: limactl start and choose:

Open an editor to review or modify the current configuration

On the line where it says arch: null replace null with x86_64. By default it will
use the architecture of your operating system (in the case of an M1 it’s aarch64).
After you save the configuration file, type the following commands:

limactl shell default
sudo systemctl start containerd
sudo nerdctl run --privileged --rm tonistiigi/binfmt --install all
exit

This is required for the guest OS to be able to execute non-native binaries.
And that’s it for installation! Lima comes with containerd and nerdctl for building docker images.

Creating an alias to make building Docker images with Lima easy

The method of building Docker containers is normally as follows:
lima nerdctl build ., where lima nerdctl is a drop-in replacement for the docker command.
To keep my current way of working, I’ve added an alias:

alias docker='lima nerdctl'

Type:

echo alias docker=\'lima nerdctl\' >> ~/.zprofile to make this alias persistent.
Now you can use the docker command as usual, but build and run images using an emulated
Intel processor. You can change the name of the alias (e.g. dockerr) if you want to
keep being able to use your native architecture to build images.

When you run a docker image through lima, port forwarding is automatically arranged, so
any port your container listens on is exposed on localhost. In addition, you can create
several lima instances and use them concurrently. The limactl start command has an
optional argument: limactl start foobar will create a lima instance called foobar,
and with LIMA_INSTANCE=foobar lima [command] you can execute commands on that specific instance.

Drawbacks

By default your Mac home directory is read only. This is intentional. Write support on Mac
home directories is experimental. You can yolo it by editing the ~/.lima/default/lima.yaml file
and set writable to true and restart lima (limactl stop && limactl start). Having said that,
the lima home directory is writable, so if you simply place your code there it negates the need
to make the Mac home directory writable.

Another drawback is the speed. Especially if you’re compiling stuff in your container you really
notice the difference between a native architecture and an emulated one. Unfortunately that is not
to change any time soon.

Share this article: Tweet this post / Post on LinkedIn