❝

TL;DR: brew install colima && colima start && docker context use colima swaps the engine behind your existing docker CLI. You continue using the same commands, but you don't need a desktop app anymore.

The Docker Desktop app is the standard way to run containers on a Mac. It runs Docker Engine (which includes the Docker daemon) inside a Linux VM and provides the GUI, configuration, and macOS integration around it. Its use is subject to Docker's subscription terms, including paid requirements for certain larger organizations.

colima runs the same Docker daemon without the app. The daemon runs inside a Lima VM (a Linux virtual machine that colima uses to host the daemon), and you drive it with the same docker CLI you already use every day. This issue covers the switch from Docker Desktop, the everyday commands, and what you give up.

Switching from Docker Desktop

The switch is surprisingly easy. After installing with brew install colima, do:

colima start
docker context use colima
docker run hello-world

If you already have the docker CLI, that is all you have to do. On a clean machine, install the client first (using brew install docker). The CLI is a separate formula from the daemon, which colima provides in this case. Then run colima start; it boots the Lima VM with sensible defaults. (You installed it with brew install colima, which also pulled in Lima.)

You can still keep Docker Desktop if needed (both engines can cohabit). But if Docker Desktop was running before the switch, you have to quit it, since two daemons cannot share the same default socket path. Later, you can switch back to using Docker Desktop by running docker context use desktop-linux.

Run a web server

After the hello-world test, let's go further with a container running a web server.

The Python image ships a working HTTP server in its standard library, and the server can serve a directory of your actual files. The whole loop is done using the following single command:

docker run -d --name demo -p 8765:8000 \
  -v "$PWD:/srv" \
  python:3-slim python -m http.server 8000 --directory /srv

That command pulls the image, starts the server detached (-d), names it demo, publishes port 8000 to the host's 8765, and bind-mounts your current directory into the container across the VM boundary. Then check the result:

curl -s localhost:8765
docker logs demo
docker ps

You can confirm that the beginning of the HTTP response (obtained with the curl command) includes the line <h1>Directory listing for /</h1>, which matches the directory being served, and the rest contains the listing of that directory's files. Also, if you edit a file in your current directory and re-run curl, the change should appear.

When done running that container, clean up using:

docker rm -f demo

One more container: a reverse proxy

hello-world and the Python server both run alone. Real stacks run more than one container, with containers talking to each other. We can use Docker Compose for such cases, and colima supports it. Also we have Caddy, a packaged web server which, with two lines of config, reverse-proxies to any other container on the same network.

For the demonstration, take the following config for Compose; save it as compose.yaml in the directory you want served:

services:
  demo:
    image: python:3-slim
    command: python -m http.server 8000 --directory /srv
    working_dir: /srv
    volumes:
      - ./:/srv
    ports:
      - "8765:8000"

  web:
    image: caddy:2
    depends_on:
      - demo
    ports:
      - "8080:80"
    volumes:
      - ./caddy:/etc/caddy

Then take the following Caddy config and save it one directory down at ./caddy/Caddyfile:

:80 {
  reverse_proxy demo:8000
}

(The caddy directory must exist; mkdir -p caddy before saving the Caddyfile.)

Now, making sure you are in the directory where compose.yaml is, run everything:

docker compose up -d
# then, verify:
curl -s localhost:8080 | head -2
# to stop:
docker compose down

After docker compose up -d starts both containers detached, the curl reaches Caddy on localhost:8080 and returns the same directory listing the Python server served on its own. docker compose down stops both containers and removes the network that Compose created for them.

In the Caddyfile, reverse_proxy demo:8000 works because Caddy and the demo container run inside the VM, where they can reach each other directly.

Sizing the Lima VM

You can use --cpu, --memory, and --disk, CLI flags that you set at start time:

colima start --cpu 4 --memory 8 --disk 60

--cpu and --memory are the VM's share of the machine. --disk is the VM's disk image size, in GB. To change any of them later, stop colima and start it again with the new values, or edit the generated template directly using colima start --edit.

What you give up

  • The GUI. No menu bar icon, no dashboard, no settings window. With colima, everything is based on commands and the config template.

  • A settings slider for resource changes. Resizing means a stop and a start with flags (or editing the template), not moving a slider while the daemon runs.

  • Desktop's extensions ecosystem. The extension marketplace is Desktop-specific; there is nothing colima-side to replace it.

  • First-start cost. The initial colima start creates the Lima VM and pulls the Linux image; this may take minutes, instead of seconds. But subsequent starts are faster.

❝

colima is not in the book, but it is a natural addition to The Modern CLI Stack for those who run containers from a Mac and want the same docker CLI without a desktop app. If you want the full toolkit, The Modern CLI Stack is a free ~50-page PDF + EPUB covering mise, starship, zoxide, fzf, broot, ripgrep, fd, bat, eza, delta, tldr, atuin, lazygit.

Reply

Avatar

or to participate