I know before learning or using any new technology, our first question often is why use it in the very first place.
Well, we need to understand how things were before Docker came into the picture and the problem it aimed to fix.
Before Docker
Virtual machines (VMs) were the primary solution for many application development and deployment needs. VMs offered a way to create isolated environments within a single physical server. However, provisioning multiple virtual machines, each with its operating system, could be resource-intensive and less efficient. The virtual machines also consume higher disk space as each VM is heavy. This is the exact problem that containers aim to solve.
Containers
Containers are not something new; they have existed for a long time. Think of a container as an isolated virtual environment for your application, but it's much lighter and faster than VMs. Containers use the same underlying operating system kernel, unlike VMs. A container includes your application and everything it needs to run, like code, settings, dependencies, and some parts of the OS. They run consistently across different environments, isolated from the rest of the system.
VMs & Containers
It's not a choice between containers or virtual machines; it's often containers and virtual machines coexisting in large environments.
Containers are the best option for modern apps due to their portability and scalability, making them perfect for cloud-native solutions. Yet, VMs are better for hosting applications, offering strong isolation by allowing different operating systems and kernels to run on a single machine. Now, you might provision a virtual machine for hundreds or thousands of containers.
What is Docker?
Docker is a high-level tool that provides a user-friendly interface and powerful functionalities for creating, managing, and running containers. It helps in the process of setting up and working with containers, allowing users to package applications and their dependencies in a consistent, portable, and efficient manner. You don't need to spend hours setting the environment for your application. Just put your application's stuff inside a "Docker Container" and it's ready to run.
Client-Server Architecture of Docker
Yes, Docker uses a Client-Server architecture. The user interacts with the Docker Client with commands. The Client communicates with the Docker Daemon, which does all the tasks such as building and running them.
Some Docker Elements
Docker Image
Docker image is a template for creating a container, it is built using the instructions that are defined in a Dockerfile. They are designed in layers and each layer is immutable, meaning they do not change after they are built. This immutability ensures consistency in different environments.
Docker registries
Docker registries are the centralized repo for Docker Images. One can choose between private or public (Docker Hub) registries according to your needs. Docker images are pushed to and pulled from these registries, allowing for easy distribution and sharing of containerized applications.
Dockerfile
Dockerfile is like a blueprint for building a house. This file contains all the instructions and configuration to create an Image. It defines the instructions like base image, sets up the environment, installs software, copies files, and specifies commands to run.
Here's a simple Dockerfile that prints "Hello, Docker!" when you run a container from it :
FROM python CMD ["python", "-c", "print('Hello, Docker!')"]
Workflow
A Dockerfile serves to create Docker Images. These Docker Images are like snapshots of your application. They are lightweight and portable. Once you've built a Docker Image, you can use it to create isolated instances called containers. Containers are where your application runs.
Some commands
docker pull imageName # Pull an image
docker images # List Docker images
docker run -it imageName # Run a container interactively
docker run -d imageName # Run a container in detached mode (background)
docker ps -a # List all containers (including stopped ones)
docker stop containerID or ContainerName # Stop a container
docker start containerID or ContainerName # Start a container
docker rm containerID or ContainerName # Remove a container
docker rmi imageName # Remove an image
docker push imageName # Push an image to a registry
docker logs containerID or ContainerName # View logs of a running container
docker exec -it containerID or ContainerName # Execute a command in a running container
Hands-on
Let's try to pull an image from Docker Hub which is a public registry and run a container. Make sure you've configured Docker into your system and Docker daemon is running. For assistance: Get Docker
We'll be using the python image here :
root@MSI:~# docker pull python Using default tag: latest latest: Pulling from library/python 0a9573503463: Pull complete 1ccc26d841b4: Pull complete 7c45daddd450: Pull complete 0952bd8ba4ec: Pull complete 53f1aa318bc2: Pull complete Digest: sha256:2586dd7abe015eeb6673bc66d18f0a628a997c293b41268bc981e826bc0b5a92 Status: Downloaded newer image for python:latest docker.io/library/python:latest What's Next? View summary of image vulnerabilities and recommendations → docker scout quickview python
By default docker pulls the latest version of Python, you can specify the tag implicitly. e.g.
docker pull python:3.11
Now that you have an image in your system you can create a container from it :
root@MSI:~# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE python latest 17e65561fd2c 5 days ago 1.02GB root@MSI:~# docker run -it python Python 3.12.0 (main, Apr 20 2024, 09:45:59) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> print('Hello, world!') Hello, world! >>> (3+7) 10 >>>exit() root@MSI:~# docker run -d python da8371465e74e7cdc6a29578c67f4fdf973f0e9e88d723f70ceeadc4276ed416
-it
allows us to interact with the container's shell or application in an interactive and user-friendly way.-d
runs the container in detached mode.Our purpose is achieved, so let's just remove the container and image from our system :
root@MSI:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES da8371465e74 python "python3" 2 minutes ago Exited (0) 2 minutes ago unruffled_gagarin root@MSI:~# docker rm da83 da83 root@MSI:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES root@MSI:~# root@MSI:~# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE python latest 17e65561fd2c 5 days ago 1.02GB root@MSI:~# docker rmi python Untagged: python:latest Untagged: python@sha256:2586dd7abe015eeb6673bc66d18f0a628a997c293b41268bc981e826bc0b5a92 Deleted: sha256:17e65561fd2c7ecae6297c2cc049960607ff94f92f6a1ca3857f94569fc9c199 Deleted: sha256:781e8bd079dcc84a458a8f4f3a150194c7d4d97e99f46c969a5f021443245582 Deleted: sha256:fe26881c5fffddca7e97ebdd52578444af7a9c2b490ba91b5d793de4d8c3c984 Deleted: sha256:75a8404e2d8b812db31af6bafa0c0cb4c8deaf763ab5134484213933def00b09 Deleted: sha256:3a78d30473881be3a54a8b6a11de5da7ac2dd645c813dcb7331527a30e50a993 Deleted: sha256:354f4b6949596277291588a6a2b924144fa72edbc21ff3c12e168187e233fd0d Deleted: sha256:2fa37f2ee66efbd308b9b91bce81c262f5e6ab6c3bf8056632afc60cc602785c root@MSI:~# root@MSI:~# docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE root@MSI:~#
That's it. This is all you need to know to start with Docker. Remember, there are many more advanced features in Docker, start by experimenting with containers and getting hands-on with Docker.