Docker: "works on my machine"
Containers are one of the biggest drivers of how we serve applications today.
What is Docker?
Docker is an open source suite of PaaS (Platform as a Service) solutions for serving applications by building, deploying and managing containers.
What is a container?
According to the official Docker website
A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.
Let’s dive into this definition. They are standard software units, because their execution is isolated from the operating system, this allows it to work without conflicts from other programs, which makes it more stable and reproducible.
Container vs Virtual machine
After the previous definition, you might be thinking: “Isn’t that what a virtual machine does?”. Well, a virtual machine indeed creates isolation from the main operating system, but it does this by virtualizing other operating systems, consuming much more resources compared to containers, since they function as processes of the operating system.
How does a container work?
The container works by combining namespaces, which is a feature that allows isolation between groups of processes at a logical level, with cgroups, which is a feature that defines the consumption limits and sharing of resources by processes.
Namespaces
- PID - Process isolation
- NET - Isolation of network interfaces
- IPC - Isolation of communication between processes and shared memory
- MNT - File System Isolation / Mount Point
- UTS - Kernel isolation (simulates another host)
Cgroups
- blkio - Implements inbound and outbound blocking
- acct - Group tasks using cgroups and declare the CPU usage of these groups
- sets - Provides a mechanism for allocating CPUs and memory to a set of tasks
- devices - Implements a cgroup to enforce restrictions on device files
- freezer - Manages the running state of a task, pausing and running according to the system administrator’s will
- hugetlb - Controller that allows you to adjust the usage of larger virtual memory pages, per control group
- memory - Controller that isolates the behavior of memory, of a group of tasks, from the rest of the system
- net_cls - Provides an interface to mark network packages with a class identifier
- net_prio - Provides an interface that allows an administrator to dynamically configure the priority of network traffic
- resource_counter - It should facilitate the management of resources by controllers, providing common tools for accounting
Container vs Image
Container is an image with a temporary read and write layer. This allows the same image to be reused, changing only the layer and reading and writing, which makes the container process even lighter.
Persistence types
Bind mounts
Managed by the file system
docker run -it -v /volume-dk:/app ubuntu
docker run -it --mount type=bind,source=/home/viniciusflv/Documents/codes/app-exemplo/volume-dk,target=/app ubuntu
Volumes
Managed by docker
docker volume create [name]
docker run -it -v meu-volume:/app ubuntu
docker run -it --mount source=meu-volume,target=/app ubuntu
tmpfs
It is not written in the read and write layer
docker run -it --tmpfs=/app ubuntu
docker run -it --mount type=tmpfs,destination=/app ubuntu
Network communication
List networks
docker network ls
Bridge
Create a network channel
Create networks
docker network create --driver bridge [netname]
Network names
docker run -it --name [name] --network [netname] [image] [cmd]
None
Remove the network interface
Host
Removes network isolation from container and system
Installing docker on linux
Updating programs
sudo apt update
Installing dependencies
sudo apt install \ ca-certificates \ curl \ gnupg \ lsb-release
Downloading
sudo mkdir -p /etc/apt/keyringscurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Adding the signing key
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Installing Docker CE
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Giving CLI execution permission to user
sudo usermod -aG docker $USER
Running a container
To run a container we can go to Docker Hub, which is a repository of published open source images, and search for a container. I’ll start by choosing the official Ubuntu image.
docker run ubuntu
Whenever you run a a container the following steps are going to happen:
As it was the first run you will notice that the following logs will appear at your terminal:
Unable to find image 'ubuntu:latest' locallylatest: Pulling from library/ubuntue96e057aae67: Already existsDigest: sha256:4b1d0c4a2d2aaf63b37111f34eb9fa89fa1bf53dd6e4ca954d47caebca4005c2Status: Downloaded newer image for ubuntu:latest
You may also notice that nothing happens, even if you run the command again. That’s because docker’s default behavior is to stop execution of the container if there are no processes running.
We can run a container command by declaring it in front of the image id:
docker run ubuntu echo Olá mundo
Listing running images and containers
Now that we’ve downloaded our first image, we can list them with the command:
docker images
To list running containers let’s first run bash in interactive mode:
docker run -it ubuntu bash
And in another terminal run the command:
docker ps
Deleting images and containers
Delete a container
docker container rm -f [container]
Delete all containers
docker container rm -f $(docker container list -q)
Delete an image
docker image rm -f [image]
Building an image
To build an image it is necessary to create a Dockerfile. In this file will be declared a series of instructions that will configure the image.
FROM
Every Dockerfile must be preceded by the FROM statement followed by the id of the parent image. It serves as basis for us to build our custom image layer.
FROM ubuntu
RUN
We can run commands inside the image through the RUN instruction. The result of these commands will be assigned to the image sequentially.
RUN echo Hello World
LABEL
Add metadata to an image.
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
CMD
The main purpose of the CMD instruction is to provide default arguments for the execution of an ENTRYPOINT.
CMD ["cd", "./app"]
EXPOSE
Exposes an application execution port.
EXPOSE 3000
ENV
Declares an environment variable.
ENV PORT=3000
ARG
Defines variables that users can pass in build-time with the docker build
command via the --build-arg <varname>=<value>
flag.
ENV PORT=3000
ADD
Copies remote or compressed files and adds to the image’s file system.
ADD hom* /mydir/
COPY
Copy local files and add to image file system.
COPY hom* /mydir/
VOLUME
Creates a disk mount point, with a specific name, and marks it as externally mounted to other volumes or containers.
VOLUME ["/data"]
USER
Instruction that creates a username (or UID), and optionally the user’s group (or GID), to be used as the default for the rest of the current stage.
USER node
WORKDIR
Instruction that declares the working directory for the RUN, CMD, ENTRYPOINT, COPY and ADD statements.
WORKDIR /path/to/workdir
ENTRYPOINT
Defines the executable container entrypoint command.
ENTRYPOINT ["npm", "run", "dev"]
ONBUILD
Instructions to be executed when the image is used as base for another build.
ONBUILD ADD . /app/srcONBUILD RUN /usr/local/bin/python-build --dir /app/src
STOPSIGNAL
Change docker’s default stop signal.
STOPSIGNAL signal
HEALTHCHECK
Instruction that tells docker how to test if the container is still functional.
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
SHELL
Instruction allows you to change the default shell used to run commands.
SHELL ["powershell", "-command"]
Uploading an image in docker hub?
- Create your Docker Hub account

- Use the command below to login
docker login -u [username]
- Create an image, with the name concatenating the username and the image name separated by ”/” [username]/[imagename]
docker build username/imagename:1.0.0
- Run the publish command
docker push username/imagename:1.0.0