Docker is a containerization platform that allows you to package applications and their dependencies into lightweight, portable containers. These containers ensure that applications run consistently across various environments, from development to production.
Think of Docker containers as shipping containers. Just as shipping containers standardize the transportation of goods across ships, trains, and trucks, Docker containers standardize the deployment of applications across different environments. This ensures that what works in development will work in production without discrepancies.
The Docker Engine acts as the kitchen where containers are "cooked" and managed. It handles building, running, and managing Docker containers. The Registry, like Docker Hub, is a cookbook library where you can store and retrieve container images, facilitating easy sharing and deployment.
Mastering basic Docker commands is crucial for effective container management. Below are essential commands with practical examples:
docker pull nginx
Downloads the Nginx image from Docker Hub to your local machine.
docker run -d -p 8080:80 nginx
Starts an Nginx container in detached mode, mapping port 8080 on the host to port 80 in the container.
docker ps
Displays all currently running Docker containers.
docker stop <container_id>
Stops a running container identified by its container ID.
docker rm <container_id>
Deletes a stopped container from your system.
docker build -t my-app .
Builds a Docker image named "my-app" using the Dockerfile in the current directory.
Command | Description | Example |
---|---|---|
docker pull <image_name> | Download an image from Docker Hub | docker pull ubuntu |
docker run [OPTIONS] <image_name> | Run a container from an image | docker run -d -p 3000:3000 my-app |
docker ps | List running containers | docker ps |
docker stop <container_id> | Stop a running container | docker stop abc123 |
docker rm <container_id> | Remove a stopped container | docker rm abc123 |
docker images | List downloaded images | docker images |
docker rmi <image_name> | Remove an image | docker rmi nginx |
A Dockerfile is a script containing a series of instructions on how to build a Docker image. It defines the environment and steps needed to set up your application within a container.
alpine
or slim
to reduce image size and improve security.
FROM python:3.9-slim
RUN
commands to reduce the number of layers, which decreases image size and build time.
RUN apt-get update && apt-get install -y \
curl \
git
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
RUN useradd -m myuser
USER myuser
FROM node:14 AS build
WORKDIR /app
COPY . .
RUN npm install && npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
# .dockerignore
node_modules
.git
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
This Dockerfile sets up a Node.js application by using a lightweight Node.js base image, installing dependencies, copying application code, exposing the necessary port, and defining the default command.
docker logs <container_id>
docker run -d -p 8081:80 nginx
docker system prune -a
docker run -d --memory="512m" --cpus="1" nginx
docker network inspect
to troubleshoot network settings.FROM node:14 AS build
WORKDIR /app
COPY . .
RUN npm install && npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
docker run -d --memory="512m" --cpus="1" nginx
RUN useradd -m myuser
USER myuser
docker scan
to detect and address security issues.
docker scan my-app
Follow these steps to containerize a simple Node.js application:
mkdir my-node-app
cd my-node-app
npm init -y
npm install express
app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('Hello Docker!'));
app.listen(3000, () => console.log('App running on port 3000'));
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
docker build -t my-node-app .
docker run -d -p 3000:3000 my-node-app
Access the application by navigating to http://localhost:3000 in your browser.
Create a file named app.py
with the following content:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello from Python!"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
requirements.txt
Flask==2.0.1
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
docker build -t my-python-app .
docker run -d -p 5000:5000 my-python-app
Access the application by navigating to http://localhost:5000 in your browser.
docker run -d --name my-postgres -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 postgres
This command starts a PostgreSQL container named "my-postgres" with the specified password, exposing it on port 5432.
docker run -d --name my-postgres -e POSTGRES_PASSWORD=mysecretpassword -v my-pgdata:/var/lib/postgresql/data -p 5432:5432 postgres
This ensures that your database data persists even if the container is removed.
Docker Compose is a tool that allows you to define and manage multi-container Docker applications using a YAML file. It simplifies the orchestration of multiple containers, making it easier to set up complex environments.
docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
In this example, a web application and a PostgreSQL database are defined as separate services. The web service depends on the db service and mounts a volume for data persistence.
docker-compose up -d
Builds, creates, starts, and attaches to containers for a service in detached mode.
docker-compose down
Stops and removes containers, networks, and volumes created by docker-compose up
.
docker-compose logs -f
Follows the logs of all services.
docker-compose up --scale web=3
Runs multiple instances of a service (e.g., 3 instances of the web service).
Create a docker-compose.yml
with the content provided above.
docker-compose up -d
This command will build the web service, pull the PostgreSQL image, and start both containers.
docker-compose ps
Ensure that both the web and db services are running.
Navigate to http://localhost:3000 to interact with the web service.
docker-compose down
docker run -v $(pwd):/app -p 3000:3000 my-node-app
Integrating Docker into CI/CD pipelines automates the building, testing, and deployment of applications. Below is an example using GitHub Actions:
name: Docker Build and Push
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: my-dockerhub-username/my-app:latest
This workflow automates the process of building a Docker image and pushing it to Docker Hub whenever changes are pushed to the main branch.
mkdir docker-node-app
cd docker-node-app
npm init -y
npm install express
app.js
file with a simple Express server:
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('Hello Docker!'));
app.listen(3000, () => console.log('App running on port 3000'));
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
docker build -t my-node-app .
docker run -d -p 3000:3000 my-node-app
docker-compose.yml
file with web and database services:
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
docker-compose up -d
docker-compose ps
docker-compose down
FROM python:3.9-slim AS build
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.9-slim
WORKDIR /app
COPY --from=build /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
docker build -t optimized-python-app .
docker run -d -p 5000:5000 optimized-python-app
docker scan
.docker scan my-node-app
DOCKER_USERNAME
and DOCKER_PASSWORD
.docker logs
and logging drivers effectively.By following this comprehensive Docker crash course, you have gained a solid foundation in containerization. You have learned core concepts, essential commands, best practices for writing Dockerfiles, troubleshooting techniques, performance and security tips, real-world application examples, and integration with development workflows and CI/CD pipelines. Engaging with hands-on exercises has reinforced your understanding and equipped you with practical skills to effectively manage Docker containers in various environments.