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.
Table of contents
The “Problem”
Running docker
on MacOS is not fun. This is because MacOS (and probably Windows?) requires a Linux
VM of some sort for to actually run the containers. This is because Docker runs on top of Linux’s LXC capabilities.
House of cards? Or, Shoulders of the Giants?
This isn’t my favorite thing, but as far as I can tell there’s 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.
- https://dev.to/ericnograles/why-is-docker-on-macos-so-much-worse-than-linux-flh
- https://news.ycombinator.com/item?id=34098367
- https://www.reddit.com/r/docker/comments/vwq724/wtf_is_up_with_docker_desktop_on_macos/
- https://medium.com/homullus/beating-some-performance-into-docker-for-mac-f5d1e732032c
Solutions
I’ve used all of the following in some capacity over the years and here are my thoughts.
Update: 2024-01-30
Orbstack has entered the scene and quickly becomes a contender for a colima replacement.
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.
Setup
- Install docker -
brew install docker
- Install docker-desktop -
brew install --cask docker
- Launch
Docker Desktop
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
- 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 ia config files. 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 an LLM? Run it with 8 CPUs, 16gb of RAM, and 100GB of storage.
Those scenarios are 100% made-up, but do you get the idea.
I like that I can scale the docker runtime for the project I’m currently working on.
Pros
- Easily configure multiple VMs
- 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? no.) 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 setDOCKER_CONTEXT=remote
in your shell. - Set
DOCKER_HOST=ssh://username@remote-machine
- Run
- 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 on your mac -
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 to tell docker to use the new context. Which one depends on your situation
- Set
DOCKER_HOST=ssh://username@remote-machine
- Set
DOCKER_CONTEXT=remote
- Run
docker context use remote
- Set
- Choose one of the following to tell docker to use the new context. Which one depends on your situation
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.