1. Docker 环境安装与配置
1.1 在 Ubuntu 系统上安装 Docker
创建安装脚本文件:install_docker.sh
bash
#!/bin/bash
# 更新系统包列表
sudo apt-get update
# 安装必要的依赖包
sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 添加 Docker 稳定版仓库
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 更新包列表(包含 Docker 仓库)
sudo apt-get update
# 安装 Docker Engine
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# 将当前用户添加到 docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER
# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
docker --version
echo "Docker 安装完成!请重新登录以使组权限生效。"
1.2 Docker 基础配置
创建配置文件:docker_daemon.json
json
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"data-root": "/var/lib/docker",
"storage-driver": "overlay2"
}
应用配置:
bash
# 创建 docker 配置目录
sudo mkdir -p /etc/docker
# 复制配置文件
sudo cp docker_daemon.json /etc/docker/daemon.json
# 重启 docker 服务
sudo systemctl daemon-reload
sudo systemctl restart docker
# 验证配置
docker info
2. Docker 基础概念与命令
2.1 Docker 核心组件理解
创建学习文档:docker_concepts.md
markdown
# Docker 核心概念
## 镜像 (Image)
- 只读模板,用于创建容器
- 分层存储结构
- 包含运行应用所需的所有内容
## 容器 (Container)
- 镜像的运行实例
- 具有独立的文件系统、网络和进程空间
- 可写层在只读镜像层之上
## 仓库 (Registry)
- 存储和分发镜像的地方
- Docker Hub 是官方公共仓库
- 可以搭建私有仓库
2.2 基础命令练习
创建练习脚本:basic_commands.sh
bash
#!/bin/bash
# 查看 Docker 版本信息
docker version
# 查看系统信息
docker info
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:latest
# 查看本地镜像
docker images
# 运行容器(前台运行)
docker run -it --name my-nginx nginx:latest
# 运行容器(后台运行)
docker run -d --name my-nginx-background -p 8080:80 nginx:latest
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 停止容器
docker stop my-nginx-background
# 启动已停止的容器
docker start my-nginx-background
# 重启容器
docker restart my-nginx-background
# 进入容器内部
docker exec -it my-nginx-background bash
# 查看容器日志
docker logs my-nginx-background
# 查看容器详细信息
docker inspect my-nginx-background
# 删除容器
docker rm my-nginx-background
# 删除镜像
docker rmi nginx:latest
3. 第一个 Docker 应用:Hello World
3.1 创建简单的 Web 应用
创建应用文件:app.py
python
from flask import Flask
import os
import socket
app = Flask(__name__)
@app.route('/')
def hello():
container_id = socket.gethostname()
return f'''
<!DOCTYPE html>
<html>
<head>
<title>Docker Hello World</title>
<style>
body {{
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white;
}}
.container {{
text-align: center;
background: rgba(255, 255, 255, 0.1);
padding: 40px;
border-radius: 15px;
backdrop-filter: blur(10px);
}}
h1 {{
font-size: 2.5em;
margin-bottom: 20px;
}}
p {{
font-size: 1.2em;
margin: 10px 0;
}}
</style>
</head>
<body>
<div class="container">
<h1>🚀 Docker Hello World!</h1>
<p><strong>容器ID:</strong> {container_id}</p>
<p><strong>环境:</strong> Python Flask in Docker</p>
<p>🎉 恭喜!你的第一个Docker应用运行成功!</p>
</div>
</body>
</html>
'''
@app.route('/health')
def health():
return {'status': 'healthy', 'service': 'hello-world'}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
3.2 创建 Dockerfile
创建 Dockerfile 文件:Dockerfile
dockerfile
# 使用官方 Python 运行时作为基础镜像
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制当前目录内容到容器的 /app 目录
COPY . /app
# 安装依赖
RUN pip install --no-cache-dir flask
# 暴露端口
EXPOSE 5000
# 定义环境变量
ENV NAME World
# 容器启动时运行应用
CMD ["python", "app.py"]
3.3 构建和运行应用
创建构建脚本:build_and_run.sh
bash
#!/bin/bash
# 构建 Docker 镜像
docker build -t hello-world-app .
# 运行容器
docker run -d -p 5000:5000 --name hello-container hello-world-app
# 检查容器状态
docker ps
# 查看日志
docker logs hello-container
echo "应用已启动!访问 http://localhost:5000 查看结果"
4. Docker 容器网络配置
4.1 网络基础操作
创建网络操作脚本:network_demo.sh
bash
#!/bin/bash
# 查看网络列表
docker network ls
# 创建自定义网络
docker network create --driver bridge my-custom-network
# 查看网络详情
docker network inspect my-custom-network
# 在自定义网络中运行容器
docker run -d --name web1 --network my-custom-network nginx:alpine
docker run -d --name web2 --network my-custom-network nginx:alpine
# 测试容器间通信
docker exec web1 ping web2
# 创建另一个网络
docker network create --driver bridge another-network
# 将容器连接到多个网络
docker network connect another-network web1
# 查看容器的网络配置
docker inspect web1 | grep -A 10 "Networks"
# 断开网络连接
docker network disconnect another-network web1
# 清理
docker stop web1 web2
docker rm web1 web2
docker network rm my-custom-network another-network
4.2 多容器应用网络配置
创建多容器应用文件:docker-compose-network.yml
yaml
version: '3.8'
services:
web:
image: nginx:alpine
container_name: nginx-web
ports:
- "8080:80"
networks:
- frontend
depends_on:
- api
api:
image: python:3.9-alpine
container_name: python-api
command: python -m http.server 8000
networks:
- frontend
- backend
working_dir: /app
database:
image: postgres:13-alpine
container_name: postgres-db
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
networks:
- backend
volumes:
- db_data:/var/lib/postgresql/data
networks:
frontend:
driver: bridge
backend:
driver: bridge
volumes:
db_data:
运行多容器应用:
bash
docker-compose -f docker-compose-network.yml up -d
docker network ls
docker-compose -f docker-compose-network.yml down
5. Docker 数据持久化
5.1 数据卷操作
创建数据卷管理脚本:volume_management.sh
bash
#!/bin/bash
# 创建数据卷
docker volume create my-data
# 查看数据卷列表
docker volume ls
# 查看数据卷详情
docker volume inspect my-data
# 使用数据卷运行容器
docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=testdb \
-v my-data:/var/lib/mysql \
mysql:8.0
# 查看数据卷使用情况
docker exec mysql-container df -h
# 创建备份卷
docker volume create backup-data
# 使用临时容器备份数据
docker run --rm \
-v my-data:/source \
-v backup-data:/backup \
alpine tar czf /backup/mysql-backup.tar.gz -C /source .
# 查看备份文件
docker run --rm -v backup-data:/backup alpine ls -lh /backup
# 清理
docker stop mysql-container
docker rm mysql-container
docker volume rm my-data backup-data
5.2 绑定挂载实战
创建绑定挂载示例:bind_mount_demo.sh
bash
#!/bin/bash
# 创建本地目录
mkdir -p /home/$USER/docker-data/website
mkdir -p /home/$USER/docker-data/config
# 创建示例网站文件
cat > /home/$USER/docker-data/website/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Bind Mount Demo</title>
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white;
}
.container {
text-align: center;
background: rgba(255, 255, 255, 0.2);
padding: 40px;
border-radius: 15px;
backdrop-filter: blur(10px);
}
</style>
</head>
<body>
<div class="container">
<h1>🎯 Bind Mount 演示</h1>
<p>这个页面来自宿主机的目录!</p>
<p>实时修改 host 的文件会立即反映在容器中</p>
</div>
</body>
</html>
EOF
# 使用绑定挂载运行 Nginx
docker run -d \
--name nginx-bind-mount \
-p 8081:80 \
-v /home/$USER/docker-data/website:/usr/share/nginx/html \
nginx:alpine
echo "访问 http://localhost:8081 查看绑定挂载的网站"
# 实时修改测试
echo "<p>🚀 实时更新测试成功!</p>" >> /home/$USER/docker-data/website/index.html
# 查看容器中的文件变化
docker exec nginx-bind-mount cat /usr/share/nginx/html/index.html
# 清理
docker stop nginx-bind-mount
docker rm nginx-bind-mount
6. Dockerfile 最佳实践
6.1 优化 Dockerfile
创建优化后的 Dockerfile:optimized.Dockerfile
dockerfile
# 多阶段构建示例
# 阶段1: 构建阶段
FROM python:3.9-slim as builder
WORKDIR /app
# 复制 requirements 文件
COPY requirements.txt .
# 安装构建依赖和 Python 包
RUN apt-get update && apt-get install -y \
gcc \
g++ \
&& pip install --user -r requirements.txt \
&& apt-get remove -y gcc g++ \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/*
# 阶段2: 运行阶段
FROM python:3.9-slim
# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1
WORKDIR /app
# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 从构建阶段复制已安装的包
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appuser . .
# 设置路径和非root用户
ENV PATH=/home/appuser/.local/bin:$PATH
USER appuser
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:5000/health || exit 1
# 暴露端口
EXPOSE 5000
# 启动命令
CMD ["python", "app.py"]
创建 requirements 文件:requirements.txt
txt
Flask==2.3.3
requests==2.31.0
gunicorn==21.2.0
6.2 多阶段构建实战
创建多阶段构建示例:multi-stage.Dockerfile
dockerfile
# 多阶段构建:Go 应用示例
# 阶段1: 构建阶段
FROM golang:1.19-alpine as builder
WORKDIR /app
# 下载依赖
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# 阶段2: 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# 从构建阶段复制二进制文件
COPY --from=builder /app/main .
# 创建非root用户
RUN adduser -D -g '' appuser
USER appuser
# 暴露端口
EXPOSE 8080
# 启动应用
CMD ["./main"]
创建 Go 应用示例:main.go
go
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
hostname, _ := os.Hostname()
fmt.Fprintf(w, `
<!DOCTYPE html>
<html>
<head>
<title>Go Docker App</title>
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: white;
}
.container {
text-align: center;
background: rgba(255, 255, 255, 0.1);
padding: 40px;
border-radius: 15px;
backdrop-filter: blur(10px);
}
</style>
</head>
<body>
<div class="container">
<h1>🐹 Go + Docker</h1>
<p><strong>容器ID:</strong> %s</p>
<p>多阶段构建成功!</p>
</div>
</body>
</html>
`, hostname)
})
log.Println("Server starting on :8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
创建 Go 模块文件:go.mod
go
module docker-go-app
go 1.19
7. Docker Compose 实战
7.1 完整的 Web 应用栈
创建 Docker Compose 文件:docker-compose-fullstack.yml
yaml
version: '3.8'
services:
# 前端服务
frontend:
build:
context: .
dockerfile: frontend.Dockerfile
container_name: vue-frontend
ports:
- "3000:80"
networks:
- app-network
depends_on:
- backend
environment:
- API_URL=http://backend:8000
restart: unless-stopped
# 后端 API 服务
backend:
build:
context: .
dockerfile: backend.Dockerfile
container_name: flask-backend
ports:
- "8000:8000"
networks:
- app-network
depends_on:
- database
environment:
- DATABASE_URL=postgresql://user:password@database:5432/myapp
- REDIS_URL=redis://redis:6379
volumes:
- backend-logs:/app/logs
restart: unless-stopped
# 数据库服务
database:
image: postgres:13-alpine
container_name: postgres-db
networks:
- app-network
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
restart: unless-stopped
# Redis 缓存服务
redis:
image: redis:6.2-alpine
container_name: redis-cache
networks:
- app-network
command: redis-server --appendonly yes
volumes:
- redis-data:/data
restart: unless-stopped
# Nginx 反向代理
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
networks:
- app-network
depends_on:
- frontend
- backend
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
restart: unless-stopped
# 监控服务
monitor:
image: portainer/portainer-ce:latest
container_name: portainer
ports:
- "9000:9000"
networks:
- app-network
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer-data:/data
restart: unless-stopped
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
postgres-data:
driver: local
redis-data:
driver: local
backend-logs:
driver: local
portainer-data:
driver: local
7.2 创建相关配置文件
创建 Nginx 配置:nginx.conf
nginx
events {
worker_connections 1024;
}
http {
upstream backend {
server backend:8000;
}
upstream frontend {
server frontend:80;
}
server {
listen 80;
server_name localhost;
# 前端静态文件
location / {
proxy_pass http://frontend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 后端 API 代理
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# CORS 头
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
}
# 健康检查端点
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
创建数据库初始化脚本:init.sql
sql
-- 创建示例表
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入示例数据
INSERT INTO users (username, email) VALUES
('admin', 'admin@example.com'),
('user1', 'user1@example.com')
ON CONFLICT (username) DO NOTHING;
INSERT INTO products (name, price, description) VALUES
('Docker Book', 39.99, 'Learn Docker from scratch'),
('Kubernetes Guide', 49.99, 'Master container orchestration')
ON CONFLICT (id) DO NOTHING;
8. Docker 安全实践
8.1 安全扫描与最佳实践
创建安全扫描脚本:security_scan.sh
bash
#!/bin/bash
# 安装 Docker 安全扫描工具
sudo apt-get update
sudo apt-get install -y trivy
# 扫描本地镜像
echo "扫描 nginx 镜像的安全漏洞..."
trivy image nginx:latest
# 使用非 root 用户运行容器
docker run -d \
--name security-demo \
--user 1000:1000 \
-p 8082:80 \
nginx:alpine
# 检查容器运行用户
docker exec security-demo whoami
# 只读文件系统示例
docker run -d \
--name read-only-demo \
--read-only \
--tmpfs /tmp \
-p 8083:80 \
nginx:alpine
# 安全选项示例
docker run -d \
--name secure-container \
--security-opt=no-new-privileges:true \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
-p 8084:80 \
nginx:alpine
# 检查容器安全性
docker inspect secure-container | grep -A 5 SecurityOpt
echo "安全演示完成!"
8.2 创建安全加固的 Dockerfile
创建安全加固的 Dockerfile:secure.Dockerfile
dockerfile
# 使用特定版本的基础镜像
FROM nginx:1.23-alpine
# 设置用户和组
RUN addgroup -g 1000 -S www-group && \
adduser -S -D -H -u 1000 -h /var/cache/nginx -s /sbin/nologin -G www-group -g www-user www-user
# 移除不必要的文件
RUN rm -rf /etc/nginx/conf.d/* && \
rm -rf /usr/share/nginx/html/*
# 复制自定义配置
COPY nginx-secure.conf /etc/nginx/nginx.conf
COPY html/ /usr/share/nginx/html/
# 设置正确的权限
RUN chown -R www-user:www-group /var/cache/nginx && \
chown -R www-user:www-group /var/log/nginx && \
chown -R www-user:www-group /etc/nginx/nginx.conf && \
chmod -R 755 /usr/share/nginx/html && \
chmod 644 /etc/nginx/nginx.conf
# 切换到非root用户
USER www-user
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:80/ || exit 1
# 暴露端口
EXPOSE 80
# 启动命令
CMD ["nginx", "-g", "daemon off;"]
创建安全 Nginx 配置:nginx-secure.conf
nginx
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 安全头
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# 隐藏服务器版本
server_tokens off;
# 限制请求大小
client_max_body_size 1m;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
server_name _;
# 根目录配置
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# 安全限制
limit_except GET {
deny all;
}
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 健康检查
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
9. Docker 监控与日志管理
9.1 容器监控实战
创建监控脚本:monitoring_setup.sh
bash
#!/bin/bash
# 使用 Docker Stats 监控
echo "实时容器资源使用情况:"
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
# 设置容器资源限制
docker run -d \
--name limited-container \
--memory=512m \
--cpus=1.0 \
--memory-reservation=256m \
--blkio-weight=500 \
nginx:alpine
# 检查资源限制
docker inspect limited-container | grep -A 10 "HostConfig"
# 安装 cAdvisor 进行详细监控
docker run -d \
--name=cadvisor \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--privileged \
--device=/dev/kmsg \
gcr.io/cadvisor/cadvisor:v0.47.0
echo "cAdvisor 监控面板: http://localhost:8080"
# 日志管理示例
docker run -d \
--name logging-demo \
--log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
-p 8085:80 \
nginx:alpine
# 查看日志
docker logs logging-demo
# 日志导出
docker logs logging-demo > nginx.log
# 清理
docker stop cadvisor limited-container logging-demo
docker rm cadvisor limited-container logging-demo
9.2 使用 Prometheus 和 Grafana
创建监控栈配置:docker-compose-monitoring.yml
yaml
version: '3.8'
services:
# Node Exporter - 系统指标收集
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
command:
- '--path.rootfs=/host'
network_mode: host
pid: host
restart: unless-stopped
volumes:
- '/:/host:ro,rslave'
user: root
# cAdvisor - 容器指标收集
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
devices:
- /dev/kmsg
network_mode: host
restart: unless-stopped
privileged: true
# Prometheus - 指标存储和查询
prometheus:
image: prom/prometheus:latest
container_name: prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
ports:
- "9090:9090"
networks:
- monitoring
# Grafana - 数据可视化
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3000:3000"
networks:
- monitoring
depends_on:
- prometheus
# Alertmanager - 告警管理
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
restart: unless-stopped
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- alertmanager-data:/alertmanager
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
- '--web.external-url=http://localhost:9093'
ports:
- "9093:9093"
networks:
- monitoring
networks:
monitoring:
driver: bridge
volumes:
prometheus-data:
driver: local
grafana-data:
driver: local
alertmanager-data:
driver: local
创建 Prometheus 配置:prometheus.yml
yaml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'docker-containers'
static_configs:
- targets: ['localhost:9323']
10. 生产环境部署实战
10.1 完整的生产级配置
创建生产环境部署脚本:production_deploy.sh
bash
#!/bin/bash
set -e
# 环境变量配置
export COMPOSE_PROJECT_NAME="myapp"
export DEPLOY_ENV="production"
export DOCKER_REGISTRY="registry.mycompany.com"
export APP_VERSION="1.0.0"
# 创建必要的目录
mkdir -p {logs,data,config,backups}
# 拉取最新镜像
docker-compose -f docker-compose-prod.yml pull
# 停止现有服务
docker-compose -f docker-compose-prod.yml down
# 备份数据库
docker run --rm \
-v ${COMPOSE_PROJECT_NAME}_db_data:/source \
-v $(pwd)/backups:/backup \
alpine tar czf /backup/db-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /source .
# 启动服务
docker-compose -f docker-compose-prod.yml up -d
# 健康检查
echo "进行健康检查..."
sleep 30
# 检查所有服务状态
docker-compose -f docker-compose-prod.yml ps
# 检查服务健康状态
for service in $(docker-compose -f docker-compose-prod.yml ps --services); do
container_id=$(docker-compose -f docker-compose-prod.yml ps -q $service)
health_status=$(docker inspect --format='{{.State.Health.Status}}' $container_id 2>/dev/null || echo "no health check")
echo "服务 $service: $health_status"
done
# 日志检查
docker-compose -f docker-compose-prod.yml logs --tail=50
echo "部署完成!"
创建生产环境 Docker Compose:docker-compose-prod.yml
yaml
version: '3.8'
x-common-variables: &common-vars
DEPLOY_ENV: production
LOG_LEVEL: info
TZ: Asia/Shanghai
services:
# 应用服务
app:
image: ${DOCKER_REGISTRY}/myapp:${APP_VERSION}
container_name: ${COMPOSE_PROJECT_NAME}-app
restart: unless-stopped
environment:
<<: *common-vars
DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@database:5432/${DB_NAME}
REDIS_URL: redis://redis:6379
depends_on:
database:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
- backend
- frontend
# 数据库
database:
image: postgres:13-alpine
container_name: ${COMPOSE_PROJECT_NAME}-database
restart: unless-stopped
environment:
<<: *common-vars
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
- ./config/postgres.conf:/etc/postgresql/postgresql.conf
command: postgres -c config_file=/etc/postgresql/postgresql.conf
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 40s
networks:
- backend
# Redis
redis:
image: redis:6.2-alpine
container_name: ${COMPOSE_PROJECT_NAME}-redis
restart: unless-stopped
command: redis-server /usr/local/etc/redis/redis.conf
volumes:
- redis_data:/data
- ./config/redis.conf:/usr/local/etc/redis/redis.conf
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 5
networks:
- backend
# Nginx
nginx:
image: nginx:1.23-alpine
container_name: ${COMPOSE_PROJECT_NAME}-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
- ./logs/nginx:/var/log/nginx
depends_on:
- app
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
networks:
- frontend
networks:
frontend:
driver: bridge
driver_opts:
com.docker.network.driver.mtu: 1500
backend:
driver: bridge
internal: false
volumes:
db_data:
driver: local
driver_opts:
type: none
o: bind
device: ${PWD}/data/db
redis_data:
driver: local
driver_opts:
type: none
o: bind
device: ${PWD}/data/redis
创建环境配置文件:.env.production
bash
# 应用配置
COMPOSE_PROJECT_NAME=myapp-production
APP_VERSION=1.0.0
DOCKER_REGISTRY=registry.mycompany.com
# 数据库配置
DB_NAME=myapp
DB_USER=app_user
DB_PASSWORD=secure_password_123
# 网络配置
DOMAIN=myapp.com
SSL_EMAIL=admin@myapp.com
# 资源限制
APP_MEMORY_LIMIT=1g
DB_MEMORY_LIMIT=2g
REDIS_MEMORY_LIMIT=512m
Docker 学习流程图
总结
通过这10个详细的实战案例,您已经全面掌握了 Docker 的核心概念和实际应用技能。从基础的环境安装到生产级部署,每个案例都提供了完整的代码和配置,确保您可以立即在实践中应用这些知识。
关键学习要点:
- Docker 基础命令和概念理解
- 容器网络和数据管理
- Dockerfile 最佳实践和多阶段构建
- Docker Compose 编排复杂应用
- 容器安全加固和监控
- 生产环境部署策略