# 3. Docker: The basics
###### tags: `corsounipd2022`
> based on
> * https://training.play-with-docker.com/dev-stage1/
> * https://training.play-with-docker.com/ops-s1-hello/
:::warning
Create your own **Docker ID** at https://hub.docker.com/signup and…
Option 1:
You can download and install Docker on multiple platforms. Refer to the following link: https://docs.docker.com/get-docker/ and choose the best installation path for you.
Option 2:
You can use a virtual machine that you can [download here](https://bit.ly/dockervm_2022
)
You have to use VirtualBox with the option: "Files / Import virtualized service". The VM has user "**docker**" with password "**docker**"
Option 3:
You can execute it online: https://labs.play-with-docker.com/
:::
:::info
The code of this section is [here ![](https://i.imgur.com/5Un0gCm.jpg =40x)](https://www.dropbox.com/sh/u73b82rr9crtzwt/AAALzsmqKDWiGLGu4wqW5eqga?dl=0)
:::
## Containers and images
A container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI. You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state.
An image is a read-only template with instructions for creating a Docker container. A Docker registry stores Docker images.
Docker Hub (https://hub.docker.com/) is a public registry that anyone can use, and Docker is configured to look for images on Docker Hub by default; there are millions of images available.
![](https://i.imgur.com/LoBB95F.png)
There are three different ways to use containers. These include:
* To run a **single task**: This could be a shell script or a custom app.
* **Interactively**: This connects you to the container similar to the way you SSH into a remote server.
* In the **background**: For long-running services like websites and databases.
In the following we will see examples of all three ways to use containers
## Run a single task "Hello World"
```
$ docker container run hello-world
```
![](https://i.imgur.com/113RKn6.png)
[`https://hub.docker.com/_/hello-world`](https://hub.docker.com/_/hello-world)
![](https://i.imgur.com/ntTx3DW.png)
Images can have multiple versions. For example you could pull a specific version of `ubuntu` image as follows:
```bash
$ docker pull ubuntu:12.04
```
If you do not specify the version number of the image the Docker client will default to a version named `latest`.
So for example, the `docker pull` command given below will pull an image named `ubuntu:latest`:
```bash
$ docker pull ubuntu
```
To get a new Docker image you can either get it from a registry (such as the Docker Store) or create your own. You can also search for images directly from the command line using `docker search`. For example:
```bash
$ docker search mqtt
```
You can check the images you downloaded using:
```
$ docker image ls
```
## Run an interactive container
:::info
**By the way...**
In the rest of this seminar, we are going to run an ==Alpine Linux== container. Alpine (https://www.alpinelinux.org/) is a lightweight Linux distribution so it is quick to pull down and run, making it a popular starting point for many other images.
:::
```
$ docker image pull alpine
$ docker image ls
```
Some examples:
```
$ docker run alpine echo "hello from alpine"
$ docker run alpine ls -l
```
![](https://i.imgur.com/1iQnej7.png)
**The command `run` creates a container from an image and executes the command that is indicated.**
Let's try with these examples:
```
$ docker run alpine /bin/sh
$ docker run -it alpine /bin/sh
```
Which is the difference between these two examples?
The latter command runs an alpine container, attaches interactively ('`-i`') to your local command-line session ('`-t`'), and runs /bin/sh.
E.g., try: `/ # ip a `
Summing up:
1. With `run`, if you do not have the image locally, Docker pulls it from your configured registry.
1. Docker creates a new container.
1. Docker allocates a read-write filesystem to the container, as its final layer.
1. Docker creates a network interface to connect the container to the default network. By default, containers can connect to external networks using the host machine’s network connection.
1. Docker starts the container and executes `/bin/sh`.
1. When you type `exit` to terminate the `/bin/sh` command, the container stops but is not removed. You can start it again or remove it.
---
## Docker container instances... and isolation
This is an important security concept in the world of Docker containers:
In previous example, **even though each docker container run command used the same alpine image, each execution was a separate, isolated container.**
Each container has a separate filesystem and runs in a different namespace; by default a container has no way of interacting with other containers, even those from the same image.
So, if we do this:
```
$ docker run -it alpine /bin/ash
/ # echo "hello world" > hello.txt
/ # ls
```
we will get to something like this:
![](https://i.imgur.com/9OR5wVe.png)
To show all Docker containers (both running and stopped) we can also use the command `$ docker ps -a`.
![](https://i.imgur.com/qXNOkxH.png)
In this specific case, the container with the ID `330a96cc4f29` is the one with the file
Now if we do:
```
$ docker start 330a96cc4f29
$ docker attach 330a96cc4f29
/ # ls -al
total 68
drwxr-xr-x 1 root root 4096 Jan 28 09:51 .
drwxr-xr-x 1 root root 4096 Jan 28 09:51 ..
-rwxr-xr-x 1 root root 0 Jan 28 09:50 .dockerenv
drwxr-xr-x 2 root root 4096 Nov 24 09:20 bin
drwxr-xr-x 5 root root 360 Jan 28 09:58 dev
drwxr-xr-x 1 root root 4096 Jan 28 09:50 etc
-rw-r--r-- 1 root root 11 Jan 28 09:51 hello.txt
drwxr-xr-x 2 root root 4096 Nov 24 09:20 home
drwxr-xr-x 7 root root 4096 Nov 24 09:20 lib
...
```
While if we do:
```
$ docker container start e700ae985bc0
$ docker exec 7b6c70dd5b77 ls -l
total 56
drwxr-xr-x 2 root root 4096 Nov 24 09:20 bin
drwxr-xr-x 5 root root 360 Jan 28 10:01 dev
drwxr-xr-x 1 root root 4096 Jan 28 09:45 etc
drwxr-xr-x 2 root root 4096 Nov 24 09:20 home
drwxr-xr-x 7 root root 4096 Nov 24 09:20 lib
drwxr-xr-x 5 root root 4096 Nov 24 09:20 media
drwxr-xr-x 2 root root 4096 Nov 24 09:20 mnt
drwxr-xr-x 2 root root 4096 Nov 24 09:20 opt
dr-xr-xr-x 256 root root 0 Jan 28 10:01 proc
drwx------ 1 root root 4096 Jan 28 09:45 root
drwxr-xr-x 2 root root 4096 Nov 24 09:20 run
```
We will see that in that container there is not the file "hello.txt"!
## Handling containers
To summarize a little.
To show which Docker containers are running:
```
$ docker ps
```
To show all Docker containers (both running and stopped):
```
$ docker ps -a
```
If you don't see your container in the output of `docker ps -a` command, than you have to run an image:
```
$ docker run ...
```
If a container appears in `docker ps -a` but not in `docker ps`, the container has stopped, you have to restart it:
```
$ docker start <container ID>
```
If the Docker container is already running (i.e., listed in `docker ps`), you can reconnect to the container in each terminal:
```
$ docker exec -it <container ID> sh
```
### Detached containers
Starts an Alpine container using the `-dit` flags running `ash`. The container will start **detached** (in the background), interactive (with the ability to type into it), and with a TTY (so you can see the input and output). Since you are starting it detached, you won’t be connected to the container right away.
```
$ docker run -dit --name alpine1 alpine ash
```
Use the docker `attach` command to connect to this container:
```bash
$ docker attach alpine1
/ #
```
Detach from alpine1 without stopping it by using the detach sequence, `CTRL + p CTRL + q` (*hold down CTRL and type p followed by q*).
### Finally...
Commands to stop and remove containers and images.
```
$ docker stop <CONTAINER ID>
$ docker rm <CONTAINER ID>
```
The values for `<CONTAINER ID>` can be found with:
```
$ docker ps
````
Remember that when you remove a container all the data it stored is erased too...
List all containers (only IDs)
```
$ docker ps -aq
```
Stop all running containers
```
$ docker stop $(docker ps -aq)
```
Remove all containers
```
$ docker rm $(docker ps -aq)
```
Remove all images
```
$ docker rmi $(docker images -q)
```