Boosting Local Development Efficiency: Replacing Docker Desktop with Lima?

This article examines a viable Docker Desktop alternative designed to meet the specific needs of developers using Mac.

IMPORTANT: we recommend a full drive backup to an external drive before proceeding in case of any issues, as otherwise data loss is guaranteed.

Meet Lima VM

Lima launches Linux virtual machines with automatic file sharing, port forwarding, and containerd. It can be considered as an unofficial “macOS subsystem for Linux”, or “containerd for Mac”.

While Lima project introduces its own CLI command “nerdctl” (contaiNERD ctl), it can be used with docker with minimal configuration.

Shortest path to Docker Desktop replacement

1/ Backup existing databases

Currently, Lima VM allows mounting host folders and it works great until a docker container tries to execute chown or chmod on the mounted folder - currently not supported but is actively being worked on by the Lima team.

There is a workaround for this where we can use docker named volumes instead of mounting host folders directly. Note that where a container does not require chown or chmod,you can continue mounting folders directly.

We have been using folder mounting extensively. Accordingly, we had to export databases when creating new docker named volumes as volumes are initially empty.

2/ Clean up existing Docker artefacts

Once you are happy you have all the backups you require, you can clean up existing Docker artefacts (note: these operations will remove all data previously managed by Docker Desktop.)

IMPORTANT: we recommend a full drive backup to an external drive before proceeding in case of any issues, as otherwise data loss is guaranteed.

You will need to stop and remove any running containers prior to executing below.

# remove all docker named volumes
docker volume prune

# remove all containers
docker container prune

# remove all images
docker image prune
docker image prune -a

# remove all networks
docker network prune

# for a good measure now remove everything
docker system prune --volumes

3/ Remove Docker Desktop

Bye-bye, Docker Desktop:

rm -rf /Applications/Docker.app

rm -f /usr/local/bin/docker
rm -f /usr/local/bin/docker-machine
rm -r /usr/local/bin/docker-machine-driver*
rm -f /usr/local/bin/docker-compose

rm -rf /usr/local/share/boot2docker
rm -rf ~/.boot2docker

pkgutil --forget io.docker.pkg.docker
pkgutil --forget io.docker.pkg.dockercompose
pkgutil --forget io.docker.pkg.dockermachine
pkgutil --forget io.boot2dockeriso.pkg.boot2dockeriso

It is possible few will return an error. You can safely ignore those.

Phew — all that data gone. You did backup, didn’t you?

4/ Setup Lima VM

Lima comes with its own CLI tool “nerdctl” which can be used as a replacement for docker CLI. It also supports the same set of commands as docker CLI. In our case, we wanted to use docker-compose. To enable a seamless transition, we decided on configuring Lima VM to be a replacement for both docker and docker-compose, with the added benefit of it running rootless docker daemon — yes, those rootful docker daemons can inflict damage.

5/ Install Lima VM

Life is short and so are the Lima installation instructions: brew install lima

6/ Lima configuration file

Below is a configuration file we will use to start a lima VM with docker rootless daemon.

Create the file docker.yaml with below contents (based on the example here):

# Example to use Docker instead of containerd & nerdctl
# $ limactl start ./docker.yaml
# $ limactl shell docker docker run -it -v $HOME:$HOME --rm alpine

# To run `docker` on the host (assumes docker-cli is installed):
# $ export DOCKER_HOST=$(limactl list docker --format 'unix://{{.Dir}}/sock/docker.sock')
# $ docker ...

# This example requires Lima v0.8.0 or later
images:
# Hint: run `limactl prune` to invalidate the "current" cache
- location: "https://cloud-images.ubuntu.com/impish/current/impish-server-cloudimg-amd64.img"
arch: "x86_64"
- location: "https://cloud-images.ubuntu.com/impish/current/impish-server-cloudimg-arm64.img"
arch: "aarch64"
mounts:
- location: "~"
writable: true
- location: "/tmp/lima"
writable: true
# containerd is managed by Docker, not by Lima, so the values are set to false here.
containerd:
system: false
user: false
provision:
- mode: system
script: |
#!/bin/sh
sed -i 's/host.lima.internal.*/host.lima.internal host.docker.internal/' /etc/hosts
- mode: system
script: |
#!/bin/bash
set -eux -o pipefail
command -v docker >/dev/null 2>&1 && exit 0
export DEBIAN_FRONTEND=noninteractive
curl -fsSL https://get.docker.com | sh
# 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: user
script: |
#!/bin/bash
set -eux -o pipefail
systemctl --user start dbus
dockerd-rootless-setuptool.sh install
docker context use rootless
probes:
- script: |
#!/bin/bash
set -eux -o pipefail
if ! timeout 30s bash -c "until command -v docker >/dev/null 2>&1; do sleep 3; done"; then
echo >&2 "docker is not installed yet"
exit 1
fi
if ! timeout 30s bash -c "until pgrep rootlesskit; do sleep 3; done"; then
echo >&2 "rootlesskit (used by rootless docker) is not running"
exit 1
fi
hint: See "/var/log/cloud-init-output.log". in the guest
portForwards:
- guestSocket: "/run/user/{{.UID}}/docker.sock"
hostSocket: "{{.Dir}}/sock/docker.sock"
message: |
To run `docker` on the host (assumes docker-cli is installed):
$ export DOCKER_HOST=unix://{{.Dir}}/sock/docker.sock
$ docker ...

Note the section in the file:

- location: "~"
writable: true

While it is recommended to have a read only mount of your home directory, we found many workflows depended on having write access.

To start lima VM, execute: limactl start ./docker.yaml

This will download and provision the lima VM with docker daemon ready to serve your Dockerized needs.

7/ Docker and Docker Compose

We have removed docker and docker-compose used by Docker Desktop, and hence we need to reinstall them. Lucky for us, it is pretty simple:

brew install docker
brew install docker-compose

All you need to do now is point docker CLIs to use lima VM, execute — replace with your own: export DOCKER_HOST=unix:///Users/<username>/.lima/docker/sock/docker.sock

Congratulations — you have removed Docker Desktop, and have almost an identical solution for your Dockerized workflows.

Rancher Desktop

If you are interested in kubernetes, it might be worthwile exploring: https://rancherdesktop.io/ and https://github.com/rancher-sandbox/rancher-desktop

Podman

Lima VM supports podman workflows and these will be explored in another article. An example configuration file can be found here.

Caveats

Containers executing chown or chmod will fail on the host mounted folders - use docker named volumes instead.

All data now resides inside the lima VM, in most instances, you can start and stop the VM without losing data (unless there is a bug in lima VM) — keep backups going!

Warning!

Executing: lima remove docker will remove the VM and ALL data (remember that now all docker images and containers reside inside this VM), thus deleting the VM will in kind remove all containers and images you might have.

IMPORTANT: we recommend a full drive backup to an external drive in case of any issues, as otherwise data loss is guaranteed.

Information has been prepared for information purposes only and does not constitute advice.

--

--