Simplifying Docker.

Simplifying Docker.

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.