DEV Community

Cover image for Getting Started with Docker: A Hands-On Guide to Containerization and Orchestration"
Seyi Lufadeju
Seyi Lufadeju

Posted on

Getting Started with Docker: A Hands-On Guide to Containerization and Orchestration"

Table of contents


INTRODUCTION

What is Docker?
Docker is an open-source that allows developers to streamline the deployment, scaling, and administration of applications through the use of containers. Containers bundle an application along with its dependencies to guarantee uniformity across various environments.

Why Use Docker?

  • Portability – Run applications anywhere (local, cloud, or on-premise).
  • Efficiency – Uses fewer resources compared to virtual machines (VMs).
  • Scalability – Easily scale applications up or down.
  • Faster Deployment – Containers start in milliseconds.
  • Consistent Environment – Ensures that applications work the same in development, testing, and production.

DOCKER INSTALLATION

Installing Docker
Docker provides different installation options based on your operating system:

Windows

  • Download Docker Desktop from Docker's official site.
  • Install Docker Desktop and enable WSL 2 backend if prompted.
  • Start Docker Desktop and ensure it is running.
  • Open Command Prompt (cmd) or PowerShell and verify the installation with:
docker --version
Enter fullscreen mode Exit fullscreen mode

MacOS

  • Download Docker Desktop for Mac from Docker's official site.
  • Install and launch Docker Desktop.
  • Verify installation
docker --version
Enter fullscreen mode Exit fullscreen mode

Linux (Ubuntu)

  • Update existing packages
sudo apt update
sudo apt install -y ca-certificates curl gnupg

Enter fullscreen mode Exit fullscreen mode
  • Add Docker’s GPG key:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
sudo chmod a+r /etc/apt/keyrings/docker.asc

Enter fullscreen mode Exit fullscreen mode
  • Set up the repository:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Enter fullscreen mode Exit fullscreen mode
  • Install Docker:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Enter fullscreen mode Exit fullscreen mode
  • Start Docker and verify
sudo systemctl start docker
sudo systemctl enable docker
docker --version

Enter fullscreen mode Exit fullscreen mode

UNDERSTANDING DOCKER BASIC COMMANDS

Here are essential Docker commands to get familiar with:

  • Checking Docker Installation
docker --version
docker info

Enter fullscreen mode Exit fullscreen mode

Working with Images

  • List available images
docker images

Enter fullscreen mode Exit fullscreen mode
  • Download a new image:
docker pull <image_name>

Example:
docker pull nginx

Enter fullscreen mode Exit fullscreen mode
  • Remove an image
docker rmi <image_id>

Enter fullscreen mode Exit fullscreen mode

Working with Containers

  • Run a container:
docker run <image_name>

Example:
docker run nginx

Enter fullscreen mode Exit fullscreen mode
  • List running containers:
docker ps

Enter fullscreen mode Exit fullscreen mode
  • List all containers (including stopped ones):
docker ps -a

Enter fullscreen mode Exit fullscreen mode
  • Stop a running container:
docker stop <container_id>

Enter fullscreen mode Exit fullscreen mode
  • Remove a container:
docker rm <container_id>

Enter fullscreen mode Exit fullscreen mode

CONTAINERIZE AN APPLICATION

Before you can run the application, you need to get the application source code onto your machine.

git clone https://github.com/docker/getting-started-app.git
Enter fullscreen mode Exit fullscreen mode
  • View the contents of the cloned repository. You should see the following files and sub-directories.

Image description


Build the app's image
To build the image, you'll need to use a Dockerfile. A Dockerfile is simply a text-based file with no file extension that contains a script of instructions. Docker uses this script to build a container image.

  • In the getting-started-app directory, the same location as the package.json file, create a file named Dockerfile with the following contents:

Image description

This Dockerfile starts off with a node:lts-alpine base image, a light-weight Linux image that comes with Node.js and the Yarn package manager pre-installed. It copies all of the source code into the image, installs the necessary dependencies, and starts the application.

  • Build the image using the following commands:

In the terminal, make sure you're in the getting-started-app directory. Replace /path/to/getting-started-app with the path to your getting-started-app directory.

cd /path/to/getting-started-app
Enter fullscreen mode Exit fullscreen mode

Build the image.

docker build -t getting-started .
Enter fullscreen mode Exit fullscreen mode

The docker build command uses the Dockerfile to build a new image. You might have noticed that Docker downloaded a lot of "layers". This is because you instructed the builder that you wanted to start from the node:lts-alpine image. But, since you didn't have that on your machine, Docker needed to download the image.

After Docker downloaded the image, the instructions from the Dockerfile copied in your application and used yarn to install your application's dependencies. The CMD directive specifies the default command to run when starting a container from this image.

Finally, the -t flag tags your image. Think of this as a human-readable name for the final image. Since you named the image getting-started, you can refer to that image when you run a container.

The . at the end of the docker build command tells Docker that it should look for the Dockerfile in the current directory.

Image description


Start an app container
Now that you have an image, you can run the application in a container using the docker run command.

  • Run your container using the docker run command and specify the name of the image you just created:
docker run -d -p 127.0.0.1:3000:3000 getting-started
Enter fullscreen mode Exit fullscreen mode

The -d flag (short for --detach) runs the container in the background. This means that Docker starts your container and returns you to the terminal prompt. Also, it does not display logs in the terminal.

The -p flag (short for --publish) creates a port mapping between the host and the container. The -p flag takes a string value in the format of HOST:CONTAINER, where HOST is the address on the host, and CONTAINER is the port on the container. The command publishes the container's port 3000 to 127.0.0.1:3000 (localhost:3000) on the host. Without the port mapping, you wouldn't be able to access the application from the host.

Image description

Run the docker ps command in a terminal to list your containers.

