Docker is the container runtime and orchestration engine.
- Enterprise Edition (EE) and Community Edition (CE)
- Moby is the Open Source project of Docker — Moby consists of modular components.
When to use Docker
- Simplifying Configuration – Put the configuration and environment settings in the code
- Application Isolation
- Server Consolidation
- Dev/Production environment are the same
- Debugging – Bugs in production can be replicated in Development easily
Docker Architecture
Docker is a client-server architecture.
- Clients communicate with the Docker daemon (server) using REST APIS through UNIX sockets or Network Interfaces.
- Docker daemon (dockerd) handles building, running, and distribute containers.
- dockerd manages the following docker objects: Images, Containers, Networks, and Volumes.
- Docker client (Docker) sends the user commands to dockerd.
- Docker Registries store docker images.
- Private Registry
- Public Registry such as DockerHub
Docker Images
Docker image is a read-only template and contains instructions for creating a Docker container.
- An Image can be based on other images – multiple layers -.
- Each layer represents an instruction in the image’s Dockerfile.
- Each layer is read-only, except the last one.
- Each layer has only a set of differences from the layer before it.
- A container adds a new writable layer on top of the underlying layers.
Docker Containers
A container is a runnable instance of an image.
- Containers can connect to networks and can attach persistent storages.
- A new image can be created based on the container’s current state.
- Containers are isolated from other containers and the host machine.
- All changes are stored in the writable layer, and the writable layer is deleted when the container is deleted. The image remains unchanged.
Build Images with Dockerfile
A Dockerfile is a set of instructions (called directives) used to construct a Docker image.
- FROM: sets the basic image
- ENV: sets environment variables
- RUN: creates a new layer on top of the previous one
- CMD: specifies a default command to run a container at the execution time
- USER: sets the user name (or UID) and optional group name (or GID)
- USER <user>[:<group>]
- USER <UID>[:<GID>]
- WORKDIR: sets the working directory
FROM ubuntu:jammy
ENV NGINX_VERSION 1.23.2
RUN apt-get update && apt-get install -y curl
RUN apt-get update && apt-get install -y nginx=$NGINX_VERSION
CMD ["nginx", "-g", "daemon off;"]
You can build the image with the “docker build” command.
docker build -t {TAG_NAME} .
Services
- Services can scale containers across multiple Docker daemons.
- Services define and manage the desired state.
- Service is load-balanced.
Docker Swarm
- Multiple Docker daemons (Master and Workers) are working together.
- The daemons all communicate using the Docker API
- Features
- Scaling, Load Balancing
- Service Discovery: Each service is assigned with a unique DNS name
- Rolling update
- Supported in Docker 1.12 and higher
Docker Engine
Docker engine is base on open-standards by the Open Container Initiative (OCI) and modular in design.
- Initial Release of Docker: Docker daemon + LXC (Lightweight Linux container)
- LXC was replaced with libcontainer
Docker became more modular:
- runc
- Implementation of the OCI container-runtime-spec
- CLI wrapper for libcontainer
- Responsible to create containers
- containerd
- Manages Container lifecycle: start, stop, pause, delete
- shim
- Implementation of daemon-less Containers
Container Lifecycle
- Running
- Stopped
- Restarted
Creating a Container
- Executing a command using CLI
- Docker client uses the appropriate API payload and POSTs to the correct API endpoint
- Docker daemon receives requests
- Docker daemon calls ‘containerd‘ to start a new container
- ‘containerd‘ creates an OCI bundle from the Docker image
- ‘containerd‘ instructs ‘runc‘ to create a container using the OCI bundle
- ‘runc’ interfaces with the OS kernel to get the constructs needed to create a container (namespaces, cgroups, etc.)
- Container process starts as a child process
- ‘runc‘ exits once the container starts
- Container is running
Running Containers
docker run [options] Image[:Tag] [Command] [Arg…]
- Image (required): the name of the container image to run.
- Tag (optional): a specific image tag, usually used to pull a specific version
- Command (optional): the command to run inside the container
- Arg (optional): arguments to pass when running the command
Examples
# image only
docker run hello-world
docker image ls
docker container ls -a
#image:tag
docker run nginx:1.23.2
# the process is running
Ctrl + C # to exit
# image command arg1 arg2
docker run busybox echo hello world!
Run Command Options
- -d, —detach: run the container in a detached mode in the background
- —name: a container name; not specified, a random name is assigned.
- — restart: specify when the container should restart
- no (default): never restart the container
- on-failure: only if the container fails
- always: always restart
- unless-stopped: always restart unless the container was manually stopped
- -p <host port>:<container port> : port mapping
- -m, —memory: hard limit on memory usage
- -i, —interactive: keep STDIN open even if not attached
- -t, —tty: allocate a pseudo-TTY
docker run -d --name my-nginx-server --restart on-failure -p 8080:80 -m 256M nginx
docker container ls
curl localhost:8080
Storage Driver
Storage drivers provide a pluggable framework for the temporary internal storage of a container’s writable layer.
- devicemapper
- Block-storage
- Efficient for doing a lot of writes
- Default for CentOS 7 and earlier
- overlay2
- File-based storage
- Default for CentOS 8+ and Ubuntu
docker info

Selecting a Storage Driver
By default, Docker automatically selects a storage driver compatible with your environment.
You can override the storage driver in two ways:
- Set the –storage-driver flag when starting Docker
- [Recommended] Update the “storage-driver” value in the “/etc/docker/daemon.json”
sudo vi /etc/docker/daemon.json
{
"storage-driver: "devicemapper"
}
sudo systemctl restart docker
docker info