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
-
Windows/MacOS:
- Download and install Docker Desktop.
- Ensure that virtualization is enabled on your machine.
-
Linux:
- Follow the Docker Engine installation guide for your distribution.
- Example for Ubuntu:
sudo apt update sudo apt install -y docker.io sudo systemctl start docker sudo systemctl enable docker
Verify Installation:
Run the following command to check the Docker version:
docker --version
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>
- List Images: View all downloaded images on your system.
docker images
- Remove an Image: Delete unused images to save space.
docker rmi <image_id>
Working with Containers
- Run a Container: Start a container from an image.
docker run -d -p 8080:80 <image_name>
-
-d
: Run in detached mode. -
-p
: Map host ports to container ports.- List Running Containers:
docker ps -a
-
-a
means list all containers - Stop a Container:
docker stop <container_id>
- Remove a Container:
docker rm <container_id>
- Execute Commands Inside a Container:
docker exec -it <container_id> bash
Inspecting and Managing Containers
- Inspect a Container: View detailed information about a container.
docker inspect <container_id>
- View Logs: Access logs for debugging.
docker logs <container_id>
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
, orpython
, depending on your application's requirements. Example:
FROM node:14
- 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
- COPY: This command copies files or directories from your local system into the Docker image. Example:
COPY . /app
.
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
- 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"]
-
ENTRYPOINT: Sets the default executable for the container. Unlike
CMD
,ENTRYPOINT
cannot be overridden by arguments provided at runtime. Example:
ENTRYPOINT ["python", "app.py"]
- 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
- 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
- WORKDIR: Sets the working directory for the container. All subsequent commands will be run in this directory. Example:
WORKDIR /app
- VOLUME: Creates a mount point inside the container, allowing for persistent data storage across container restarts. Example:
VOLUME ["/data"]
- **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
- 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>
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"]
Build an Image
To build an image from the Dockerfile:
docker build -t my-app .
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>
- Use a Volume in a Container:
docker run -v <volume_name>:/path/in/container <image_name>
- List Volumes:
docker volume ls
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
- Create a Network:
docker network create <network_name>
- Connect a Container to a Network:
docker network connect <network_name> <container_id>
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
Compose Commands
- Start Services:
docker-compose up or docker compose up -d
-
-d
to start containers in detatched mode - Stop Services:
docker-compose down or docker-compose down -v
-
-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>
- Push an Image:
docker push <username>/<image_name>
- Pull an Image:
docker pull <username>/<image_name>
10. Troubleshooting Docker
Common Issues
- Container Fails to Start: Check logs using:
docker logs <container_id>
- 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
- Visit Spring Initializr.
- Configure the project:
- Project: Maven
- Language: Java
- Spring Boot Version: 3.4.1
- Dependencies: Spring Web
- 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
-
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);
}
}
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!";
}
}
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"]
Commands:
mvn clean install
docker build -t springboot-demo-app .
docker run -d -p 8080:8080 springboot-demo-app
curl http://localhost:8080/hello
and when you test using curl you should see:
2. Python Flask Application
Application Setup:
mkdir flask-app && cd flask-app
Project structure:
flask-app
├── app.py
├── Dockerfile
├── requirements.txt
-
- 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)
- Create
-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"]
Commands:
echo "flask" > requirements.txt
docker build -t flask-app .
docker run -p 5000:5000 flask-app
curl http://localhost:5000
And you should see this :
3. Node.js Application
Application Setup:
- 1. Set Up the Project Directory:
mkdir node-app && cd node-app
- 2. Initialize a New Node.js Project: Run the following command and follow the prompts:
npm init -y
- 3. Install Required Dependencies: For this example, we’ll use the Express framework:
npm install express
- 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}`);
});
- 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"]
- 6. Building the Docker Image
docker build -t node-app .
docker run -d -p 3003:3000 node-app
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
You should see:
Docker compose practical examples
Create a directory and file
mkdir docker-compose & cd docker-compose
touch docker-compose.yml
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:
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)