Kubernetes Overview · Part 0505

Docker InstallationmacOS, Windows and Linux

From zero to a real running container: a step-by-step guide to installing Docker on macOS, Windows and Linux, verifying the installation and testing it with Nginx and Docker Compose.

Translated from the original Bangla with AI. If anything reads oddly, the Bangla version is the reference.

Docker installation paths: Docker Desktop on macOS and Windows with WSL 2, Docker Engine on Linux, then a hello-world and Nginx container test
FIG. 05 Docker Desktop on macOS and Windows, Docker Engine on Linux, then a real container to verify it.

In this tutorial, we will learn how to install Docker on macOS, Windows and Linux, how to verify that the installation worked, and how to test Docker by running a real container.

Before installing Docker, there is one thing to understand: the installation process is not the same on every operating system.

We usually use one of two installation approaches:

macOS / Windows
       ↓
Docker Desktop
       ↓
Docker Engine
       ↓
Containers

Linux Server
       ↓
Docker Engine
       ↓
containerd
       ↓
Containers

What is Docker Desktop?

Docker Desktop is a desktop application that makes Docker easy to use, mainly on macOS and Windows. It includes Docker Engine, the Docker CLI, Docker Compose and a graphical user interface (GUI).

What is Docker Engine?

Docker Engine is Docker’s core container management technology. It helps create, start, stop and manage containers. On Linux servers and in production environments, Docker Engine is usually installed directly.

What is Docker Compose?

Docker Compose lets us manage one or more containers through a YAML configuration file.

For example, Docker Compose can run an application’s backend, database and Redis cache together.

1. Installing Docker on macOS

The easiest way to install Docker on macOS is to use Docker Desktop.

Step 1: Check your Mac’s processor architecture

First, open Terminal and run this command:

uname -m

Possible output:

arm64   → Apple Silicon (M1, M2, M3, M4 etc.)

x86_64  → Intel Mac

Why check this?

Because Docker Desktop has separate installers for Apple Silicon and Intel Macs.

Downloading the wrong installer can cause installation or compatibility problems.

Step 2: Download Docker Desktop

Download the installer from Docker’s official website:

https://docs.docker.com/desktop/setup/install/mac-install/

Choose the installer that matches your processor.

Apple Silicon Mac → Apple Silicon Version

Intel Mac         → Intel Version

Step 3: Install Docker Desktop

Open the downloaded .dmg file.

Then:

Docker.dmg
     ↓
Docker.app
     ↓
Applications Folder
     ↓
Open Docker Desktop

The first time Docker Desktop starts, macOS may ask for some system permissions.

Approve the permissions it needs.

Once Docker Desktop has fully started, you will see the Docker icon in the menu bar.

Step 4: Verify the Docker installation

Open Terminal and run these commands:

docker --version

docker compose version

docker run hello-world

If the installation worked, the output will include:

Hello from Docker!

What actually happened here?

When you run docker run hello-world, Docker first checks whether the hello-world image exists on the local system.

If it doesn’t, Docker downloads it from Docker Hub.

It then uses that image to create and run a container.

When the container runs successfully, we see the Hello from Docker! message.

In other words, Docker Engine is working correctly.

Step 5: Run a real Nginx container

Now let’s run an actual web server container.

docker run -d --name test-nginx -p 8080:80 nginx

Let’s go through each part of this command:

ParameterWhat it does
docker runCreates and runs a new container
-dRuns the container in the background
--name test-nginxGives the container a name
-p 8080:80Connects port 8080 on the host to port 80 in the container
nginxUses the Nginx Docker image

Now open a browser and go to:

http://localhost:8080

If everything is working, you will see the Welcome to nginx! page.

This means a real web server is running inside a Docker container.

Stop and remove the container

When you have finished testing:

docker stop test-nginx

docker rm test-nginx

The first command stops the container and the second removes it.

That verifies the Docker installation and basic container execution on macOS.

2. Installing Docker on Windows

Installing Docker on Windows is a little different.

That’s because Windows usually uses WSL 2 to run Docker’s Linux containers.

WSL stands for: Windows Subsystem for Linux.

WSL lets you run a Linux environment inside Windows.

Our installation architecture will be:

Windows 10 / Windows 11
             ↓
            WSL 2
             ↓
       Docker Desktop
             ↓
        Docker Engine
             ↓
       Linux Containers

