|
|
|
@@ -1,25 +1,27 @@
|
|
|
|
|
## Containers
|
|
|
|
|
# Containers
|
|
|
|
|
|
|
|
|
|
### Containers Exercises
|
|
|
|
|
## Containers Exercises
|
|
|
|
|
|
|
|
|
|
|Name|Topic|Objective & Instructions|Solution|Comments|
|
|
|
|
|
|--------|--------|------|----|----|
|
|
|
|
|
|Running Containers|Basics|[Exercise](running_containers.md)|[Solution](solutions/running_containers.md)
|
|
|
|
|
|Containerized Web Server|Basics|[Exercise](containerized_web_server.md)|[Solution](solutions/containerized_web_server.md)
|
|
|
|
|
|Working with Images|Image|[Exercise](working_with_images.md)|[Solution](solutions/working_with_images.md)
|
|
|
|
|
|Containerized Web Server|Applications|[Exercise](containerized_web_server.md)|[Solution](solutions/containerized_web_server.md)
|
|
|
|
|
|Containerized Database|Applications|[Exercise](containerized_db.md)|[Solution](solutions/containerized_db.md)
|
|
|
|
|
|Containerized Database with Persistent Storage|Applications|[Exercise](containerized_db_persistent_storage.md)|[Solution](solutions/containerized_db_persistent_storage.md)
|
|
|
|
|
|My First Dockerfile|Dockerfile|[Exercise](write_dockerfile_run_container.md)|
|
|
|
|
|
|Run, Forest, Run!|Restart Policies|[Exercise](run_forest_run.md)|[Solution](solutions/run_forest_run.md)
|
|
|
|
|
|Layer by Layer|Image Layers|[Exercise](image_layers.md)|[Solution](solutions/image_layers.md)
|
|
|
|
|
|Containerize an application | Containerization |[Exercise](containerize_app.md)|[Solution](solutions/containerize_app.md)
|
|
|
|
|
|Multi-Stage Builds|Multi-Stage Builds|[Exercise](multi_stage_builds.md)|[Solution](solutions/multi_stage_builds.md)
|
|
|
|
|
|
|
|
|
|
### Containers Self Assessment
|
|
|
|
|
## Containers Self Assessment
|
|
|
|
|
|
|
|
|
|
* [Containers 101](#questions-containers-101)
|
|
|
|
|
* [OCI](#questions-oci)
|
|
|
|
|
* [Images](#questions-images)
|
|
|
|
|
* [Basic Commands](#questions-basic-commands)
|
|
|
|
|
* [Volume](#questions-volume)
|
|
|
|
|
* [Storage](#questions-containers-storage)
|
|
|
|
|
* [Dockerfile](#questions-dockerfile)
|
|
|
|
|
* [Architecture](#questions-architecture)
|
|
|
|
|
* [Docker Architecture](#questions-docker-architecture)
|
|
|
|
@@ -29,9 +31,10 @@
|
|
|
|
|
* [Docker Networking](#questions-docker-networking)
|
|
|
|
|
* [Security](#questions-security)
|
|
|
|
|
* [Docker In Production](#questions-docker-in-production)
|
|
|
|
|
* [Rootless Containers](#questions-rootless-containers)
|
|
|
|
|
|
|
|
|
|
<a name="questions-containers-101"></a>
|
|
|
|
|
#### Containers 101
|
|
|
|
|
### Containers 101
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What is a Container?</summary><br><b>
|
|
|
|
@@ -98,7 +101,7 @@ You should choose containers when:
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-oci"></a>
|
|
|
|
|
#### Containers - OCI
|
|
|
|
|
### OCI
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What is the OCI?</summary><br><b>
|
|
|
|
@@ -118,7 +121,7 @@ Create, Kill, Delete, Start and Query State.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-images"></a>
|
|
|
|
|
#### Containers - Images
|
|
|
|
|
### Images
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What is a container image?</summary><br><b>
|
|
|
|
@@ -154,7 +157,7 @@ docker.io docker.io/rahulgadre/snake-game
|
|
|
|
|
<details>
|
|
|
|
|
<summary>How to list the container images on certain host?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
CONTAINER_BINARY=podman # or docker
|
|
|
|
|
CONTAINER_BINARY=podman
|
|
|
|
|
$CONTAINER_BINARY images
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
@@ -165,7 +168,7 @@ Note: you can also use `$CONTAINER_RUNTIME image ls`
|
|
|
|
|
<summary>How to download/pull a container image without actually running a container?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
CONTAINER_BINARY=podman # or docker
|
|
|
|
|
CONTAINER_BINARY=podman
|
|
|
|
|
$CONTAINER_BINARY pull rhel
|
|
|
|
|
```
|
|
|
|
|
</b></details>
|
|
|
|
@@ -375,7 +378,7 @@ Cons:
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-basic-commands"></a>
|
|
|
|
|
#### Containers - Basic Commands
|
|
|
|
|
### Basic Commands
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>How to list all the containers on a given host?</summary><br><b>
|
|
|
|
@@ -437,18 +440,73 @@ With the -d flag. It will run in the background and will not attach it to the te
|
|
|
|
|
`docker container run -d httpd` or `podman container run -d httpd`
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>If you'll run <code>sleep 100</code> inside a container, will you see it when listing all the processes of the host on which the container runs? Why?</summary><br><b>
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-volume"></a>
|
|
|
|
|
#### Containers - Volume
|
|
|
|
|
<details>
|
|
|
|
|
<summary>True or False? If image <code>httpd-service</code> has an entry point for running the httpd service then, the following will run the container and eventually the httpd service <code>podman run httpd-service ls</code></summary><br><b>
|
|
|
|
|
|
|
|
|
|
False. Running that command will override the entry point so the httpd service won't run and instead podman will run the `ls` command.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>True or False? Running <code>podman restart CONTAINER_NAME</code> kills the main process inside the container and runs it again from scratch</summary><br><b>
|
|
|
|
|
|
|
|
|
|
False. `podman restart` creates an entirely new container with the same ID while reusing the filesystem and state of the original container.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-containers-storage"></a>
|
|
|
|
|
### Storage
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Container storage is said to be ephemeral. What does it mean?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
It means the contents of the container and the data generated by it, is gone when the container is removed.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>True or False? Applications running on containers, should use the container storage to store persistent data</summary><br><b>
|
|
|
|
|
|
|
|
|
|
False. Containers are not built to store persistent data and even if it's possible with some implementations, it might not perform well in case of applications with intensive I/O operations.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>You stopped a running container but, it still uses the storage in case you ever resume it. How to reclaim the storage of a container?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
In order to reclaim the storage of a container, you have to remove it.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>How to create a new volume?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
`docker volume create some_volume`
|
|
|
|
|
```
|
|
|
|
|
CONTAINER_BINARY=podman
|
|
|
|
|
$CONTAINER_BINARY volume create some_volume
|
|
|
|
|
```
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>How to mount a directory from the host to a container?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
CONTAINER_BINARY=podman
|
|
|
|
|
mkdir /tmp/dir_on_the_host
|
|
|
|
|
|
|
|
|
|
$CONTAINER_BINARY run -v /tmp/dir_on_the_host:/tmp/dir_on_the_container IMAGE_NAME
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
In some systems you'll have also to adjust security on the host itself:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
podman unshare chown -R UID:GUID /tmp/dir_on_the_host
|
|
|
|
|
sudo semanage fcontext -a -t container_file_t '/tmp/dir_on_the_host(/.*)?'
|
|
|
|
|
sudo restorecon -Rv /tmp/dir_on_the_host
|
|
|
|
|
```
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-dockerfile"></a>
|
|
|
|
|
#### Containers - Dockerfile
|
|
|
|
|
### Dockerfile
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What is a Dockerfile?</summary><br><b>
|
|
|
|
@@ -539,7 +597,7 @@ Instructions such as ENTRYPOINT, ENV, EXPOSE, create image metadata and they don
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-architecture"></a>
|
|
|
|
|
#### Containers - Architecture
|
|
|
|
|
### Architecture
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>How container achieve isolation from the rest of the system?</summary><br><b>
|
|
|
|
@@ -613,8 +671,14 @@ Multiple namespaces: pid,net, mnt, uts, ipc, user
|
|
|
|
|
* SElinux
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>True or False? Containers have ephemeral storage layer</summary><br><b>
|
|
|
|
|
|
|
|
|
|
True. The ephemeral storage layer is added on top of the base image layer and is exclusive to the running container. This way, containers created from the same base image, don't share the same storage.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-docker-architecture"></a>
|
|
|
|
|
#### Containers - Docker Architecture
|
|
|
|
|
### Docker Architecture
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Which components/layers compose the Docker technology?</summary><br><b>
|
|
|
|
@@ -791,7 +855,7 @@ Because each container has its own writable container layer, and all changes are
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-docker-compose"></a>
|
|
|
|
|
#### Containers - Docker Compose
|
|
|
|
|
### Docker Compose
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Explain what is Docker compose and what is it used for</summary><br><b>
|
|
|
|
@@ -810,7 +874,7 @@ In general, it's useful for running applications which composed out of several d
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-docker-images"></a>
|
|
|
|
|
#### Containers - Docker Images
|
|
|
|
|
### Docker Images
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What is Docker Hub?</summary><br><b>
|
|
|
|
@@ -867,7 +931,7 @@ By default, Docker uses everything (all the files and directories) in the direct
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-networking"></a>
|
|
|
|
|
#### Containers - Networking
|
|
|
|
|
### Networking
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What container network standards or architectures are you familiar with?</summary><br><b>
|
|
|
|
@@ -880,7 +944,7 @@ CNI (Container Network Interface):
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-docker-networking"></a>
|
|
|
|
|
#### Containers - Docker Networking
|
|
|
|
|
### Docker Networking
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What network specification Docker is using and how its implementation is called?</summary><br><b>
|
|
|
|
@@ -916,7 +980,7 @@ True. An endpoint can connect only to a single network.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-security"></a>
|
|
|
|
|
#### Containers - Security
|
|
|
|
|
### Security
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What security best practices are there regarding containers?</summary><br><b>
|
|
|
|
@@ -937,7 +1001,7 @@ True. An endpoint can connect only to a single network.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-docker-in-production"></a>
|
|
|
|
|
#### Containers - Docker in Production
|
|
|
|
|
### Docker in Production
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>What are some best practices you following in regards to using containers in production?</summary><br><b>
|
|
|
|
@@ -973,3 +1037,44 @@ Restart Policies. It allows you to automatically restart containers after certai
|
|
|
|
|
* no: don't restart the container at any point (default policy)
|
|
|
|
|
* on-failure: restart the container when it exists due to an error (= exit code different than zero)
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<a name="questions-rootless-containers"></a>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Explain Rootless Containers</summary><br><b>
|
|
|
|
|
|
|
|
|
|
Historically, user needed root privileges to run containers. One of the most basic security recommendations is to provide users with minimum privileges for what they need.
|
|
|
|
|
|
|
|
|
|
For containers it's been the situation for a long time and still for running some containers today from docker.io, you'll need to have root privileges.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Are there disadvantages in running rootless containers?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
Yes, the full list can be found [here](https://github.com/containers/podman/blob/main/rootless.md).
|
|
|
|
|
|
|
|
|
|
Some worth to mention:
|
|
|
|
|
|
|
|
|
|
- No binding to ports smaller than 1024
|
|
|
|
|
- No images sharing CRI-O or other rootful users
|
|
|
|
|
- No support running on NFS or parallel filesystem homerdirs
|
|
|
|
|
- Some commands don't work (mount, podman stats, checkpoint, restore, ...)
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Give one example of rootless containers are more safe from security perspective</summary><br><b>
|
|
|
|
|
|
|
|
|
|
In rootless containers, user namespace appears to be running as root but it doesn't, it's executed with regular user privileges. If an attacker manages to get out of the user space to the host with the same privileges, there's not much he can do because it's not root privileges as opposed to containers that run with root privileges.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>When running a container, usually a virtual ethernet device is created. To do so, root privileges are required. How is it then managed in rootless containers?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
Networking is usually managed by Slirp in rootless containers. Slirp creates a tap device which is also the default route and it creates it in the network namepsace of the container. This device's file descriptor passed to the parent who runs it in the default namespace and the default namespace connected to the internet. This enables communication externally and internally.
|
|
|
|
|
</b></details>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>When running a container, usually a layered file system is created, but it requires root privileges. How is it then managed in rootless containers?</summary><br><b>
|
|
|
|
|
|
|
|
|
|
New drivers were created to allow creating filesystems in a user namespaces. Drivers like the FUSE-OverlayFS.
|
|
|
|
|
</b></details>
|
|
|
|
|