docker ps
Enter fullscreen mode Exit fullscreen mode

Output similar to the following should appear.

Image description


UPDATE THE APPLICATION

In part 1, we containerized a todo application. In this part, we'll update the application and image. we'll also learn how to stop and remove a container.

Update the source code

In the following steps, you'll change the "empty text" when you don't have any todo list items to "You have no todo items yet! Add one above!"

  • In the src/static/js/app.js file, update line 56 to use the new empty text.
- <p className="text-center">No items yet! Add one above!</p>
+ <p className="text-center">You have no todo items yet! Add one above!</p>
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

  • Build your updated version of the image, using the docker build command.
docker build -t getting-started .
Enter fullscreen mode Exit fullscreen mode
  • Start a new container using the updated code.
docker run -dp 127.0.0.1:3000:3000 getting-started
Enter fullscreen mode Exit fullscreen mode

You probably saw an error like this:

docker: Error response from daemon: driver failed programming external connectivity on endpoint laughing_burnell 
(bb242b2ca4d67eba76e79474fb36bb5125708ebdabd7f45c8eaf16caaabde9dd): Bind for 127.0.0.1:3000 failed: port is already allocated.
Enter fullscreen mode Exit fullscreen mode

The error occurred because you aren't able to start the new container while your old container is still running. The reason is that the old container is already using the host's port 3000 and only one process on the machine (containers included) can listen to a specific port. To fix this, you need to remove the old container.


Remove the old container

  • Get the ID of the container by using the docker ps command.

Image description

  • Use the docker stop command to stop the container. Replace with the ID from docker ps.
docker stop <the-container-id>
Enter fullscreen mode Exit fullscreen mode

Image description

  • Once the container has stopped, you can remove it by using the docker rm command.

Image description

Start the updated app container
Now, start your updated app using the docker run command.

docker run -dp 127.0.0.1:3000:3000 getting-started
Enter fullscreen mode Exit fullscreen mode

Image description


Share the application

Now that you've built an image, you can share it. To share Docker images, you have to use a Docker registry. The default registry is Docker Hub and is where all of the images you've used have come from.


Push the image

  • Sign in to Docker Hub using the command docker login -u YOUR-USER-NAME

Image description

  • Use the docker tag command to give the getting-started image a new name. Replace YOUR-USER-NAME with your Docker ID.
docker tag getting-started YOUR-USER-NAME/getting-started
Enter fullscreen mode Exit fullscreen mode
  • Now run the docker push command again. If you're copying the value from Docker Hub, you can drop the tagname part, as you didn't add a tag to the image name. If you don't specify a tag, Docker uses a tag called latest.

Image description

Image description


CREATING A MULTI-CONTAINER APPLICATION WITH DOCKER

Introduction
With Docker Compose, you can define all of your containers and their configurations in a single YAML file. If you include this file in your code repository, anyone that clones your repository can get up and running with a single command.

It's important to understand that Compose is a declarative tool - you simply define it and go. You don't always need to recreate everything from scratch. If you make a change, run docker compose up again and Compose will reconcile the changes in your file and apply them intelligently.


Dockerfile versus Compose file

A Dockerfile provides instructions to build a container image while a Compose file defines your running containers. Quite often, a Compose file references a Dockerfile to build an image to use for a particular service.


Step by Step Guide

  • Download and install Docker Desktop.

  • Open a terminal and clone this sample application

git clone https://github.com/dockersamples/todo-list-app 
Enter fullscreen mode Exit fullscreen mode

Image description

  • Navigate into the todo-list-app directory:
cd todo-list-app
Enter fullscreen mode Exit fullscreen mode

Inside this directory, you'll find a file named compose.yaml. This YAML file is where all the magic happens! It defines all the services that make up your application, along with their configurations. Each service specifies its image, ports, volumes, networks, and any other settings necessary for its functionality. Take some time to explore the YAML file and familiarize yourself with its structure.

Image description

Use the docker compose up command to start the application:

docker compose up -d --build
Enter fullscreen mode Exit fullscreen mode

When you run this command, you should see an output like this:

Image description


Two container images were downloaded from Docker Hub - node and MySQL
A network was created for your application
A volume was created to persist the database files between container restarts
Two containers were started with all of their necessary config

  • With everything now up and running, you can open http://localhost:3000 in your browser to see the site. Feel free to add items to the list, check them off, and remove them.

Image description

  • If you look at the Docker Desktop GUI, you can see the containers and dive deeper into their configuration.

Image description

We defined services in a docker-compose.yml file, set up network connections, and ran everything with a single command. This approach simplifies development, ensures environment consistency, and is a great foundation for deploying applications to cloud environments.


SUMMARY

This guide provides a comprehensive introduction to Docker, covering essential concepts and practical implementations.

  • Introduction: An overview of Docker, its significance in modern software development, and its advantages in containerization.
  • Docker Installation: Step-by-step instructions to install Docker on various operating systems, ensuring a proper setup for containerized development.
  • Understanding Docker Basic Commands: A hands-on exploration of fundamental Docker commands to manage containers, images, and networks efficiently.
  • Containerize an Application: A practical approach to packaging an application into a Docker container, making it portable and scalable.
  • Update the Application: Techniques for modifying and updating containerized applications while maintaining version control and stability.
  • Share the Application: Methods to push container images to Docker Hub or other registries for seamless collaboration and deployment.
  • Creating a Multi-Container Application with Docker Compose: An introduction to Docker Compose, demonstrating how to define and manage multi-container applications for complex environments.

Top comments (2)

Collapse
 
madhurima_rawat profile image
Madhurima Rawat

Great article 👏. I recently started working with docker and this is super helpful.

Collapse
 
david_j_eddy profile image
David J Eddy

Try podman, same commands, less corporate money grabbing.