Step 1: Check the Windows requirements

Before installing Docker Desktop, make sure that:

  • You are using a supported version of Windows 10 or Windows 11.
  • The system supports virtualization and it is enabled.
  • WSL 2 can be installed.
  • The system meets Docker Desktop’s minimum hardware requirements.

Official requirements:

https://docs.docker.com/desktop/setup/install/windows-install/

Step 2: Install WSL 2

Search for PowerShell in the Windows Start menu.

Then select Run as Administrator.

Run this command:

wsl --install

This command installs the components WSL needs, and usually installs a default Linux distribution.

If Windows asks you to restart, restart it.

Update WSL

wsl --update

Check the WSL status

wsl --status

Check the installed Linux distributions

wsl -l -v

Example output:

NAME       STATE      VERSION

Ubuntu     Running    2

Here, VERSION 2 means Ubuntu is using WSL 2.

If a distribution uses WSL 1, convert it to WSL 2 if needed.

Example:

wsl --set-version Ubuntu 2

Step 3: Install Docker Desktop

Download the Windows installer from the official Docker website:

https://docs.docker.com/desktop/setup/install/windows-install/

When running the installer, enable the WSL 2 backend if the option is offered.

Installation workflow:

Download Docker Desktop
           ↓
Run Installer
           ↓
Enable WSL 2 Backend
           ↓
Complete Installation
           ↓
Launch Docker Desktop

After starting Docker Desktop, make sure Linux containers mode is enabled.

Step 4: Enable WSL integration

Open Docker Desktop.

Then:

Docker Desktop
      ↓
Settings
      ↓
Resources
      ↓
WSL Integration
      ↓
Enable Ubuntu / Debian
      ↓
Apply & Restart

Why is WSL integration important?

Say you want to run Docker commands from the Ubuntu terminal on Windows.

With WSL integration enabled, the Ubuntu terminal can use Docker Desktop’s Docker Engine directly.

This makes it easier to work across the Windows and Linux development environments.

Step 5: Verify Docker from PowerShell

Open PowerShell and run:

docker --version

docker compose version

docker run hello-world

Expected output:

Hello from Docker!

Step 6: Verify Docker from WSL Ubuntu

Now open the Ubuntu terminal.

docker --version

docker compose version

docker run hello-world

If you see Hello from Docker! here too, WSL integration is working correctly.

Important: When you use Docker Desktop, you usually don’t need to install Docker Engine separately inside WSL Ubuntu.

Step 7: Run a real Nginx container

From PowerShell or the WSL Ubuntu terminal:

docker run -d --name test-nginx -p 8080:80 nginx

Go to this address in a browser:

http://localhost:8080

If you see the Nginx welcome page, the container is running successfully.

Cleanup

docker stop test-nginx

docker rm test-nginx

You have now tested Docker Desktop, Docker Engine, WSL integration and container execution on Windows.

3. Installing Docker on Linux — Ubuntu / Debian

On Linux servers, Docker is usually installed as Docker Engine.

This is especially common on servers, virtual machines (VMs), cloud infrastructure and on-premises environments.

Here we install Docker Engine directly instead of Docker Desktop.

Step 1: Remove old or conflicting Docker packages

Before installing Docker’s official packages, you may need to remove conflicting packages.

sudo apt remove \
  docker.io \
  docker-doc \
  docker-compose \
  docker-compose-v2 \
  podman-docker \
  containerd \
  runc

Why remove them?

Ubuntu’s or Debian’s default repositories may contain some Docker-related packages.

These can conflict with the packages installed from Docker’s official repository.

However, before running this command on an existing production server, make sure no running application depends on the old Docker or containerd installation.

Step 2: Install the required dependencies

First, update the package list:

sudo apt update

Then:

sudo apt install -y ca-certificates curl

Here:

PackageWhat it does
ca-certificatesCertificate validation for HTTPS connections
curlDownloads files from the internet

Step 3: Add Docker’s official GPG key

To verify Docker’s package repository, add Docker’s official GPG key.

For Ubuntu:

sudo install -m 0755 -d /etc/apt/keyrings

sudo curl -fsSL \
  https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc

sudo chmod a+r /etc/apt/keyrings/docker.asc

For Debian:

Follow the same process, but the GPG key URL is:

