Docker
Info
Docker is a virtualization technique based on containers.
It allows running very light and isolated containers.
Advantages of containers
- Speed: Simplifies setup and teardown of complex environments.
- Consistency: Ensures all developers use the same environment.
- Portability: Easily share configurations for testing or deployment.
Quote
Preliminaries
See virtualization notes.
Docker hub
Docker Hub is the equivalent of GitHub. It stores Docker images from the community.
Use verified and popular images!
Everyone can upload images to Docker hub. Some can have security issues or may contain malwares.
Installation
Cf official Docker documentation.
Usage
Usage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Common Commands:
run Create and run a new container from an image
exec Execute a command in a running container
ps List containers
build Build an image from a Dockerfile
pull Download an image from a registry
push Upload an image to a registry
images List images
login Authenticate to a registry
logout Log out from a registry
search Search Docker Hub for images
version Show the Docker version information
info Display system-wide information
Management Commands:
builder Manage builds
buildx* Docker Buildx
compose* Docker Compose
container Manage containers
context Manage contexts
debug* Get a shell into any image or container
desktop* Docker Desktop commands (Alpha)
dev* Docker Dev Environments
extension* Manages Docker extensions
feedback* Provide feedback, right in your terminal!
image Manage images
init* Creates Docker-related starter files for your project
manifest Manage Docker image manifests and manifest lists
network Manage networks
plugin Manage plugins
sbom* View the packaged-based Software Bill Of Materials (SBOM) for an image
scout* Docker Scout
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes
Swarm Commands:
swarm Manage Swarm
Commands:
attach Attach local standard input, output, and error streams to a running container
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
export Export a container's filesystem as a tar archive
history Show the history of an image
import Import the contents from a tarball to create a filesystem image
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
save Save one or more images to a tar archive (streamed to STDOUT by default)
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
wait Block until one or more containers stop, then print their exit codes
Global Options:
--config string Location of client config files (default
"C:\\Users\\bapti\\.docker")
-c, --context string Name of the context to use to connect to the
daemon (overrides DOCKER_HOST env var and
default context set with "docker context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket to connect to
-l, --log-level string Set the logging level ("debug", "info",
"warn", "error", "fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default
"C:\\Users\\bapti\\.docker\\ca.pem")
--tlscert string Path to TLS certificate file (default
"C:\\Users\\bapti\\.docker\\cert.pem")
--tlskey string Path to TLS key file (default
"C:\\Users\\bapti\\.docker\\key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Run 'docker COMMAND --help' for more information on a command.
For more help on how to use Docker, head to https://docs.docker.com/go/guides/
Docker Basics
One can first analyze the following command:
docker run --rm bash echo Salut!
It gives the follwing result:
Unable to find image 'bash:latest' locally
latest: Pulling from library/bash
e1517fbc9c07: Download complete
467989b961c3: Download complete
43c4264eed91: Download complete
Digest: sha256:ce062497c248eb1cf4d32927f8c1780cce158d3ed0658c586a5be7308d583cbb
Status: Downloaded newer image for bash:latest
Salut!
What happens is:
- Docker searches for a bash image and since we did not specified any tag, it takes the latest version.
- Docker pulls (downloads) bash image from DockerHub.
- Docker executes the command
echo Salut!
. - Docker removes the container (not the image) since we used the flag
-rm
.
Get Help
Each docker command has a --help
feature to get a description and usage.
View downloaded (cached) images
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
bash latest ce062497c248 6 weeks ago 21.8MB
After having launched a bash container, bash image is cached in the computer. Caching ensures that the following runs are much faster: there is no need to download the image again.
Running again:
docker run --rm bash:3.2 echo Salut!
REPOSITORY TAG IMAGE ID CREATED SIZE
bash latest ce062497c248 6 weeks ago 21.8MB
bash 3.2 79dd16db958d 5 months ago 17.4MB
Again, this is the goal of caching: the bash version 3.2 have to be dowloaded and appears in the table.
Running interactive Docker
-t
: asks Docker to give a terminal access, plugging STDIN and STDOUT-i
: runs the container in interactive mode, giving access to the keyboard-ti
: combination of-t
and-i
docker run -ti --rm bash:3.2 echo Salut!
exit
`docker run
always create a new container.
Start an existing container
Once we've created a container, we must not use docker run command again. The container can be started using the command:
docker start -ai <container name>
-a
: attach the container to a process-i
: runs the container in interactive mode, giving access to the keyboard-ai
: combination of-a
and-i
Stop an existing container
exit
docker exit
List container information
docker ps
docker ps -q
docker ps -a
docker ps -l
docker ps -s
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"
Detail informations for any container
Use `docker ps
t get container's name and then:
docker inspect <container name>
Attach to a running container
docker attach <container name>
Detach from a running container
ctrl p+q
Container IDs
Image and containers have unique IDs, that can be obtained using docker images
.
IDs can be used to:
- get images properties
- manipulate images
Print history / layers of an image
docker history <IMAGE_ID>
Shortcut
Typing only the first unique digits of the ID is the same as copy-pasting the whole ID.
Info
All the layers that constitude the container image are read-only. There is a read-write partition inside the container (separated from host), that stores the data of the container. Now there are multiple issues:
- How to make backup of the container?
- How to update an image for this container?
Answer: containers are volatile, and this is where volumes are important.
Volumes handling
Maped volumes
Volumes mount a directory from host machine into a container. The deletion of the container will not affect the project files.
docker run -ti --rm -v $(pwd)/<host folder>:<docker folder>
bash title="To mound a directory in read only, add ro
:"
docker run -ti --rm -v $(pwd)/<host folder>:ro<docker folder>
Managed volumes
docker volume create my_data
docker volume ls
docker run --rm -ti -v my_data:/src bash
docker run --rm -ti -v my_data:/src bash
When mounting an empty managed volume, the mounting folder of the container is totally transferred inside the host folder, and stays after the container has been deleted.
Docker containers can then modify the volume.
docker volume inspect my_data
Delete all existing containers
docker stop $(docker ps -q)
docker rm $(docker ps -a -q)
Test some executable in different environments
docker run --rm -v $(pwd)/script.sh:/script.sh bash:4 /script.sh
What this command will do is:
- create a temporary docker (
rm
command is used) using bash version 4 - mount a volume corresponding to the executable file
script.sh
- execute the script with the command
/script.sh
- exit the container and delete it
To test the script or the executable on another bash version, the only thing to do is specifying the version we want to test in the same command:
docker run --rm -v $(pwd)/script.sh:/script.sh bash:3.2 /script.sh
And we have not touched to our system configuration!
Network ports handling
Just as volumes, containers have their own network ports, that can be mounted to host's network ports. -p
is similar to -v
to mount volumes, but for network ports.
docker run --rm -p <host port>:<container port> nginx
Note that:
- ports can be reserved
- cannot be allocated twice
- if no host port is specified, the host machine choses the port number
docker run --rm -p -d <host port>:<container port> nginx
Note that -d
detaches the docker and runs it in the background so that the server can run continously.
However, docker silences the maping and we want a way to see quickly which port host's system decided to use `docker ps
t get container's name and then:
docker inspect <container name>
Network drivers
There are different levels of network drivers for docker containers:
- none: no network driver
- bridge (default): only containers created using the bridge and host will be able to connect to each others
- custom bridges: same as bridge but this is not a default bridge
- host: no network isolation between host and container
- overlay
- macvlan
Bridge features can be checked using ping
command inside each docker
Network features can be checked using ifconfig
command inside the docker
No network
docker run -ti --rm --network none bash
Default bridge
docker run -ti --rm bash
Warning
This default bridge provides acceess to every other docker and the host machine, one may want to ping specific containers instead of all of them. In this case, custom bridges can be used.
Custom bridge
docker run -ti --rm --network create --driver=bridge my_bridge_name bash
Then, my_bridge_name network should appear inside the created network:
docker network ls
docker run -ti -rm --network=my_bridge_name --name=server1 bash
Docker uses a internal DNS only for cloned bridges or custom briges, but not for default bridges
Containers sharing the same network can therefore ping each other by their IP, but also using their names (given by --name
).
If a container was created on another bridge or none, it can be linked at container runtime with:
docker network connect my_bridge_name server
Once done, server container should be able to ping server1 because it will share the same bridge network. Note that this is done while the container is running and do not require a container reboot.
Host driver
Opening a network port on the docker is equivalent to opening a network port on the host machine.
This type of network can be used in very specific cases, but goes against container's isolation principle.
Delete a network
docker network rm my_bridge_name
Log detached containers
docker logs <container id or name>
This command is useful for detached containers.
Executing a command in an active container
docker exec -ti <container id or name> <program>
e.g.
docker exec -ti d24 bash
This will open the container in a bash console, in interactive mode.
Creating images
Sometimes, existing images do not have the features we want, and therefore we have to create it.
This can be done by:
- Selecting an existing image on DockerHub
- Typing commands that should be run in addition on the image, creating additional layers
Editing the Dockerfile
Any Dockerfile starts with a base image specification:
FROM ubuntu:22.04
In this scenario, the base image on which we will add layers is ubuntu, version 22.04.
Changing the version number of the base image is a standard way of testing a code throughout software versions
Installing libraries automatically using apt-get
Sometimes, installing libraries need a user input, like Y for yes or N for no.
In this case, the syntax in the dockerfile becomes:
RUN apt-get install -y libxml2-dev
This command will provide an automated Y or yes input to the installation procedure of the container.
In other scenarios, time-zone has to be known by a user input and stops the container installation process.
To automate this, two commands can be added at the top of the Dockerfile:
ENV TZ=Europe/Paris
ENV DEBIAN_FRONTEND=noninteractive
Changing the working directory
WORKDIR /opt/test
Build the new image from a Dockerfile
docker build -t <new container name> <path to Docker file>
docker build -t php_soap:7.0.31 .
Where:
-t
creates a tag for the new imagephp_soap:7.0.31
.
specifies that the dockerfile is in the current working directory
If the Dockerfile has a custom name (different from Dockerfile or dockerfile), then the path to this configuration script is indicated by -f my_custom_named_dockerfile path_to_custom_dockerfile