Running Docker on Apple Silicon M1 (follow-up)

This is a follow-up post to “Running Docker on Apple Silicon M1”, continuing the journey of exploring Docker on Apple’s new M1 machines.

We left off at booting an ARM Linux virtual machine, and installing & running Docker inside it. This works fine and allows you run containers like for instance a Postgres database. They can expose their ports and instead of connecting to localhost:5432 on the host, you connect to your VM’s IP address, for instance 192.168.64.8:5432.

Now in case you’re not aware, Docker is actually a service that exposes an API over HTTP and when you run docker commands, they control the service via these API requests on a local socket. You’ve probably seen the reference to unix:///var/run/docker.sock at times.

What that means is that it’s possible to direct your docker client to talk to a Docker service over the network, and that’s what we can do as well to enable “regular” docker commands to work with a locally running “Linux Docker VM”.

Incidentally, that’s exactly what “Docker for Mac” is doing under the hood: it is actually a VM based on Apple’s Hypervisor framework which hosts Docker, not your Mac itself.

Installing “Docker for Mac”

In order to get started, we need to obtain the Docker client app. I migrated my existing setup from a Time Machine backup and therefore had Docker installed from the start. If you need to install from scratch, installing the client binaries is probably the easiest way to get started.

Assuming you have a docker binary to hand, you’re good to go. The way we’ll set up the connection is via a “docker context” and all this is thanks to a tip by Johannes Weiss.

Setting up SSH in virtual machine

First though, we need to configure to connect to our VM via SSH. Install the SSH server:

sudo apt-get install openssh-server

and copy your public key to the ubuntu user’s authorized_keys for password-less access.

In order to connect to the VM, you’ll need to find its IP address (which is on a 192.168.64.0 network if you’ve followed along from the previous blog post).

Our image comes without net-tools, so we’ll install these first:

sudo apt install net-tools

and then run

ifconfig | grep 192.168

which should yield the following

ubuntu@ubuntu:~$ ifconfig | grep 192.168
        inet 192.168.64.8  netmask 255.255.255.0  broadcast 192.168.64.255

With all this out of the way, we can test the connection from the host:

ssh [email protected]

Setting up a Docker context

The remaining steps are simple. We create a Docker context:

docker context create myvm --docker "host=ssh://[email protected]"

and tell Docker to use it

docker context use myvm

Now all docker commands are targeting the virtual machine, just like they do in Docker for Mac.

❯ docker context create myvm --docker "host=ssh://[email protected]"
myvm
Successfully created context "myvm"
~
❯ docker context use myvm
myvm
~
❯ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
~
❯ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

You can find out more about docker context in the online documentation.

Bear in mind that this setup does not come with the convenience of Docker for Mac’s bridge networking or support for volumes – but surely these aren’t far off.