class: title

# Airgapped images

![Background containers](airgapped/air-gap-poster.jpg)

---

## Airgapped

- In an airgapped environment there is no direct access to public repositories.

- Images have to be converted into files and vice versa in order to import them.

- Imported images can be used on a single node, repeat for multiple nodes. ;-)

- Imported images can also be pushed into a internal, secure, registry.

---

## Objectives

* We will now see how to:
* Pull public images
* Convert them to files
* Import them on a secure node
* Use them local
* Tag them and push them into a secure registry

---

## Pulling images

Let's pull a public Ubuntu image.

There is no real magic here.
.lab[
```bash
$ docker pull ubuntu:22.04
22.04: Pulling from library/ubuntu
837dd4791cdc: Pull complete
Digest: sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5
Status: Downloaded newer image for ubuntu:22.04
docker.io/library/ubuntu:22.04
```
]
* This image has only one layer, but that is not relevant.

---

## Let's see how to use it local

.lab[
```bash
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       22.04     1f6ddc1b2547   2 weeks ago   77.8MB

$ docker run --rm ubuntu:22.04 uptime
 08:46:39 up  1:42,  0 users,  load average: 0.00, 0.00, 0.00
```
]

* The container is started using the name of the image.

---

## Convert the image to a file

Assume we're working on a host that is not secure but it has access to public repo's.

Let's pull an image and convert it to file to ship it to a secure enviroment.

.lab[
```bash
$ docker pull python:latest
latest: Pulling from library/python
bd73737482dd: Pull complete
6710592d62aa: Pull complete
75256935197e: Extracting  54.58MB/54.58MB
c1e5026c6457: Download complete
f0016544b8b9: Download complete
1d58eee51ff2: Download complete
93dc7b704cd1: Download complete
caefdefa531e: Download complete

$ docker save python:latest > python_image.tar
```
]

---

## Clean up

Remove the python image to pretend that we are now working on a secure host where we need this image.

.lab[
```bash
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
python       latest    0a6cd0db41a4   2 weeks ago   919MB
ubuntu       22.04     1f6ddc1b2547   2 weeks ago   77.8MB

$ docker image rm python:latest
Untagged: python:latest
Untagged: python@sha256:3a619e3c96fd4c5fc5e1998fd4dcb1f1403eb90c4c6409c70d7e80b9468df7df
Deleted: sha256:0a6cd0db41a4daebb332262ddd1f61a29e88169b8c93476cb885f46d400473c8
Deleted: sha256:2107499ce10dd1004c16e7c0b47e3cb86317188b5f9a1ab64ac1968c3f56fe2c
...

$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       22.04     1f6ddc1b2547   2 weeks ago   77.8MB
```
]

---

## Import image on 'secure' system

Let's pretend that we copied the `tar` file to this node via secure, approved methodes.
Once it is there we can import it.

.lab[
    ```bash
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       22.04     1f6ddc1b2547   2 weeks ago   77.8MB

$ docker load < python_image.tar
974e52a24adf: Loading layer  129.3MB/129.3MB
b0df24a95c80: Loading layer  29.52MB/29.52MB
...
30563becc00e: Loading layer  11.64MB/11.64MB
Loaded image: python:latest

$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
python       latest    0a6cd0db41a4   2 weeks ago   919MB
ubuntu       22.04     1f6ddc1b2547   2 weeks ago   77.8MB
```
]

---

## Image locally available

The imported image is available on the host where it was imported. The name of the image has not changed.
This operation can be repeated throughout the organisation and the images could be stored somewhere in a filesystem in `tar` format.

.lab[
```bash
$ docker run --rm -it python cat /etc/debian_version
11.7

$ ls -l
total 919644
-rw-r--r-- 1 docker users 941711360 Jan  6 08:51 python_image.tar
```
]

You could also do a `tar tvf python_image.tar`

---

## Sharing an imported image

If a local registry is available it can be used to store and share imported images. The steps are simple:

* Import image
* Add a new name to the image including the name of the registry (tagging the image)
* Push the new name to the registry.

---

## Self signed certificates

Let's create a certificate to simulate a more secure environment.

.lab[
```bash
$ mkdir certs
$ openssl req \
  -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
  -addext "subjectAltName = DNS:node1" \
  -x509 -days 365 -out certs/domain.crt
Generating a RSA private key
...
writing new private key to 'certs/domain.key'
-----
...
Common Name (e.g. server FQDN or YOUR name) []:node1
Email Address []:
```
]

---

## Install certificate for docker

Docker expects certificates to exist at a directory in `/etc/docker/certs.d`. This directory contains a subdir named equal to the node name of the certificate. Inside is the corresponding file.

.lab[
```bash
$ sudo mkdir -p /etc/docker/certs.d/node1:443
$ sudo cp certs/domain.crt /etc/docker/certs.d/node1\:443/ca.crt
$ sudo systemctl restart docker
```
]

---

## Start the local registry

Let's start a local registry first using a one liner.

.lab[
```bash
$ docker run -d --restart=always --name registry -v "$(pwd)"/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -p 443:443 registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
8a49fdb3b6a5: Pull complete
58116d8bf569: Pull complete
4cb4a93be51c: Pull complete
cbdeff65a266: Pull complete
6b102b34ed3d: Pull complete
Digest: sha256:20d084723c951e377e1a2a5b3df316173a845e300d57ccdd8ae3ab2da3439746
Status: Downloaded newer image for registry:2
0c1a3bfe39f5d3a90d42bf97ad3e95220496317b8185a865f57a7fa5aceac68d
```
]

---

## Tag and push python image

Assign an additional(!) name to the python image and push it into the registry

.lab[
```bash
$ docker tag python:latest node1:443/python:latest

$ docker image ls
REPOSITORY          TAG       IMAGE ID       CREATED       SIZE
python              latest    0a6cd0db41a4   2 weeks ago   919MB
node1:443/python    latest    0a6cd0db41a4   2 weeks ago   919MB
ubuntu              22.04     1f6ddc1b2547   2 weeks ago   77.8MB
registry            latest    65f3b3441f04   3 weeks ago   24MB

$ docker push node1:443/python
Using default tag: latest
The push refers to repository [node1:443/python]
30563becc00e: Pushed
71c951de0520: Pushed
0eb817dfc4e1: Pushing [==================>                                ]  20.54MB/56.5MB
...
974e52a24adf: Waiting
latest: digest: sha256:cbaa654007e0c2f2e2869ae69f9e9924826872d405c02647f65f5a72b597e853 size: 2007
```
]