https://download.docker.com/linux/debian/gpg

Why use a GPG key?

With the GPG key, the package manager can verify that the Docker packages come from a trusted source and that the repository metadata’s signature is valid.

Step 4: Add Docker’s official repository

Now tell the operating system where to find the Docker packages.

Ubuntu repository

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Debian repository

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker’s official repository is now configured.

Step 5: Install Docker Engine

First, update the package list:

sudo apt update

Then install Docker Engine and the related tools:

sudo apt install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

This command installs several important Docker components.

PackageDescription
docker-ceDocker Community Edition Engine
docker-ce-cliDocker Command Line Interface
containerd.ioContainer Runtime
docker-buildx-pluginAdvanced Docker Image Building
docker-compose-pluginMulti-Container Application Management

Step 6: Start the Docker service

Once Docker is installed, start the service.

sudo systemctl enable --now docker

Check the service status:

sudo systemctl status docker

Expected result:

Active: active (running)

What the command means:

enable configures the Docker service to start automatically when the system boots.

--now starts the service immediately.

Step 7: Verify the Docker installation

Now run:

sudo docker --version

sudo docker compose version

sudo docker run hello-world

Expected:

Hello from Docker!

This confirms that Docker can run containers successfully.

Step 8: Use Docker without sudo (optional)

On Linux, running Docker commands usually requires root privileges or permission on the Docker socket.

In a development environment, if you don’t want to type sudo every time, you can add your user to the Docker group.

sudo usermod -aG docker "$USER"

Then:

newgrp docker

Test:

docker run hello-world

Security warning:

A user in the Docker group can effectively get root-level privileges. On a production server, give this permission only to trusted administrators.

For more restricted environments, consider Rootless Docker.

Step 9: Test a real Nginx container

Now let’s run an Nginx web server:

docker run -d --name test-nginx -p 8080:80 nginx

Container status:

docker ps

Send an HTTP request:

curl http://localhost:8080

The expected result is Nginx’s HTML response.

This means the Nginx web server inside the container is working correctly.

Container cleanup

docker stop test-nginx

docker rm test-nginx

Note: On a remote Linux server, localhost means that server. To reach it from a browser on your own computer, you need to consider the server IP, the network route and the firewall configuration.

4. Installing Docker on Fedora Linux

Fedora Linux uses dnf for package management.

So Ubuntu’s apt commands won’t work here.

Step 1: Remove old Docker packages

sudo dnf remove \
  docker \
  docker-client \
  docker-client-latest \
  docker-common \
  docker-latest \
  docker-latest-logrotate \
  docker-logrotate \
  docker-selinux \
  docker-engine-selinux \
  docker-engine

Step 2: Install the DNF plugins

sudo dnf -y install dnf-plugins-core

Step 3: Add the Docker repository

On newer, DNF5-based Fedora:

sudo dnf config-manager addrepo \
  --from-repofile \
  https://download.docker.com/linux/fedora/docker-ce.repo

On older, DNF4-based Fedora:

sudo dnf config-manager --add-repo \
  https://download.docker.com/linux/fedora/docker-ce.repo

Step 4: Install Docker Engine

sudo dnf install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

Step 5: Start the Docker service

sudo systemctl enable --now docker

Step 6: Verify Docker

sudo docker run hello-world

Expected:

Hello from Docker!

The basic Docker installation on Fedora is now complete.

5. Installing Docker on RHEL / CentOS / Rocky / AlmaLinux

The installation process on RHEL-based Linux distributions is very similar to Fedora’s.

However, you need to select the correct Docker repository for your distribution.

Step 1: Install the DNF plugins

sudo dnf install -y dnf-plugins-core

Step 2: Add the Docker repository

CentOS

sudo dnf config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo

RHEL

sudo dnf config-manager --add-repo \
  https://download.docker.com/linux/rhel/docker-ce.repo

On a DNF5-based system, you may need the config-manager addrepo --from-repofile syntax instead.

Rocky Linux and AlmaLinux: on these distributions, check your OS version and Docker’s package support before using a compatible Docker repository.

Step 3: Install Docker Engine

sudo dnf install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

Step 4: Start the Docker service

sudo systemctl enable --now docker

Step 5: Verify the installation

sudo docker run hello-world

Expected:

Hello from Docker!

