Docker 101
Wikipedia defines docker as an open-source project that automates the deployment of software applications inside containers by providing an additional layer of abstraction and automation of OS-level virtualization on Linux.
Docker is within a sandboxed environment, it allows users to package an application with all of its dependencies into a standardized unit for development.Provides a layer of isolation from the host,where the container uses the host’s system resources like storage,memory and CPU.
Architecture
- Docker Engine: the core runtime that runs and manages containers and its lifecycle.
- Docker Client: the command line interface (CLI), that interacts with docker engine and sends commands and user requests to the user engine.
- Docker Registry: the central repository, that stores and distributes docker images,which are building blocks of containers,
Docker Hub
is one such example of Docker Registry.
docker ps
docker ps
pulls a public docker image from DockerHub.The image will be stored in our local system, we can specify the tag if we want to pull older versions of the image.
-a
flag of the docker ps displays also shows all the terminated containers.
docker pull
docker pull Image:Tag
pulls the image from the registry server where Image
is the image name, and tags can be used to identify versions of the same image, using tags a specific version of the image can be pulled
For example to pull a debian image with the tag bookworm or bullseye release the command would be docker pull debian:bookworm
& docker pull debian:bullseye
.
docker images
docker images
: command output displays all the images downloaded in our local system, Every image gets an IMAGE_ID. The -a
flag is used to view all the images available on the local machine.
docker run|exec
docker run
: command runs a container of the image provided, if the image is not present locally, it will pull from the registry server.A
docker run -it ubuntu
: this command takes the ubuntu
image which was pulled previously and creates a container, few are the flags are -i
the interactive session, to keep the STDIN open even if container is not attached, -t
tty session, allocate a TTY session for the container getting created. --name <container-name>
flag can be used to give a unique name to the container getting created, here the container name is loving_darwin
.
If we observe the bash prompted is changed as soon as the run
command is executed to root@e5e...
, this bash prompt mentions that this is inside the container.
We next execute a echo sample hello world within the container and then exit using exit
command within the container bash prompt.
Now docker ps
now shows empty because we exited the container, but with the -a
flag it also shows all terminated containers, here in our case loving_darwin
the container name, was exited 8 seconds ago.
To start with container in background we use the flag -d
to start the container in background, explains to starting the container in deattached state.
From the above image we create another container named welcome-ubuntu
with the flag --name
.
-
docker run -d -it --name welcome-ubuntu ubuntu bash
: summarizes to create a container namedwelcome-ubuntu
in deattached state using the-d
flag, using the imageubuntu
. -
docker ps -a
: now displays the newly created container namedwelcome-ubuntu
. -
docker exec -it welcome-ubuntu bash
: runs a new command within a running container, here we specified the container-namewelcome-ubuntu
, and `bash prompt command is to be executed and opened on connecting to the container.
docker stop|rm
-
docker stop welcome-ubuntu
: command stops the running command and its status can be checked viadocker ps -a
, where theSTATUS
is changed toExited(137) 7 seconds ago
. -
docker rm welcome-ubuntu
: command deletes the entire container without any traces of the container.
docker rmi
docker rmi <image-name>
deletes the image from the local system, so the next time we run docker run
or docker pull
, the image is redownloaded again.
docker network ls
Docker network is a feature in docker, allowing you to create a network of docker container managed by a master node called the manager.Containers inside the docker network can talk to each other by sharing packets of information.
docker network ls
: lists networks in the docker
Network Drivers: - bridge: default driver when container is created. - host: containers will not have any IP Address they will be directly created in the system network which will remove isolation - none: IP Address wont be assigned to containers.
docker logs
`docker logs
docker kill vs docker stop
Container doesn’t stop for a SIGTERM
signal sent by a stop command, to terminate the process stop follows the SIGTERM
with a SIGKILL
after a grace period, instead it is faster to use docker kill
which terminates the container immediately.
docker search
To search for images within the registery server i.e here Docker Hub we can use the command docker search <container-name>
say for example, docker search debian
will list out the images with the repository owner and official status.
debian
is an official image provide by debian, hence the official status [OK]
.
docker prune
prune command deletes all the unused and stopped containers,unused build cache,unused images from the host system,below command demonstrates the examples of the docker prune
command.
By default,volumes aren’t removed to prevent important data from being deleted,if no container is using the volume using the --volumes
flag along with the prune command drop unused volumes also.
docker build
docker build
command builds docker images from a Dockerfile, which is a file that contains all the commands a user could call from the terminal.Docker builds images by reading instructions in Dockerfile.
A docker instruction has two components: INSTRUCTION
and ARGUMENT
.
Consider the below Dockerfile for building the docker image.
FROM debian:bookworm
WORKDIR /etc/apt
RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' > sources.list
docker build . -t debian-bookworm-backports
: command to build the docker image for the above Dockerfile, .
is used pass the instructions file which is in the same directory, -t
flag is to give a name to the docker image getting built.
After the image is built successfully to verify the list of images we can find out the image debian-bookworm-backports
is listed below, with a size of 117MB for the built image.
In the next step lets create a container using the image from which we built now, using the command docker run -d -it debian-bookworm-backports
, which creates a container using the image debian-bookworm-backports
with the name practical_galois
.
Lets now connect to container using the command docker exec -it practical_galois bash
, where the bash prompt changes to that of the container, also observe the current working directory has been changed to /etc/apt
because in our dockerfile we had a instruction to set the WORKDIR /etc/apt
, also to verfiy if were able to stdout the debian backports repository we just cat
the sources.list
file.
For subsequent builds we can use docker build . -t debian-bookworm-backports:v2
, where v2
is the tag.
Docker Instructions
FROM
: base image we want to start fromRUN
: run commands during the image build processENV
: sets Environment variable during the build process and also while the container is created.COPY
: command copies a a file or folder from the host to the docker image.EXPOSE
: to expose a port on the docker image at runtime.ADD
: advanced version of COPY command,to copy files,tarballs to the docker image from the host,we can also define instructions to extract the tarball on the docker image.WORKDIR
: set the current working directory in the docker image.VOLUME
: mount the volume to the docker container.USER
: sets the username and UUID when running the container,for setting the non-root user.LABEL
: sets metadata information of Docker image.CMD
: executes a command within a running container, only one CMD command is allowed,if multiple are present only the last one is takes effect.ENTRYPOINT
: commands that will execute when the Docker container starts.
Defining Start conditions for container
Let us consider a sample project where we run yt-dlp against a youtube link which downloads the video, let us build the Dockerfile by giving instructions.
To construct a container image we should first select a base image,here debian:bookworm
as a base image to build yt-dlp image, the first line of the Dockerfile will be
FROM debian:bookworm
To get the binary of yt-dlp, we need curl and to run the yt-dlp
we need python3
so these two packages has to be installed before running the binary,so the Dockerfile with additions will be
FROM debian:bookworm
RUN apt update -y && apt install curl python3 -y
Fetching the yt-dlp binary from github and copying it to /usr/local/bin
and changing the permissions of the binary to executable of all.
FROM debian:bookworm
RUN apt update -y && apt install curl python3
RUN curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
RUN chmod a+x /usr/local/bin/yt-dlp
CMD ["/usr/local/bin/yt-dlp"]
Upon creating the image and creation of container yt-dlp is to be launched.
$ docker run yt-dlp
Usage: yt-dlp [OPTIONS] URL [URL...]
yt-dlp: error: You must provide at least one URL.
Type yt-dlp --help to see a list of all options.
$ docker run yt-dlp https://www.youtube.com/watch?v=uTZSILGTskA
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "https://www.youtube.com/watch?v=uTZSILGTskA": stat https://www.youtube.com/watch?v=uTZSILGTskA: no such file or directory: unknown.
ERRO[0000] error waiting for container: context canceled
According to the above error the youtube link should be taken as an argument to the binary yt-dlp, but here the yt-dlp is executing as a command,updating the CMD TO ENTRYPOINT
FROM ubuntu:22.04
WORKDIR /mydir
RUN apt-get update && apt-get install -y curl python3
RUN curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
RUN chmod a+x /usr/local/bin/yt-dlp
# Replacing CMD with ENTRYPOINT
ENTRYPOINT ["/usr/local/bin/yt-dlp"]
$ docker run yt-dlp https://www.youtube.com/watch?v=DptFY_MszQs
[youtube] Extracting URL: https://www.youtube.com/watch?v=DptFY_MszQs
[youtube] DptFY_MszQs: Downloading webpage
[youtube] DptFY_MszQs: Downloading ios player API JSON
[youtube] DptFY_MszQs: Downloading android player API JSON
[youtube] DptFY_MszQs: Downloading player 9bb09009
[youtube] DptFY_MszQs: Downloading m3u8 information
[info] DptFY_MszQs: Downloading 1 format(s): 22
[download] Destination: Welcome to Kumpula campus! | University of Helsinki [DptFY_MszQs].mp4
[download] 100% of 29.92MiB in 00:00:04 at 7.10MiB/s
Now when the container is run when passed the youtube link as argument the video is downloaded, but it is stored onto the container,here comes the concept of volumes where data is stored.
Docker Volumes
What if you want to store information outside the docker container, that can be used as shared storage for other containers. Docker volumes are mounted to filesystem paths onto the container, where the actual data is stored on the host.With the help of drivers data is written in different services.
Example to pull a nginx
docker image and syncing file and directories across containers and docker volume.
-
To create a volume:
docker volume create nginx-data
, where nginx-data is the volume name,where the volume is created at/var/lib/docker/volumes/nginx-data/_data
. -
docker inspect nginx-data
displays information at what date the volume was created,mountpoint,drivers,etc.
$ docker inspect nginx-data
[
{
"CreatedAt": "2024-03-20T09:29:03Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/nginx-data/_data",
"Name": "nginx-data",
"Options": null,
"Scope": "local"
}
]
- Next let us pull a basic nginx image, and start it with the volume nginx-data (created above) using the flat
-v
to specify which volume.
[node2] (local) root@192.168.0.27 ~
$ docker run -itd -v /var/lib/docker/volumes/nginx-data/_data/:/var/www/html nginx`
what ever data in /var/www/html
inside the container is present is synced to the host nginx-data
.
To verify the working of docker volume, [inside the container] change to the directory /var/www/html
and create a sample file like hello_world.java
and [on the host] when the files are listed under /var/lib/docker/volumes/nginx-data/_data
hello_world.java shows, there by verifying the shared volume.