When Docker decided to change the Docker Desktop pricing model I found that, while reasonable, it was an additional reoccurring cost for basic tooling that remained easily accessible and free on other platforms so I set on a search for alternatives.
Ubuntu Multipass is one of numerous alternatives that can replace Docker Desktop on Macs and Windows.
Getting Started
The following steps have been tested on an Intel Macbook w/ 16gb of ram after removing Docker Desktop.
Installing Multipass
Ideally, use brew install multipass
, however there’s currently a bug (sftp server: handle_stat: cannot stat #2203) which results in log files filling your hard drive. As of time of writing it is recommended to use the package referenced in the issue.
Configuring a Shell
The following configuration values can be modified, but those presented have been tested successfully with a large application stack. Additionally, changing the shell name will require changes to commands that follow in this guide.
multipass launch --name development --cpus 4 --mem 8g --disk 100G
Entering the Shell
multipass shell development
All command from this point forward, unless specified otherwise, are to be done from within the multipass shell.
Installing Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
sudo apt install docker-compose
Optionally, Configure Sudoless Docker
sudo apt-get install -y uidmap
dockerd-rootless-setuptool.sh install
echo "export DOCKER_HOST=unix:///run/user/1000/docker.sock" >> ~/.bashrc
source ~/.bashrc
Optionally, Configure AWS
sudo apt install awscli
aws configure
$(aws ecr get-login --no-include-email --region us-west-2)
Probably, Configure GitHub
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
ssh-keygen -t ed25519 -C "your_email@example.com"
cat ~/.ssh/id_ed25519.pub
You can add the new key here: SSH and GPG keys.
Maybe, Transfer Existing Source Code
It may be more or less work to transfer your existing code as there will be configuration differences between Mac and Linux. It’s also possible to run off the mount, but you may experience high cpu usage depending on the application’s disk activities.
On the Mac:
multipass mount ~/git/ development:/home/ubuntu/git-mac/
In the Multipass shell:
cp -Rv git-mac/ git
On the Mac:
multipass umount development
Optionally, Configure Privileged Port Access in the Virtual Machine
While Docker is perfectly happy trying to bind to any port, the Ubuntu install needs some coaxing:
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee -a /etc/sysctl.conf
sudo sysctl --system
You can now start as containers as usual: docker-compose up
As needed, Configure Additionally Software
If you plan to run some things in the container without docker, you may need some extra tools, e.g.:
sudo apt install npm
If you’ve transfered source code, the stored configuration may have environment specific tools which need cleared. For example the package-lock.json
should not be checked in from Linux until you’ve standardized, or it could break Mac installations and the node_modules
should be re-installed.
rm -r ./node_modulesrm package-lock.json
npm install
You can now start non-docker projects as well, e.g. npm start
Finding IP Addresses
Routing could have some new complexity now that the stack has changed. Finding the right IP addresses could pose some challenges. Tinkering will be required, here are some tips.
To see the IP addresses, and other information on the running virtual machines:
multipass info --all
And on the mac:
ifconfig
In some instances, host.docker.internal
and the magic host-gateway
could be useful in your docker-compose.yml
files:
version: '3'
services:
nginx:
extra_hosts:
host.docker.internal: host-gateway
For trickier bits, an environment variable set from .env
could be useful; more info here: Environment Variables in Compose
version: '3'
services:
nginx:
environment:
- ENV_SOME_HOST=${ENV_SOME_HOST}
A set of example docker-compose.override.yml
files could be useful to store in your repositories as there will likely be differences as staff settle on different solutions.
SSH
Since your essentially running virtual machines, you can even setup network access.
In the multipass shell:
sudo adduser someuser
sudo vi /etc/ssh/sshd_config
Ensure settings PasswordAuthentication yes
and PermitEmptyPasswords no
are set.
Restart:
sudo /etc/init.d/ssh restart
Now you can ssh in from the mac:
ssh someuser@your-vm-ip
Further Reading
Without the obfuscation of the virtual machine, tools like ansible
can now be used on top of multipass
or ssh
to provison new environments with reusable runbooks. Ansible for DevOps: Server and configuration management for humans would be an great read on that topic. Additionally, it’s assumed the reader has familiarity with Linux considering the pre-existing knowledge from Docker, but to learn more about Ubuntu I’d suggest picking up Ubuntu Linux Unleashed.
Conclusion
While Docker Desktop is very convenient, Ubuntu Multipass is likely an upgrade and a swiss army knife for development. The multipass
command can be used to run any number of Linux instances, which can run docker images and other applications or development environments on a Mac. You can even expose a full desktop and access it via remote desktop if you are brave enough. While that’s cool, a great side effect is that each instance is stored in an image file, which can be pre-configured and shared to new and existing engineers.