Best Docker Tutorial – 2024

This Docker tutorial are just my notes which I am sharing with you all. I have prepared this tutorial and use it for my own reference as well, while at work. Let me know if there is something else you want me to add in the Docker Tutorial

docker tutorial

How to use this Docker Tutorial

I use this tutorial as reference as well as to brush up my concepts for Docker. It helps me with my day to day work.

Why use docker

Makes it really easy and straight forward for you to install and run software on any given computer, be it desktop or any cloud based computing platform

E.g.

To install redis on your computer:

Step 1: wget http://download.redis.io.. Wget command not found

So, you troubleshoot and then you get into some other issue

Now, compare it with installing redis using docker..all you need to do is run the command

Docker run -it redis

That’s all you need to do..easy peasy

Thus, makes it really easy to install and run software without worrying about setup or dependencies

What is docker

Docker is a platform or ecosystem, around creating and running containers

Docker Ecosystem

Docker client

Docker server

Docker Machine

Docker Images

Docker Hub

Docker Compose

What is a container

Docker cli reached out to docker hub

Downloaded a single file called an image

Image is a single file with all the deps and config required to run a program

Single files which gets stored on your hard drive

We use this image to create a container. Container is an instance of an image. It runs a program

Container is a program with its own isolated set of hardware resources

Own set of Memory, Hard drive, network, etc

Docker for windows has two main tools

Docker client/cli – program that we use to issue commands. Doesn’t actually do anything.. Just CLI

Docker server/Daemon: responsible for creating images, running containers, etc.

We need dockerhub account to install docker

Docker version

Anatomy of docker run hello-world

Starts docker cli

Communicates it to docker server

Docker server checks the image cache locally

If not, it contacts docker hub

Docker server reached out to docker hub

Downloaded the hellow world file and stored it in image cache

Uses that image to create instance of it, loads it in memory

Run it second time and you should not see unable to find image locally

Operating System locally

Kernel sits between running application and the system hardware

For example, nodejs might say i want to write a file to hard drive to kernel

Running program interact through system call to kernel

Apps always interact with kernel using system call

Kernel interacts with the hardware

Now, consider a situation where, App A might need python v2 and App B needs Python v3

Now, your system will have only one python installed. Let’s say you can’t have two python versions installed at the same time.

You can use namespacing.. I.e. a segment of hard disk, dedicated to housing python

Namespace: Isolate resource per process or group of processes

NS can not only be used for HW but for SW as well.

NS can be used for processes, Users, Hard Drive, Hostnames, Network

Kernel figures out to which process or namespace it should send the call to

Control Groups or cgroups: Limit amount of resources used per process. E.g. Memory, CPU, HD I/O, Network bandwidth.

Therefore, container is a group or process that has grouping of resources specifically assigned to it.

Image

Filesystem snapshot: copy paste of very specific set of directories or files 

Start up command: 

When an image becomes a container, kernel takes a portion of HD and dedicated it to the container. After which it takes what is in FS Snapshot and place it in the HDD

After which startup command is executed. This creates a process which is isolated to its set of container

Subset of physical resources allocated to that process

NS and Cgroup are specific to Linux OS

For windows or MacOS, we use Linux VM.

To check, run docker version command and look at OS in server, it will be linux

Docker run <image name>

  1. Places the fs snapshot in hard drive
  2. Run the startup command

Docker run <image name> command

Default command override

Docker run busybox echo hi there

Docker run busybox ls

Why these commands won’t run with docker run hello-world ls

Start up commands are based upon the filesystem. 

Listing running container

Docker ps

List all the containers ever created

Docker ps –all

Container lifecycle

Docker run = docker create + docker start

Docker create <image name>

Docker start <image name>

Create – takes the fs and copy it in container. Prep/setup the container

Start – execute the start up command

Docker create hello-world

<long number >

Docker start -a <ID>

Attach to container and watch for output and print it on my terminal

Docker start <ID>

No output shown on terminal

Restart a container

Docker start <id>

Once you stop and start the container, it will attach the default command that was used to start it first

Removing stopped container

Docker system prune

Build cache

Stopped container

Dangling images

Networks not used by at least one container

Get logs of a container

Docker logs <container id>

Even the stopped container can emit logs using this command

Stopping a container

Docker stop <container id>

Docker kill <container id>

Stop – Hardware sugnal is sent to primary process sigterm signal.. Shutdown on it’s own time

Do cleanup or emit message whn you recv this signal

Kill – sigkill – shutdown now

If container does not stop in 10 seconds, then docker will switch to docker kill

Execute commands in running container

E.g. redis server.. Redis cli

Exec – run another command

-it – provide input to the container

Docker exec -it <con id> <command>

Docker exec contend command ->

STDIN  STDOUT   STDERR

Every container is a process in linux

STDIN – used to communicate the info to the process

Whatever you type in terminal gets redirected to STDIN of your running process

STDOUT – conveys info coming out of process. 

STDERR – error info channel. Redirected to show up on the screen

-it = -i -t -> -i – we want to attach our terminal to the stdin of the process

-t make sure all the text you enter or is coming out is nicely formatted or pretty or readable

Getting a command prompt or shell access to running container

Docker exec -it <cont id> sh

#  -> run unix commands here

Command processors -> bash, powershell, zsh, sh

Exec – execute additional command in the container

Docker run -it busybox sh -> doing the same thing we did with exec

Build our own custom images

Dockerfile – configuration to define how our container should behave. What diff program it should have and what happens when it starts up as container

We then pass it to docker client which passes it to docker server and which builds a usable image, which is used to start a container

DOCKERFILE

Specify a base image

Run some commands to install additional programs

Specify command to run on container startup

FROM alpine

RUN apk add –update redis

CMD [“redis-server”]

Come to docker client and run “docker build . “

Successfully build <id>

Docker run <id>

FROM – base image to use

RUN – execute some commands while we are preparing our base image

CMD – specifies what should be executed when our image is used to start up a brand new container

To understand FROM – if i give you a laptop with no OS and tell you to install chrome.. Your first step will be to install OS.. that is what FROM is.

Build command is what we use to take a dockerfile and build an image

“.” is known as the build context. It is essentially set of files and folders that belong to our project, that we want to encapsulate or wrap inside our container

Start with base image

Execute the run command

Save the image and use it for next step

Tagging an image

Docker build -t <docker id>/repo or project name>:latest .

Docker build -t kunal/abc:latest .

Successfully tagged <name>

Docker run <name>

Command to tag already existing image

Docker tag <id> <name>

To include the files in same directory as dockerfile

COPY ./ ./

Container Port Mapping

Docker run -p 8080:8080 <image tag>

No limitation on container reaching out.. Its only coming in

-p 8080:8080 -> port incoming request from 8080 to 8080 inside the container

Specify working directory

WORKDIR /usr/app -> Any following command will be executed relative to this path in the container

If the folder is not there, it will be created.

To get changes from local to container..you need to rebuild the image

Docker Compose

From node:alpine

Workdir ‘/app’

Copy package.json .

Run npm install

Copy . .

Cmd[“npm”, “start”]

Docker build -t name/visits:tag-latest .

Docker run name/vists

Docker run redis 

-> throws redis not found.. WHY?

If you spin up the images separately, i.e. in their own container, they do not have any automatic communication between the two whatsoever. They are two absolute isolated processes that do not have any communication.

Therefore, we need to setup some networking infra between the two.

  1. Use docker cli for network feature – involve handful of commands that needs to be run every time you start the containers.Not used in the industry
  1. Use docker compose

Used to start multiple container at same time and automatically connect them together with some form of networking

Separate cli tool

Automates some of the commands we need to run multiple containers at the same time

Docker-compose.yml -> contains all the options we would normally pass to docker cli

File goes to docker compose cli

From example above, create a docker compose file which spins up redis and node app

Docker-compose.yml

Version; ‘3’ – version of docker compose file

Services:

Redis-server:

Image: ‘redis’

Node-app:

Build: . – look in current dir for dockerfile nd use that to build the image

Ports:

                  – “4001:8081”

It will create both of these containers in the same network. They both have access to each other.

Docker run myimage -> docker-compose up

Docker build .

Docker run myimage -> docker-compose up –build

Docker-compose up -d-> run images in background

Docker stop <cont_id> -> docker-compose up down

Automatic container restart

“No” -> Never attempt to restart

Always -> if this container stops for any reason, always attempt to restart

On-failure -> only restart if stops with an error code

Unless-stopped -> always restart unless we forcibly stop it

Status code 

process.exit(0) -> we exited and everything is OK

1,2, -> we exited because something went wrong

Node-app:

Restart: always

In yaml file, “no” needs to be in quotes, as no means false

Docker-compose ps -> status of two containers inside docker compose files

It needs docker-compose.yml file to know which containers it needs to get the status for

Docker Volumes

Make a change in local, we want it to be reflected in the app.

Rather than doing copy, we make volumes, which are reference to folders in local machine

Docker run -p 3000:3000 -v /app/node_modules -v $(pwd}:/app <image id

-. Map the pwd into app folder

If colon is not there, then it is a bookmark. Do not try to map this folder to anything. Use what is inside the container.

You can refer to our Extensive list of Docker interview questions here

About the author
Kunal Choudhary

Leave a Comment

Contact About