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 named welcome-ubuntu in deattached state using the -d flag, using the image ubuntu.

  • docker ps -a: now displays the newly created container named welcome-ubuntu.

  • docker exec -it welcome-ubuntu bash: runs a new command within a running container, here we specified the container-name welcome-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 via docker ps -a, where the STATUS is changed to Exited(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 , displays the logs of the container.

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.

Dockerfile
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 from
  • RUN: run commands during the image build process
  • ENV: 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.

References