Running Docker on MacOS

Running `docker` on MacOS is fun. This is because MacOS requires a Linux VM of some sort for to actually run the containers.

Docker's Logo

Table of contents

The “Problem”

Running docker on MacOS is fun. This is because MacOS requires a Linux VM of some sort for to actually run the containers.

This isn’t my favorite thing, but as far as I can tell there’s just no way to get around that. The VM is required and causes some slowdown in comparison with a “bare-metal” runtime on Linux.

I’m not the first and definitely not the last to come to this conclusion.

Solutions

I’ve used all of the following in some capacity over the years and here are my thoughts.

Docker Desktop

Docker Desktop is the standard way to install Docker on MacOS. It’s probably the most familiar and just works OOTB. It also gives you access to docker extensions as well as a nice GUI for reading and managing your containers.

Pros

Cons

  • Hate having to start a GUI to load the VM
  • Licensing and subscriptions? HA!
  • Hate the menubar icon

Setup

  • Install docker - brew install docker
  • Install docker-desktop - brew install --cask docker

Rancher Desktop

Rancher desktop is a similar to Docker desktop in the way that they both have a nice GUI for you to manage.

Rancher definitely doesn’t have the same feature-set (lack of extensions) but makes up for it in their K8s support.

Pros

  • Simpler UI
  • Can run K8s

Cons

  • Still hate the menubar icon
  • No docker-compose support OOTB
  • No docker-buildx support OOTB

Setup

  • Install Rancher - brew install --cask rancher

Colima

Colima is a CLI only docker runtime. It still has a VM but gives you control over it’s specs. You can make multiple VMs with different specs and only run the ones you need when you need them.

Have a small web-server? Run it with 2 CPUs and 2gb of RAM and 10gb of storage. Training a LLM? Run it with 8 CPUs, 8gb of RAM, and 100GB of storage.

Those scenarios are 100% made-up, but do you get the idea.

I can scale the docker runtime for the project I’m currently working on.

Pros

  • No GUI or menubar icon
  • Can run K8s

Cons

  • Non-default docker.sock location meaning some apps (lazydocker, ctop) may not be able to find the daemon

Setup

  • Install Colima - brew install colima
  • Start Colima - colima start

Remote Docker Host

Why run a Linux VM if you can run it on Linux natively?

A while back I converted my old Linux desktop (year of the Linux desktop anyone?) to a “server” (by unplugging peripherals and put it by the router) that runs a number of docker services. A self-hosted “homelab” if you will.

Pros

  • No docker image/container/networks/volumes etc on my local machine
  • Can customize the runtime to your needs

Cons

  • Manual setup required. 2 options.
    • Run docker context use remote or set DOCKER_CONTEXT=remote in your shell.
    • Set DOCKER_HOST=ssh://username@remote-machine
  • Network connection could be a bottleneck
  • Requires another machine and a VPN (or other remote access solution) when not on the same network

Setup

  • Setup docker on another machine
  • Install docker - brew install docker
  • SSH into the machine to establish keys
  • Create a context - docker context create remote --description "Remote Machine" --docker "host=ssh://username@remote-machine"
    • Choose one of the following depending on you situation
      • Set DOCKER_HOST=ssh://username@remote-machine
      • Set DOCKER_CONTEXT=remote
      • Run docker context use remote

I use the following zsh snippet to toggle between remote and local setups.

Warning! It’s definitely still a WIP and only works for the current shell session.

dockerRemoteConnect () {
  desired_context=${1:-remote}

  # Use these when lazydocker isn't working
  export DOCKER_HOST=ssh://username@remote-machine

  # Use one of the following when you've created a "remote" context and you aren't worried about lazydocker
  # export DOCKER_CONTEXT=$desired_context
  # docker context use $desired_context

  echo "Success!
  Now using docker context ($DOCKER_CONTEXT) on remote host ($DOCKER_HOST).
  Try 'docker ps' to see all running containers"
}

dockerRemoteDisconnect () {
  unset DOCKER_HOST
  unset DOCKER_CONTEXT

  desired_context=${1:-colima}
  docker context use $desired_context

  echo "Success!
  Now using docker context ($desired_context) on local host.
  Try 'docker ps' to see all running containers"
}

Other

I have not tried the solutions below, maybe one day.

  • podman seems promising but I see lots of reports of docker-compose not working
  • minikube primarily for k8s, but comes with a docker runtime as well

Conclusion

I’m sure there are a number of other alternatives and different way I could’ve used the other solutions to solve my needs, but I like that…

  • remote-host option doesn’t require me to have docker running things on my local machine
  • colima let’s me easily start/stop/edit docker runtimes for my current needs

Sure, I could disable menubars icons, determine runtime specs in Docker Desktop, and go from there, but I really enjoy the terminal only workflow.

Update: 2024-01-30

Orbstack has entered the scene and quickly becomes a contender for a colima replacement.