Docker is a platform that provides lightweight isolated runtimes for software. It helps us to package the software and its dependencies in a ready to run format.

We can say its sort of works like VMs except, docker uses the kernel of our base OS.

This is achieved by few techniques done with docker,

  • File system snapshot - Dockerfile is used to build a filesystem snapshot that contains all the required files to run the software.
  • Namespacing - Docker isolates the resources for the running processes using the Namespacing feature. It is a linux feature which partitions resources and control access between processes on resources.
  • Control groups - The volume of resources used by a process can also be limited by docker. It is achieved by cgroups features which is another linux feature that helps define resource limits for a process.

Why use Docker?

As docker enables packaging and running software in a lightweight way, It solves the problem of setting up and configuring an environment to run the software.

Also, the isolation it provides will help us run a different instance of certain software without any conflict.

eg: If we want to work with Redis.

  • We need to have tools like curl in our system to download it and then do configurations to run it.
  • Docker simplifies all of it by simply pulling its Docker image and running it, we only need to specify the custom configurations.

eg: If we want to run multiple projects that use Postgresql

  • Usually, we use one Postgres installation and set up different databases so that, multiple projects are connected to it.
  • We can isolate the Postgres instance like one for each project with docker in a lightweight way and without conflicting with each other.

Components of Docker

Docker Service

Docker has a daemon service - docker server that runs in our system that would manage everything behind the scenes. It handles all docker operations from building images to running containers and makes everything work together as we configure them. It also monitors the running containers.

Docker CLI

The Docker service is controlled via docker CLI or client, which is essentially an interface for us to interact with docker service. There are different commands which would call the APIs in the Docker service and perform different actions.

Common cli commands :

  • docker pull <image_name>

Pulls an image from the remote repository and stores it in the local cache (default from docker hub)

  • docker run <image_name>

Starts a container and run an image (Its combination of docker create <image_name> which creates a container and docker start -a <container_name> which starts container and attach terminal to the container process)

  • docker run -it <image_name> <cmd>

Overrides a default run command and executes cmd after loading a container with an image (-it will give us an interactive terminal)

  • docker ps

Shows all running processes or containers

  • docker logs <container_name>

Shows logs from the process running in the container (If the log outputs to stdout)

  • docker attach <container_name>

Attaches our terminal to running container process

  • docker stop <container_name>

Stops a running container

  • docker rm <container_name>

Removes a container process

  • docker rm $(docker ps -aq)

Removes all running containers

  • docker build . -t uname/label:tag

Builds image from the Dockerfile

  • docker exec -it <container_name> <cmd>

Executes a command inside the container

  • docker system prune

Remove all unused images and containers

Docker Image

Docker image is essentially a file system snapshot mostly with a Start command that would run the software. The images are built using Dockerfile, which contains steps to build a filesystem snapshot.

Example Dockerfile:

FROM node:12-alpine
RUN apk add --no-cache python g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

We can see all the images in our local cache using docker image ls command.

Docker Container

To run a docker image, a container is to be created. The container can be assumed as an instance of that image that is ready to run/running. It is immutable, so any changes we make (like creating a new file) will not persist after we stop a container.

We can see all the running containers using docker container ls command.

Life cycle of a container.

  1. Create
  2. Start
  3. Stop (can restart them at this point)
  4. Remove

Containers are isolated from eachother, everything we perform inside one container of same image will not be available inside another instance of the same image.

Docker Volume

Since containers are immutable, we can’t persist data in them. We use volumes to persist data from a container. We map a volume for the location inside the container to a path in our local system and the data will be persisted.

We can see all the running containers using docker volume ls command.

Docker Network

We can create virtual networks using docker. Virtual bridges are created which have IP addresses to which containers (which also have IP addresses) can be connected.

There is also a DNS involved within the services, where the container/service name resolves to their respective IP address. We can use this to easily connect to running services in containers.

The ports of running containers can also be published or bound to our local system and access via localhost: port.

We can see all the running containers using docker network ls command.

Docker Repository

Docker image files that are built are stored in the docker repository. There will be a repository cache in our local system and we can also push them to remote Repository. An image will always be downloaded(pulled) and stored in the local cache before running.