Use Docker Context to switch between different solutions
Tags: docker
Published: 2021-11-17 18:58:17

You may be on the lookout for a replacement to Docker Desktop [at the moment](https://www.docker.com/blog/roi-of-docker-desktop-vs-diy-considerations-risks-and-benefits-for-business/). If you are, you may be wanting to trial the different solutions. You're going to need to know what is involved, and what the different cost models include. This post is going to show you how you can use `docker context` to run the different systems in parallel. The two solutions this post will cover are [minikube](https://minikube.sigs.k8s.io/docs/start/) and [multipass](https://multipass.run).

## Getting minikube up and running

This post assumes the host machine is a Mac. Therefore, we can use [brew.sh](https://brew.sh/) to install the necessary packages.

```shell
brew install hyperkit
brew install minikube
brew install docker
brew install docker-compose
```

Once this is complete, you can start the `minikube` application.

```shell
minikube start --driver hyperkit
```

This will now be running a Virtual Machine we can use for Docker.

## Getting multipass up and running

Let's use [brew.sh](https://brew.sh/) again to install the necessary packages.

```shell
brew install multipass
```

Multipass allows us to use [cloud-init](https://cloudinit.readthedocs.io/en/latest/) to define a the environment we can use. This will configure the virtual machine for you. The definition I use is defined below.

```yaml
users:
  - name: ubuntu
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh-authorized-keys:
      - ssh-rsa .....
package_update: true
packages:
  - apt-transport-https
  - avahi-daemon
  - ca-certificates
  - curl
  - docker
  - 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
```

It is saved to `$HOME/git/github/benmatselby/dotfiles/common/multipass-docker.yml`. You can save this file where you want. Add the contents of your `~/.ssh/id_rsa.pub` file to the `ssh-authorized-keys` array above. This allows your host machine to `ssh` into the virtual machine multipass will create.

Now we want to spin up the multipass environment:

```shell
cd $HOME/git/github/benmatselby/dotfiles/common/
multipass launch -c 2 -m 2G -d 10G -n docker-multipass 20.04 --cloud-init multipass-docker.yml
```

Make sure you `cd` into the directory where you saved the `cloud-init` script. This command will launch a virtual machine using Ubuntu 20.04, with 10GB of disk space (`-d`), 2GB of RAM (`-m`), 2 CPUs (`-c`), and named `docker-multipass`. You can change the values as you see fit. You will need the name of the instance for later.

You may also want to mount some local folders to make life a little easier:

```shell
multipass mount /Users docker-multipass
multipass mount /Volumes docker-multipass
```

You can see the information about the VM you created by running:

```shell
multipass info docker-multipass
Name:           docker-multipass
State:          Running
IPv4:           192.168.64.5
                172.17.0.1
Release:        Ubuntu 20.04.3 LTS
Image hash:     a83b747df657 (Ubuntu 20.04 LTS)
Load:           0.19 0.14 0.05
Disk usage:     1.8G out of 9.5G
Memory usage:   232.8M out of 1.9G
Mounts:         /Volumes => /Volumes
                    UID map: 501:default
                    GID map: 20:default
                /Users   => /Users
                    UID map: 501:default
                    GID map: 20:default
```

## Using docker context

We now have two environments that can be used instead of Docker Desktop: `minikube` and `multipass`. The best way to switch between the two systems is to use `docker context`. Let's now create a context for multipass, and set it as the default.

```shell
docker context create multipass \
  --description "Multipass Docker Desktop" \
  --docker "host=ssh://ubuntu@docker-multipass.local"
docker context use multipass
```

The name provided in the `multipass launch` command, is what becomes the `ubuntu@[multipass name].local` value. So if you named your multipass instance "lebowski" you would use `host=ssh://ubuntu@lebowski.local` as your `--docker` context. I used `docker-multipass` in the examples above.

The last thing we need to do is `ssh` into into the VM so we can accept the authenticity of the host.

```shell
ssh ubuntu@docker-multipass.local
```

You can now leave the VM, `exit`.

Now run `docker run hello-world`. This will run the `hello-world` container via `multipass`.

You can see what contexts you have by running:

```shell
$ docker context ls
NAME            DESCRIPTION                               DOCKER ENDPOINT
default         Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
desktop-linux                                             unix:///Users/Ben/.docker/run/docker.sock
multipass *     Multipass Docker Desktop                  ssh://ubuntu@docker-multipass.local
```

Let's now add the `minikube` context. First, we need some data from minikube to build the context:

```shell
minikube -p minikube docker-env
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.64.10:2376"
export DOCKER_CERT_PATH="/Users/Ben/.minikube/certs"
export MINIKUBE_ACTIVE_DOCKERD="minikube"
```

We need this information for the context connection string. Let's run:

```shell
docker context create minikube \
  --description "Minikube Docker Desktop" \
  --docker "host=tcp://192.168.64.10:2376,cert=/Users/Ben/.minikube/certs/cert.pem,ca=/Users/Ben/.minikube/certs/ca.pem,key=/Users/Ben/.minikube/certs/key.pem"
```

You can see how we have built up the `--docker` string by using the environment variables provided by the `minikube` command. Let's now check the contexts we have:

```shell
docker context ls
NAME            DESCRIPTION                               DOCKER ENDPOINT
default         Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
desktop-linux                                             unix:///Users/Ben/.docker/run/docker.soc
minikube        Minikube Docker Desktop                   tcp://192.168.64.10:2376
multipass *     Multipass Docker Desktop                  ssh://ubuntu@docker.local
```

We can then use `docker context use [name]` to switch between the contexts. Let's switch to `minikube` and run `hello-world`.

```shell
docker context use minikube
docker run hello-world
```

You have now run the `hello-world` container using both docker contexts.

## Conclusion

Docker Desktop is an easy to use system for the Mac. For personal projects, it is great. With the new licensing agreement, businesses may need to review how their engineers run containers during development. This post showed how you can use `docker context` to switch between different back ends to help trial alternatives to Docker Desktop.

---

Photo by <a href="https://unsplash.com/@alschim?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Alexander Schimmeck</a> on <a href="https://unsplash.com/s/photos/choice?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>

---

### See also

- [Docker knowledge to get you through the day](https://dev.to/benmatselby/docker-knowledge-to-get-you-through-the-day-47bl)
- [Setting up a VS Code Dev Container - Minikube](https://dev.to/benmatselby/setting-up-a-vs-code-dev-container-minikube-549a)