Docker on Lima is one of the alternative solutions to Docker Desktop for Mac.
Many people have already described the steps to set up for that.
In addition to such a standard setup, this guide describes how to set up a Docker environment which can run multi-arch images.
For example, you will be able to run linux/amd64 images on your M1 Mac.
- Assume that Homebrew is already installed:
$ brew -v Homebrew 3.4.9 - Install Lima:
$ brew install lima ... $ lima -v limactl version 0.10.0
To configure Lima VM itself, default.yaml may be helpful.
Here we will explain minimal changes only.
- Download docker.yaml.
$ curl -O https://raw.githubusercontent.com/lima-vm/lima/3190530a8e0f10b4000efdebcdfdc2a799da65fa/examples/docker.yaml - Add the following lines into
docker.yaml. This script runs tonistiigi/binfmt to enable QEMU emulation for Docker Engine:My# NOTE: you may remove the lines below, if you prefer to use rootful docker, not rootless systemctl disable --now docker apt-get install -y uidmap dbus-user-session +- mode: system + script: | + #!/bin/bash + # enable docker cpu emulation + # cf. https://github.com/lima-vm/lima/blob/master/docs/multi-arch.md + docker run --privileged --rm tonistiigi/binfmt --install all - mode: user script: | #!/bin/bashdocker.yamlis here. - Launch Lima VM:
$ limactl start --tty=false ./docker.yaml - Verify your setup:
Congratulations! Now you have already been able to run both images for Arm (# Show the list of VMs host$ limactl list docker NAME STATUS SSH ARCH CPUS MEMORY DISK DIR docker Running 127.0.0.1:50084 aarch64 4 4GiB 100GiB /Users/YourName/.lima/docker # Enter to the shell of VM (guest) host$ limactl shell docker # Verify the architecture of VM machine guest$ uname -a Linux lima-docker 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:57:31 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux # Trying to run the `hello-world` image on Docker guest$ docker pull hello-world guest$ docker image inspect hello-world --format '{{.Architecture}}' arm64 guest$ docker run --rm hello-world ... 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (arm64v8) ... # The above example runs the image for native architecture. # Next, we will run the image for the other architecture (e.g. for Intel CPUs). guest$ docker image rm hello-world guest$ docker pull --platform linux/amd64 hello-world guest$ docker image inspect hello-world --format '{{.Architecture}}' amd64 guest$ docker run --rm --platform linux/amd64 hello-world ... 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) ...linux/arm64/v8) and for Intel (linux/amd64).
In the previous step, we have been able to use Docker in the Lima VM. Next, we will configure the host to have direct access to the Docker Engine.
- Install Docker CLI in the host:
host$ brew install docker ... host$ docker -v Docker version 20.10.14, build a224086349 - Configure:
- Option.a) Create new context:
Then enable the context named
host$ docker context create lima \ --docker "host=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')"lima:host$ docker context use lima - Option.b) Set
DOCKER_HOSTenvironment variable; add the following lines into your~/.zshrc:Then applyexport DOCKER_HOST=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')
~/.zshrcchanges:host$ . ~/.zshrc
- Option.a) Create new context:
- Verify; If you have run the
hello-worldimage in the previous section, it should be listed here:host$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 3 months ago 13.3kB
We have already installed Buildx in the Lima VM. But it is not available directly from the host.
host$ limactl shell docker docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
rootless * docker
rootless rootless running linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
...
host$ docker buildx ls
docker buildx ls
docker: 'buildx' is not a docker command.
See 'docker --help'
You will need to install Buildx on the host manually.
- Install (cf. https://github.com/docker/buildx#manual-download):
host$ mkdir -p ~/.docker/cli-plugins host$ curl -fsSL -o ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.8.2/buildx-v0.8.2.darwin-arm64 host$ chmod +x ~/.docker/cli-plugins/docker-buildx - Verify:
host$ docker buildx ls NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS lima * docker lima lima running linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6 ...
- Install (cf. https://github.com/docker/compose#linux)
host$ curl -fsSL -o ~/.docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/v2.5.1/docker-compose-darwin-aarch64 host$ chmod +x ~/.docker/cli-plugins/docker-compose - Verify:
host$ docker compose version Docker Compose version v2.5.1
-
By default, the Lima VM will not start when you boot your Mac. If you want to start the Docker VM automatically, you can use LaunchAgents.
- Create
~/Library/LaunchAgents/lima-docker.plist:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>launch-lima-docker</string> <key>ProgramArguments</key> <array> <string>/bin/zsh</string> <string>-lic</string> <string>( limactl stop -f docker; sleep 5; limactl start docker ) > ~/Library/LaunchAgents/lima-docker.plist.log 2>&1</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <false/> <key>AbandonProcessGroup</key> <true/> </dict> </plist>
- Load it:
Then, reboot your mac. The VM$ launchctl load ~/Library/LaunchAgents/lima-docker.plistdockerwill start automatically after you login.
Or, also you can also use crontab.
$ crontab -e # Set PATH # This is an example. Make sure it is appropriate for your environment. PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin # Automatically starts the `docker` VM on Lima. @reboot ( limactl stop -f docker; sleep 5; limactl start docker; ) > /dev/null 2>&1 - Create
-
If you want to show the list of supported architectures, then run:
host$ limactl shell docker sudo docker run --rm --privileged tonistiigi/binfmt { "supported": [ "linux/arm64", "linux/amd64", "linux/riscv64", "linux/ppc64le", "linux/s390x", "linux/386", "linux/mips64le", "linux/mips64", "linux/arm/v7", "linux/arm/v6" ], "emulators": [ "qemu-arm", "qemu-i386", "qemu-mips64", "qemu-mips64el", "qemu-ppc64le", "qemu-riscv64", "qemu-s390x", "qemu-x86_64" ] } -
Some application will ignore docker contexts. In this case, rootless docker will cause problems. The simplest workaround is to make
/var/run/docker.sockas a symlink to the socket of rootless docker. Add the following shell script todocker.yaml:dockerd-rootless-setuptool.sh install docker context use rootless +- mode: user + script: | + #!/bin/bash + set -eux -o pipefail + DOCKER_SOCK_DEFAULT=$(docker context inspect default --format='{{.Endpoints.docker.Host}}' | cut -d '/' -f 3-) + DOCKER_SOCK_ROOTLESS=$(docker context inspect rootless --format='{{.Endpoints.docker.Host}}' | cut -d '/' -f 3-) + sudo rm -f "$DOCKER_SOCK_DEFAULT" + sudo ln -s "$DOCKER_SOCK_ROOTLESS" "$DOCKER_SOCK_DEFAULT" probes: - script: | #!/bin/bash -
Can Docker on Lima be a complete replacement for Docker Desktop for Mac?
- A quick survey has shown that many of the features that I wanted worked. However, there are still some unstable parts. I am not sure if I can recommend it for production use.
- File sharing (Bind mount):
- Since Lima v0.10.0, new mount option
mountType: 9phas been added. I have tested it and it seems to be better thanreverse-sshfs. However, this feature is still experimental. See lima-vm/lima#726 and others for more details. - By setting the
writableproperty totrue, we can read and write the host's file system using bind mount. - A large amount of access to bind-mounted directories will occasionally cause data corruption. For example, this happened when many intermediate files were output in such a directory during program compilation. You should minimize such access, if possible.
- I guess this issue is related to the performance issue of bind mount in docker on mac.
- There is a workaround that changes the consistency option. For example, in
devcontainer.json:The important part is// devcontainer.json { ... + "workspaceMount": "type=bind,source=${localWorkspaceFolder},target=/workspaces/${localWorkspaceFolderBasename},consistency=delegated", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", }consistency=delegated. cf. https://docker-docs.netlify.app/docker-for-mac/osxfs-caching/ - However, this workaround doesn't seem to work perfectly well.
- There is a workaround that changes the consistency option. For example, in
- Since Lima v0.10.0, new mount option
- Network access:
- Simple test: Run
$ docker run --rm -p 3000:80 nginx, then access http://localhost:3000 in your browser (e.g. Safari).
- Simple test: Run
- The following tools seems to work with this setup: