Running containers on distant host: docker contexts
Published: 2024-01-06 23:05:46

_Cover from [Ruan Bekker blog](https://blog.ruanbekker.com/blog/2022/07/14/remote-builds-with-docker-contexts/)_

Hi, today I will introduce you a docker functionnality I discovered 6 months ago: **docker contexts 🐳**.

It allows you to **build and run** your containers on a **distant host**.

> Please note I'm only a docker user, for further informations about contexts visit [the official documentation](https://docs.docker.com/engine/context/working-with-contexts/)

# 🧠 Understand contexts

Actually, docker contexts let you **manage multiple docker daemons from a single client**.

A context has two major informations:
- Its name and description
- Its endpoint

By default, a `default` context is created and used. Its endpoint is the local docker sock.
```
NAME         DESCRIPTION                               DOCKER ENDPOINT               ERROR
default                                                unix:///var/run/docker.sock
```

The strength of contexts is that you can **change from one host to another in only one command** !


# ⚡ Get started with contexts

## ⚙️ Sever configuration

First, you need to configure your server to enable remote access to your docker daemon.

⚠️ Remote access permit anyone in a network to connect to your docker daemon and, potentially have `root` access to your server ⚠️

> See [official documentation](https://docs.docker.com/config/daemon/remote-access/)

Two methods to enable remote access:
- With **systemd**
- With **daemons.json**

### With systemd

1.) Edit the `docker.service` file and put your own values.
```shell
sudo systemctl edit docker.service
```
```
[Service]
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375
```
2.) Reload changes and restart docker daemon
```shell
sudo systemctl daemon-reload && sudo systemctl restart docker.service
```

### With daemons.json
1.) Add the folowing to `/etc/docker/daemons.json`
```json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
```
2.) Restart docker

You should now have **remote access** enabled. You can verify docker is binding on port `2375` using `netstat`:
```shell
$ sudo netstat -lntp | grep dockerd
tcp        0      0 127.0.0.1:2375          0.0.0.0:*               LISTEN      3758/dockerd
```

## 💻 Client configuration & examples

First, you need to ensure that your docker cli supports the `context` command:
```shell
docker context
```

_It should show you a help about contexts_


Next, let's **create a context**
```shell
docker context create <context> --docker host=tcp://host:2375
```
_Replace `<context>` with its name and `host` by the docker daemons IP._

It should be in the list of contexts outputted by
```shell
docker context ls
```

```
NAME         DESCRIPTION                               DOCKER ENDPOINT               ERROR
default *                                              unix:///var/run/docker.sock   
<context>                                              tcp://<context-ip>:2375 
```

Default as an asterisk after its name (`default *`) because it's the currently used context.

**To change** to the newly created one, just type.
```shell
docker context use <context-name>
```

Now you can run any docker container in the **distant docker daemon**
```shell
docker run -d -it busybox /bin/sh
```
_This execute a shell in an empty container_

You should see it in `docker ps`
```shell
docker ps
```
```
CONTAINER ID   IMAGE               COMMAND                CREATED         STATUS                          PORTS     NAMES
f4d3674af80a   busybox             "/bin/sh"              2 seconds ago   Up 1 second                               focused_ramanujan
```

You can **verify that it's been running on the distant** host by passing which context to use directly in the command:
```shell
docker --context default ps
```
_Should not output busybox container_
_Whereas `docker --context <context> ps` should !_

You have know the rudiments about **docker context**. Consider referring to [the Docker documentation](https://docs.docker.com/engine/context/working-with-contexts/) for further informations and explanations.

# 📈 How I use it ?

Discovering this feature was very helpful in my workflow: I don't need to use ssh to deploy latest versions of my apps anymore.

I just change context, to choose the right server (like `databases`, `microservices`, `web-prod`) and fire `docker run -d ...`.

In parallel i use [_Portainer_](https://www.portainer.io/), a powerful web UI for docker. It allows me to manage my running containers and check their health **right in my browser** !

Here are some screenshots of my portainer:

|  |  List of connected daemons   |     |
| --- | --- | --- |
|  |  ![Connected Daemons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbsvq97qc6s0lmxr892y.png)   |     |
|  |  Lists of containers  |  |
|  | ![Containers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6hp0fvryiabea9w0xis.png) |  |


----

I hope you discovered something new,
Have nice deployments,
See you later 👋 !