This confirms, at a basic level, that Docker Engine is configured properly.

6. Docker Post-Installation Verification

After installing Docker, you should run a few standard verification commands.

They help make sure the Docker CLI, Docker Engine and Docker Compose are working correctly.

docker --version

docker compose version

docker info

docker run --rm hello-world

What does each command verify?

CommandVerification
docker --versionWhether the Docker CLI is installed
docker compose versionWhether Docker Compose is available
docker infoWhether the CLI can connect to Docker Engine
docker run --rm hello-worldWhether containers can run

One important point:

A successful docker --version alone doesn’t mean Docker Engine is running.

The Docker CLI can be installed while the Docker daemon is stopped.

That’s why verifying with docker info and docker run hello-world matters.

Real web container verification

Run an Nginx container:

docker run -d --name web-test -p 8080:80 nginx

List the running containers:

docker ps

Open in a browser:

http://localhost:8080

If you see the Nginx welcome page, container networking and the HTTP service are working at a basic level.

When you’re done:

docker stop web-test

docker rm web-test

7. Testing a Real Application with Docker Compose

So far, we have used docker run to start one container at a time.

But real-world applications are usually made up of several containers.

For example:

Web Application
      |
      +── Frontend Container
      |
      +── Backend API Container
      |
      +── PostgreSQL Container
      |
      +── Redis Container

Docker Compose is used to manage this kind of multi-container architecture.

Here we’ll test Compose with a simple Nginx service.

Step 1: Create a project directory

In the terminal:

mkdir docker-test

cd docker-test

Step 2: Create the Compose configuration file

Create a file called compose.yaml in the project directory.

The file’s content:

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"

What have we defined in this YAML file?

services: where the application’s services are defined.

web: the name of our service.

image: the Nginx image will be used to create the container.

ports: port 8080 on the host machine connects to port 80 in the container.

Step 3: Start the container with Docker Compose

docker compose up -d

When you run this command, Docker Compose will:

  1. Read the configuration file.
  2. Check whether the required Docker image exists locally.
  3. Download the image if it doesn’t.
  4. Create the network and the container.
  5. Start the container in the background.

Step 4: Check the running services

docker compose ps

Now send an HTTP request:

curl http://localhost:8080

In Windows PowerShell, you can use:

curl.exe http://localhost:8080

You can also verify it from a browser:

http://localhost:8080

Step 5: Stop the Docker Compose services

docker compose down

This command removes the Compose project’s containers and its default network.

What did we learn?

With Docker Compose, we can start, manage and stop containers through a YAML configuration.

Later, the same approach can deploy a backend, PostgreSQL, Redis, Apache Kafka or AI/ML services.

8. Docker, containerd, ctr, nerdctl and crictl — What’s the Difference?

A common confusion comes up while learning Docker.

What is the relationship between Docker Engine, containerd, runc, ctr, nerdctl, crictl and kubectl?

To understand it simply, look at this architecture:

Docker CLI
    |
    v

Docker Engine (dockerd)
    |
    v

containerd
    |
    v

runc
    |
    v

Linux Containers

Now let’s go through them one by one.

Docker CLI

The Docker CLI is Docker’s command-line interface.

For example:

docker ps
docker images
docker run nginx

We use these commands to communicate with Docker Engine.

containerd

containerd is a container runtime that provides the functionality for managing the container lifecycle.

Docker Engine uses containerd internally.

But containerd can also be used directly, without the Docker CLI.

ctr — containerd’s native CLI

ctr is containerd’s low-level command-line client.

Example:

sudo ctr containers list

This shows the containers in containerd’s default namespace.

To inspect Kubernetes’s containerd namespace:

sudo ctr -n k8s.io containers list

ctr is usually used for debugging and for understanding containerd’s internals.

nerdctl — a Docker-like CLI for containerd

nerdctl is a Docker-compatible CLI.

It works directly with containerd.

If you are familiar with Docker commands, nerdctl is relatively easy to use.

Example:

nerdctl ps
nerdctl images
nerdctl run nginx

However, you may need to install and configure nerdctl separately before using it.

crictl — Kubernetes runtime troubleshooting

crictl is the debugging tool for the Container Runtime Interface (CRI).

It is used to troubleshoot the container runtime on a Kubernetes node.

Example:

