An alternative Docker installation with Multipass on macOS without using Docker for Mac

5 min read

1276 words

Last week I received an email from the Docker Team which said that Docker for Mac (the software which also comes with a GUI) will be forbidden for commercial use when the company has more than 250 employees AND makes more than $10 million per year. To use it commercially the company has to get licenses for every developer using it, starting at $5/month. This made me think what an alternative could be for devs that don’t want to use Docker for Mac anymore, since I read a lot of posts that many devs don’t even need it. Most of them interact via CLI anyway.

I stumbled across a nice article from Josh Gorneau where he uses multipass to host his Docker VM. In this case, it is a Ubuntu 20.04 installation. So a couple of commands will be similar to Josh’s article such as the VM configuration used in this post. So let’s start with setting up multipass.

Install Multipass

Multipass is a project made available by Canonical[1] also develops and publish the Ubuntu[2] Linux distribution. So install it either from the website or via homebrew. If you don’t have the Docker CLI yet, install it too

brew install multipass docker

Creating an SSH Key

Since we will connect to our VM via SSH we need a new SSH key that will be imported while setting up the VM. To do so we can use ssh-keygen like in the following. I will create a new one since I use just one for every service I connect to. Follow the prompts to generate a key. Mine will be called docker-multipass. Since macOS and Ubuntu are pretty similar in creating SSH keys you can also follow the instructions over at DigitalOcean.

➜  ~ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/user/.ssh/id_rsa): /Users/user/.ssh/docker-multipass
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/user/.ssh/docker-multipass.
Your public key has been saved in /Users/user/.ssh/docker-multipass.pub.
The key fingerprint is:
SHA256:LjhUL0bZ8lXf9iIrOPF1EXjAJguNu3YbvUVH2tUHcak user@domain
The key's randomart image is:
+---[RSA 3072]----+
|         o .oo+o+|
|       oo o.+..==|
|      = .o.+ .++=|
|     o +...  Eoo+|
|    . o S. .o.o..|
|   . o oo+o..+.. |
|    o ..+.oo.o   |
|     . . ....    |
|                 |
+----[SHA256]-----+

To get the generated public key which will be imported to the Ubuntu VM on the setup you can use cat /Users/user/.ssh/docker-multipass.pub. Copy the output since you will need it in the next step.

The VM Config

In the following, we will create a config that will be used to set up the VM. This is done with a cloud-init configuration. Cloud-init[3] is a configuration tool from Ubuntu that helps set up virtual machines. More Information about it can be found here: Using cloud-init with Multipass | Ubuntu. The config is taken from Josh’s article linked above.

Create a docker.yaml file in your current directory and paste in the following configuration:

---
users:
  - name: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh-authorized-keys:
      - ssh-rsa AAAAB3...

package_update: true
packages:
  - docker.io
  - avahi-daemon
  - apt-transport-https
  - ca-certificates
  - curl
  - gnupg
  - lsb-release
runcmd:
  - sudo curl -fsSL https://get.docker.com | sudo bash
  - sudo systemctl enable docker
  - sudo systemctl enable -s HUP ssh
  - sudo groupadd docker
  - sudo usermod -aG docker ubuntu

The configuration sections explained

  • users is an Array that defines what users should be set up while creating the VM. Here you will also paste your SSH key created in the last step.
  • package_update tells the Ubuntu VM to run apt-get update before installing any packages in the following step to make sure the newest packages are available for installation
  • packages as the name suggests tells Ubuntu which packages to install to proceed
  • runcmd will be run after installing the packages before. In this case, it will download Docker, enabling it via systemctl, creating the docker group and afterwards adding our newly created user to this group. This will make sure that our ubuntu is allowed to interact with Docker.

Launching the Ubuntu VM

multipass launch -c 4 -m 8G -d 20G -n docker 20.04 --cloud-init docker.yaml
  • -c this specifies how many CPUs the VM can use. In this case 4
  • -m defines the amount of RAM
  • -d is for setting the disk space used by the VM
  • -n sets the VM’s name

Handling possible permission problems with a non-root user

launch failed: multipass socket access denied
Please check that you have read/write permissions to '/var/run/multipass_socket'

When you use a macOS user which is not a local admin like I do you have to give this user the permissions to read/write to multipass’s socket to be able to function. So use the chmod command to give your user the permissions needed. Otherwise, you will not be able to start multipass instances.

sudo chmod a+rw /var/run/multipass_socket

After that, the socket should be usable for the non-root user.

Log into VM

After launching the multipass Ubuntu VM in the last step check if it is possible to ssh into the newly created VM.

ssh ubuntu@docker.local

Permission denied (publickey)

When the error ubuntu@docker.local: Permission denied (publickey). will be thrown check if you provide the right ssh key when connecting. Without specifying a key ssh will use your main ssh key which is most often id_rsa. To use the key created above add an entry to your .ssh/config like below.

Host docker.local
  HostName docker.local
  User ubuntu
  IdentityFile ~/.ssh/docker-multipass

If you can connect to your newly created VM close the connection with exit and proceed to the next step where we will now use Docker from our host machine to interact with the Docker installed in the virtual machine.

Time to use Docker

Now that everything is set up check if Docker is answering. Since we use a custom Docker host we have to provide the cli where we want to execute the commands. This is where DOCKER_HOST comes into play, so use it like in the example below.

DOCKER_HOST="ssh://ubuntu@docker.local" docker version

Save the Docker Host environment variable in your terminal session

Since always putting the DOCKER_HOST variable in front of the commands can be annoying you can export it in your terminal session or save it in your .bashrc or .zshrc to have it in every terminal session in the future.

export DOCKER_HOST="ssh://ubuntu@docker.local"

Have fun using Docker

When everything is set up and your Docker is usable from within your terminal you can now start any container you like.

docker run -p 9898:9898 stefanprodan/podinfo

Exposing Ports to the Host machine

Right now (January 22) multipass does not automatically port-forward the exposed ports from within the VM. To set this up for a port use ssh with the -L argument which will block the port on your host machine which is exposed on the connected machine.

ssh -L <Host-Port>:localhost:<VM-Port> ubuntu@docker.local

I hope this article helped you set up and use Docker without using the Docker for Mac software.

Thank you for reading,
Niklas

Resources


  1. Canonical ↩︎

  2. Ubuntu ↩︎

  3. cloud-init ↩︎