DEV Community

Cover image for Mastering Docker Basics: A Comprehensive Guide for Beginners
Tandap Noel Bansikah
Tandap Noel Bansikah

Posted on • Edited on

Mastering Docker Basics: A Comprehensive Guide for Beginners

Docker Basics for Beginners

Welcome to the world of Docker! This article provides a detailed overview of essential topics and commands to help you get started with containerization. Whether you're a developer, system administrator, or just curious about modern application deployment, this guide is tailored for you.


1. Introduction to Docker

What is Docker?

Docker is an open-source platform designed to simplify application development and deployment. It allows developers to package applications and their dependencies into lightweight, portable containers that can run consistently across various environments.

Why use Docker?

Docker has become a popular choice due to its numerous benefits:

  • Portability: Applications packaged in containers can run anywhere Docker is installed, from your laptop to a production server.
  • Efficiency: Containers use fewer resources compared to virtual machines, as they share the host system's OS kernel.
  • Scalability: With orchestration tools like Kubernetes, scaling containerized applications becomes straightforward.
  • Isolation: Each container runs independently, avoiding conflicts between applications.

2. Docker Installation

Steps to Install Docker

  1. Windows/MacOS:

    • Download and install Docker Desktop.
    • Ensure that virtualization is enabled on your machine.
  2. Linux:

     sudo apt update sudo apt install -y docker.io sudo systemctl start docker sudo systemctl enable docker 
  3. Verify Installation:
    Run the following command to check the Docker version:

 docker --version 
Enter fullscreen mode Exit fullscreen mode

3. Core Concepts

Understanding the core concepts is essential to using Docker effectively:

  • Images: Immutable templates that define how a container is built. Think of them as blueprints.
  • Containers: Running instances of Docker images. Containers are isolated and lightweight.
  • Dockerfile: A script that automates the creation of Docker images.
  • Volumes: Mechanisms for persisting data generated by containers.
  • Networks: Enable communication between containers.

4. Basic Docker Commands

Working with Images

  • Pull an Image: Download an image from Docker Hub or another registry.
 docker pull <image_name> 
Enter fullscreen mode Exit fullscreen mode
  • List Images: View all downloaded images on your system.
 docker images 
Enter fullscreen mode Exit fullscreen mode
  • Remove an Image: Delete unused images to save space.
 docker rmi <image_id> 
Enter fullscreen mode Exit fullscreen mode

Working with Containers

  • Run a Container: Start a container from an image.
 docker run -d -p 8080:80 <image_name> 
Enter fullscreen mode Exit fullscreen mode
  • -d: Run in detached mode.
  • -p: Map host ports to container ports.
    • List Running Containers:
 docker ps -a 
Enter fullscreen mode Exit fullscreen mode
  • -a means list all containers
  • Stop a Container:
 docker stop <container_id> 
Enter fullscreen mode Exit fullscreen mode
  • Remove a Container:
 docker rm <container_id> 
Enter fullscreen mode Exit fullscreen mode
  • Execute Commands Inside a Container:
 docker exec -it <container_id> bash 
Enter fullscreen mode Exit fullscreen mode

Inspecting and Managing Containers

  • Inspect a Container: View detailed information about a container.
 docker inspect <container_id> 
Enter fullscreen mode Exit fullscreen mode
  • View Logs: Access logs for debugging.
 docker logs <container_id> 
Enter fullscreen mode Exit fullscreen mode

5. Building Docker Images

What is a Dockerfile?

A Dockerfile is a text file containing a series of instructions to create a Docker image. It specifies the base image, the dependencies, and the commands required to run your application. Each instruction in the Dockerfile creates a layer in the image, which is cached and can be reused to speed up future builds.

Common Dockerfile Commands:

  • FROM: This is the first command in a Dockerfile. It sets the base image for the image you are building. Every Docker image starts from a base image, which could be something like ubuntu, node, or python, depending on your application's requirements. Example:
 FROM node:14 
Enter fullscreen mode Exit fullscreen mode
  • RUN: This command is used to execute commands inside the container, like installing dependencies, running scripts, or building the app. Each RUN instruction creates a new layer. Example:
RUN npm install 
Enter fullscreen mode Exit fullscreen mode
  • COPY: This command copies files or directories from your local system into the Docker image. Example:
COPY . /app 
Enter fullscreen mode Exit fullscreen mode

. means copy all from root director into the /app direcotory inside the container.

  • ADD: Similar to COPY, but with additional functionality, such as automatically extracting compressed files or pulling files from a URL. Example:
ADD myapp.tar.gz /app 
Enter fullscreen mode Exit fullscreen mode
  • CMD: This command specifies the default command to run when the container starts. It can be overridden by providing a command when running the container. Example:
CMD ["node", "app.js"] 
Enter fullscreen mode Exit fullscreen mode
  • ENTRYPOINT: Sets the default executable for the container. Unlike CMD, ENTRYPOINT cannot be overridden by arguments provided at runtime. Example:
ENTRYPOINT ["python", "app.py"] 
Enter fullscreen mode Exit fullscreen mode
  • EXPOSE: This command informs Docker that the container listens on a specific network port at runtime. It does not publish the port but acts as documentation for the container's expected network usage. Example:
EXPOSE 8080 
Enter fullscreen mode Exit fullscreen mode
  • ENV: Defines environment variables in the container, which can be accessed by the application or any other processes inside the container. Example:
ENV NODE_ENV=production 
Enter fullscreen mode Exit fullscreen mode
  • WORKDIR: Sets the working directory for the container. All subsequent commands will be run in this directory. Example:
WORKDIR /app 
Enter fullscreen mode Exit fullscreen mode
  • VOLUME: Creates a mount point inside the container, allowing for persistent data storage across container restarts. Example:
VOLUME ["/data"] 
Enter fullscreen mode Exit fullscreen mode
  • **USER: Sets the user name or UID to use when running the container. This can improve security by running the container with a non-root user. Example:
USER appuser 
Enter fullscreen mode Exit fullscreen mode
  • MAINTAINER: This command allows you to specify the author or maintainer of the Docker image. This is useful for tracking who is responsible for the image. Example:
MAINTAINER John Doe <john.doe@example.com> 
Enter fullscreen mode Exit fullscreen mode

The about are just the commonly used commands used in a dockerfile to build a particular image, you can always explore more on the docker official documentation

Example Dockerfile

This Dockerfile creates an image for a simple Node.js application:

# Use a base image FROM node:16 # Set the working directory WORKDIR /app # Copy application files COPY package.json ./ COPY . ./ # Install dependencies RUN npm install # Expose a port EXPOSE 3000 # Start the application CMD ["npm", "start"] 
Enter fullscreen mode Exit fullscreen mode

Build an Image

To build an image from the Dockerfile:

docker build -t my-app . 
Enter fullscreen mode Exit fullscreen mode

6. Docker Volumes

What are Volumes?

Docker volumes allow you to persist data beyond the container's lifecycle.

Basic Volume Commands

  • Create a Volume:
 docker volume create <volume_name> 
Enter fullscreen mode Exit fullscreen mode
  • Use a Volume in a Container:
 docker run -v <volume_name>:/path/in/container <image_name> 
Enter fullscreen mode Exit fullscreen mode
  • List Volumes:
 docker volume ls 
Enter fullscreen mode Exit fullscreen mode

7. Docker Networking

Networking Overview

Docker networks allow containers to communicate with each other and external systems.

Types of Networks

  • Bridge: Default network; containers on the same bridge can communicate.
  • Host: Uses the host’s network stack.
  • None: No network; fully isolated containers.

Common Commands

  • List Networks:
 docker network ls 
Enter fullscreen mode Exit fullscreen mode
  • Create a Network:
 docker network create <network_name> 
Enter fullscreen mode Exit fullscreen mode
  • Connect a Container to a Network:
 docker network connect <network_name> <container_id> 
Enter fullscreen mode Exit fullscreen mode

8. Docker Compose

What is Docker Compose?

Docker Compose simplifies the management of multi-container applications using a YAML file.

Example Compose File