sudo crictl ps
sudo crictl images
sudo crictl pods

It is especially useful when troubleshooting a containerd-backed Kubernetes node.

kubectl — the Kubernetes management CLI

kubectl manages cluster resources through the Kubernetes API Server.

Example:

kubectl get pods -A
kubectl get nodes
kubectl get deployments -A

Which tool should I use when?

ToolPrimary Use Case
dockerManaging Docker containers and images
ctrLow-level containerd debugging
nerdctlDocker-like workflow directly on containerd
crictlKubernetes container runtime troubleshooting
kubectlManaging Kubernetes clusters and workloads

Remember: installing Docker doesn’t automatically install all of these CLIs. Each tool has its own use case and installation requirements.

9. Final Docker Validation — Complete Test

Now let’s run a complete validation.

You can use it on macOS, Windows and Linux, as long as Docker Engine is running and the necessary permissions are configured.

# Step 1: Check the Docker client and server
docker version

# Step 2: Check Docker Compose
docker compose version

# Step 3: Run the hello-world container
docker run --rm hello-world

# Step 4: Test an Alpine Linux container
docker run --rm alpine uname -a

# Step 5: Start an Nginx web server
docker run -d --name nginx-test -p 8080:80 nginx

# Step 6: Test the web server over HTTP
curl http://localhost:8080

# Step 7: Check the container logs
docker logs nginx-test

# Step 8: Check the running containers
docker ps

# Step 9: Stop the container
docker stop nginx-test

# Step 10: Remove the container
docker rm nginx-test

Expected success results

TestExpected Output
Docker VersionClient and Server details
Compose VersionDocker Compose v2
Hello WorldHello from Docker!
Alpine ContainerLinux Kernel information
Nginx ContainerContainer successfully started
HTTP RequestNginx HTML response
Container LogsLogs accessible
Docker PSThe running container is listed
CleanupContainer successfully removed

If all the tests pass, Docker’s installation, Engine connectivity, container execution, basic networking and Compose functionality are working.

But remember: installation validation and production readiness are not the same thing.

A production environment needs more configuration:

  • Container Security and Image Scanning
  • Resource Limits (CPU and Memory)
  • Persistent Volumes and Storage
  • Logging and Monitoring
  • Network Security and Firewall
  • Secrets Management
  • Backup and Recovery
  • Container Health Checks
  • Image Version Pinning

10. Complete Docker Installation Summary

Now let’s look at the whole installation process once more, briefly.

                  Operating System
                         |
            +------------+------------+
            |                         |
      macOS / Windows             Linux Server
            |                         |
      Docker Desktop             Docker Engine
            |                         |
            +------------+------------+
                         |
                     Docker CLI
                         |
                  Docker Engine
                         |
                     containerd
                         |
                       runc
                         |
                    Containers
                         |
                +--------+--------+
                |        |        |
              Nginx    Backend  Database

If you use macOS

Download and install Docker Desktop. Then verify it by running docker run hello-world and an Nginx container.

If you use Windows

Set up WSL 2, install Docker Desktop and enable WSL integration. Then you can test Docker commands from PowerShell and the Ubuntu terminal.

If you use a Linux server

Configure Docker’s official repository, install Docker Engine and enable the Docker service. Then verify the installation by running a container.

If you want to run multiple containers

Use Docker Compose. It lets you manage an application’s different services together through one YAML file.

If you want to use containerd directly

Use ctr for low-level operations and nerdctl for a Docker-like workflow.

If you work in a Kubernetes environment

Use crictl to troubleshoot the container runtime and kubectl to manage Kubernetes objects.

Official Documentation & References

For more detail, use the official Docker and containerd documentation.

Final Takeaway

The point of learning Docker installation isn’t just installing software; it’s understanding Docker’s complete workflow.

As a developer, or a DevOps or AI engineer, you should know:

How Docker is installed → how Docker Engine works → how a container is created from a Docker image → how port mapping works → how to run multiple services with Docker Compose → how container runtimes relate to Kubernetes.

Once you have completed this installation and verification process, you are ready to use Docker to containerize web applications, backend APIs, databases, data engineering services and AI/ML applications.

The next steps are learning Dockerfiles, Docker images, volumes, networks, Docker Compose and container security in detail.

Was this guide helpful?

Search the archive

Press Esc to close