Here’s a docker-compose.yml for a web app and a MySQL database:

version: "3.8" services: web: image: nginx ports: - "8080:80" db: image: mysql environment: MYSQL_ROOT_PASSWORD: example 
Enter fullscreen mode Exit fullscreen mode

Compose Commands

  • Start Services:
 docker-compose up or docker compose up -d 
Enter fullscreen mode Exit fullscreen mode
  • -d to start containers in detatched mode
  • Stop Services:
 docker-compose down or docker-compose down -v 
Enter fullscreen mode Exit fullscreen mode
  • -v means taking down the containers plus its volumes

9. Docker Hub

What is Docker Hub?

Docker Hub is a public repository for sharing container images.

Using Docker Hub

  • Search for Images:
 docker search <image_name> 
Enter fullscreen mode Exit fullscreen mode
  • Push an Image:
 docker push <username>/<image_name> 
Enter fullscreen mode Exit fullscreen mode
  • Pull an Image:
 docker pull <username>/<image_name> 
Enter fullscreen mode Exit fullscreen mode

10. Troubleshooting Docker

Common Issues

  • Container Fails to Start: Check logs using:
 docker logs <container_id> 
Enter fullscreen mode Exit fullscreen mode
  • Image Build Errors: Verify the Dockerfile syntax and paths.
  • Port Conflicts: Ensure no other services are using the same port.

11. Best Practices

  • Use small, efficient base images.
  • Minimize layers in Dockerfiles.
  • Avoid hardcoding sensitive data in images; use environment variables instead.
  • Regularly clean up unused images and containers.

12. Practical Examples: Building and Dockerizing Applications

1. Spring Boot Application

Application Setup:

Step 1: Create the Project

  1. Visit Spring Initializr.
  2. Configure the project:
    • Project: Maven
    • Language: Java
    • Spring Boot Version: 3.4.1
    • Dependencies: Spring Web
  3. Generate the project and unzip it.

Step 2: Project Structure

The generated structure includes:

. ├── Dockerfile ├── HELP.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main │   ├── java │   │   └── com │   │   └── bansikah │   │   └── demoapp │   │   └── DemoAppApplication.java |__ HelloController.java │   └── resources │   ├── application.properties │   ├── static │   └── templates └── test └── java └── com └── bansikah └── demoapp └── DemoAppApplicationTests.java 14 directories, 8 files 
Enter fullscreen mode Exit fullscreen mode
  • DemoAppApplication.java: The main entry point for the Spring Boot
package com.bansikah.demoapp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoAppApplication { public static void main(String[] args) { SpringApplication.run(DemoAppApplication.class, args); } } 
Enter fullscreen mode Exit fullscreen mode

HelloController.java: Our demo controller we will use to test our application.

package com.bansikah.demoapp; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String sayHello() { return "Hello, Docker!"; } } 
Enter fullscreen mode Exit fullscreen mode

Dockerfile:: Dockerize the spring applicaton so that we can run it as a docker container.

# Stage 1: Build FROM maven:3.8.7-eclipse-temurin-17 AS builder WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests # Stage 2: Run FROM openjdk:17-jdk-slim WORKDIR /app COPY --from=builder /app/target/demo-app-0.0.1-SNAPSHOT.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"] 
Enter fullscreen mode Exit fullscreen mode

Commands:

mvn clean install docker build -t springboot-demo-app . docker run -d -p 8080:8080 springboot-demo-app curl http://localhost:8080/hello 
Enter fullscreen mode Exit fullscreen mode

and when you test using curl you should see:

Image description


2. Python Flask Application

Application Setup:

mkdir flask-app && cd flask-app 
Enter fullscreen mode Exit fullscreen mode

Project structure:

flask-app ├── app.py ├── Dockerfile ├── requirements.txt 
Enter fullscreen mode Exit fullscreen mode
    1. Create app.py:
    from flask import Flask app = Flask(__name__) @app.route('/') def home(): return "Hello, Docker!" if __name__ == "__main__": app.run(host="0.0.0.0", port=5000) 

-2 Dockerfile:

# Use a lightweight Python base image FROM python:3.10-slim # Set the working directory in the container WORKDIR /app # Copy the application files COPY app.py /app COPY requirements.txt /app # Install the Python dependencies RUN pip install --no-cache-dir -r requirements.txt # Expose the port the Flask app runs on EXPOSE 5000 # Run the Flask application ENTRYPOINT ["python", "app.py"] 
Enter fullscreen mode Exit fullscreen mode

Commands:

echo "flask" > requirements.txt docker build -t flask-app . docker run -p 5000:5000 flask-app curl http://localhost:5000 
Enter fullscreen mode Exit fullscreen mode

And you should see this :

Image description


3. Node.js Application

Application Setup:

  • 1. Set Up the Project Directory:
mkdir node-app && cd node-app 
Enter fullscreen mode Exit fullscreen mode
  • 2. Initialize a New Node.js Project: Run the following command and follow the prompts:
npm init -y 
Enter fullscreen mode Exit fullscreen mode
  • 3. Install Required Dependencies: For this example, we’ll use the Express framework:
npm install express 
Enter fullscreen mode Exit fullscreen mode
  • 4. Create the Application Code: Create a file named server.js with the following content:
const express = require("express"); const app = express(); const PORT = process.env.PORT || 3000; app.get("/", (req, res) => { res.send("Hello, Dockerized Node.js!"); }); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); 
Enter fullscreen mode Exit fullscreen mode
  • 5. Creating the Dockerfile Create a Dockerfile in the project root with the following content:
# Use Node.js base image FROM node:18 # Set the working directory inside the container WORKDIR /app # Copy package.json and package-lock.json files COPY package*.json ./ # Install dependencies RUN npm install # Copy application files COPY . . # Expose the application port EXPOSE 3000 # Command to run the application CMD ["node", "server.js"] 
Enter fullscreen mode Exit fullscreen mode
  • 6. Building the Docker Image
docker build -t node-app . docker run -d -p 3003:3000 node-app 
Enter fullscreen mode Exit fullscreen mode

We exposed the appliction port to be port 3000 but since i had already another application using that port externally on my computer i had to map the port to an external port 3003

  • 7. Test Application:
curl http://localhost:3003 
Enter fullscreen mode Exit fullscreen mode

You should see:

Node application

Docker compose practical examples

Create a directory and file

mkdir docker-compose & cd docker-compose touch docker-compose.yml 
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml

version: '3.8' services: frontend: image: nginx:alpine container_name: frontend volumes: - ./frontend:/usr/share/nginx/html:ro ports: - "80:80" networks: - webnet backend: image: node:14 container_name: backend environment: - NODE_ENV=production - DB_HOST=db - DB_USER=admin - DB_PASS=secret volumes: - ./backend:/usr/src/app ports: - "3000:3000" depends_on: - db networks: - webnet db: image: postgres:13 container_name: db environment: - POSTGRES_USER=admin - POSTGRES_PASSWORD=secret - POSTGRES_DB=appdb volumes: - db_data:/var/lib/postgresql/data networks: - webnet networks: webnet: driver: bridge volumes: db_data: 
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Frontend Service: Uses the nginx image to serve static files, maps the local frontend directory to /usr/share/nginx/html, and exposes port 80.
  • Backend Service: Runs a Node.js app, connects to the database (db) with environment variables, exposes port 3000, and depends on the database service.
  • Database Service: Uses postgres image, creates appdb with credentials, and stores data in the db_data volume.
  • Networks: All services are connected to the webnet network for communication.

Conclusion:

Docker is a powerful tool for simplifying the process of building, shipping, and running applications in containers. It allows you to create isolated environments, making it easier to manage dependencies and deploy applications across various platforms. As you explore Docker, you'll see how it can streamline development workflows, enhance scalability, and improve the consistency of your applications.

Here you can find the link to all the code that has been used link to code

If you encounter any challenges or have questions while getting started with Docker, feel free to reach out! I am here to help you overcome any obstacles. Don't hesitate to post your queries, and I'll make sure to assist you.

For more information and resources, check out the following links:

Happy containerizing! 🚀

Top comments (0)