本文将系统讲解Docker容器化技术,包括镜像构建、容器编排、网络配置、数据持久化等,帮助你掌握现代应用部署的核心技能。
📋 目录
- 一、Docker核心概念
- 二、镜像构建与优化
- 三、容器管理与网络
- [四、Docker Compose编排](#四、Docker Compose编排)
- 五、数据持久化
- 六、生产环境最佳实践
一、Docker核心概念
1.1 Docker架构
┌─────────────────────────────────────────┐
│ Docker Client │
│ (docker build/run/pull) │
└─────────────────┬───────────────────────┘
│ REST API
┌─────────────────▼───────────────────────┐
│ Docker Daemon │
│ (dockerd) │
├─────────────┬───────────┬───────────────┤
│ Images │ Containers│ Networks │
├─────────────┼───────────┼───────────────┤
│ Volumes │ Plugins │ ... │
└─────────────┴───────────┴───────────────┘
│
┌─────────────────▼───────────────────────┐
│ Docker Registry │
│ (Docker Hub / 私有仓库) │
└─────────────────────────────────────────┘
1.2 核心概念对比
| 概念 | 说明 | 类比 |
|---|---|---|
| 镜像(Image) | 只读模板,包含运行环境 | 类的定义 |
| 容器(Container) | 镜像的运行实例 | 类的实例 |
| 仓库(Registry) | 存储和分发镜像 | 应用商店 |
| Dockerfile | 构建镜像的脚本 | 安装说明书 |
| Volume | 数据持久化存储 | 外接硬盘 |
1.3 常用命令速查
bash
# 镜像操作
docker images # 列出镜像
docker pull nginx:latest # 拉取镜像
docker build -t myapp:v1 . # 构建镜像
docker rmi image_id # 删除镜像
docker tag myapp:v1 myapp:latest # 打标签
docker push myrepo/myapp:v1 # 推送镜像
# 容器操作
docker ps # 运行中的容器
docker ps -a # 所有容器
docker run -d --name web nginx # 后台运行
docker start/stop/restart web # 启停容器
docker rm container_id # 删除容器
docker logs -f web # 查看日志
docker exec -it web bash # 进入容器
# 系统操作
docker system df # 磁盘使用
docker system prune # 清理无用资源
docker stats # 资源监控
二、镜像构建与优化
2.1 Dockerfile基础
dockerfile
# 基础镜像
FROM node:18-alpine
# 元数据
LABEL maintainer="dev@example.com"
LABEL version="1.0"
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制源码
COPY . .
# 构建应用
RUN npm run build
# 暴露端口
EXPOSE 3000
# 环境变量
ENV NODE_ENV=production
# 启动命令
CMD ["node", "dist/server.js"]
2.2 多阶段构建
❌ 错误示例:单阶段构建
dockerfile
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/server.js"]
# 问题:镜像包含开发依赖,体积大
✅ 正确示例:多阶段构建
dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 生产阶段
FROM node:18-alpine AS production
WORKDIR /app
# 只复制生产依赖
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# 从构建阶段复制产物
COPY --from=builder /app/dist ./dist
# 使用非root用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
EXPOSE 3000
CMD ["node", "dist/server.js"]
2.3 前端项目Dockerfile
dockerfile
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 生产阶段 - 使用Nginx
FROM nginx:alpine
# 复制自定义配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
nginx
# nginx.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# SPA路由支持
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API代理
location /api {
proxy_pass http://backend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
2.4 镜像优化技巧
dockerfile
# 1. 使用Alpine基础镜像
FROM node:18-alpine # ~170MB vs node:18 ~900MB
# 2. 合并RUN命令减少层数
RUN apk add --no-cache \
git \
curl \
&& rm -rf /var/cache/apk/*
# 3. 利用构建缓存 - 先复制依赖文件
COPY package*.json ./
RUN npm ci
COPY . . # 源码变化不影响依赖缓存
# 4. 使用.dockerignore
# .dockerignore
node_modules
.git
*.md
.env*
dist
coverage
# 5. 清理不必要文件
RUN npm ci --only=production \
&& npm cache clean --force \
&& rm -rf /tmp/*
三、容器管理与网络
3.1 容器运行参数
bash
docker run \
-d \ # 后台运行
--name myapp \ # 容器名称
--restart=unless-stopped \ # 重启策略
-p 8080:3000 \ # 端口映射
-v /data:/app/data \ # 数据卷挂载
-e NODE_ENV=production \ # 环境变量
--env-file .env \ # 环境变量文件
-m 512m \ # 内存限制
--cpus=1 \ # CPU限制
--network mynet \ # 指定网络
--health-cmd="curl -f http://localhost:3000/health" \
--health-interval=30s \ # 健康检查
myapp:latest
3.2 网络模式
bash
# 查看网络
docker network ls
# 创建网络
docker network create mynet
docker network create --driver bridge --subnet 172.20.0.0/16 mynet
# 网络模式对比
# bridge: 默认模式,容器间通过网桥通信
# host: 共享主机网络,性能最好
# none: 无网络
# overlay: 跨主机通信(Swarm)
# 容器加入网络
docker network connect mynet container_name
docker network disconnect mynet container_name
# 容器间通信
docker run -d --name db --network mynet mysql
docker run -d --name app --network mynet myapp
# app容器可以通过 db:3306 访问数据库
3.3 容器资源限制
bash
# 内存限制
docker run -m 512m --memory-swap 1g myapp
# CPU限制
docker run --cpus=2 myapp # 最多使用2个CPU
docker run --cpu-shares=512 myapp # CPU权重
# 查看资源使用
docker stats
# 输出示例
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O
myapp 0.50% 128MiB / 512MiB 25% 1.2kB / 0B
四、Docker Compose编排
4.1 基础配置
yaml
# docker-compose.yml
version: '3.8'
services:
# 前端服务
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "80:80"
depends_on:
- backend
networks:
- app-network
# 后端服务
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- app-network
restart: unless-stopped
# 数据库
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
# Redis缓存
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql_data:
redis_data:
4.2 Compose命令
bash
# 启动服务
docker-compose up -d
# 查看状态
docker-compose ps
# 查看日志
docker-compose logs -f backend
# 停止服务
docker-compose stop
# 停止并删除
docker-compose down
# 删除并清理数据卷
docker-compose down -v
# 重新构建
docker-compose build --no-cache
docker-compose up -d --build
# 扩展服务实例
docker-compose up -d --scale backend=3
# 执行命令
docker-compose exec backend sh
4.3 多环境配置
yaml
# docker-compose.yml (基础配置)
version: '3.8'
services:
backend:
build: ./backend
environment:
- NODE_ENV=${NODE_ENV:-development}
# docker-compose.override.yml (开发环境,自动加载)
version: '3.8'
services:
backend:
volumes:
- ./backend:/app
- /app/node_modules
ports:
- "3000:3000"
- "9229:9229" # 调试端口
command: npm run dev
# docker-compose.prod.yml (生产环境)
version: '3.8'
services:
backend:
restart: always
deploy:
resources:
limits:
cpus: '2'
memory: 1G
bash
# 开发环境(自动使用override)
docker-compose up
# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
五、数据持久化
5.1 Volume类型
bash
# 1. 命名卷(推荐)
docker volume create mydata
docker run -v mydata:/app/data myapp
# 2. 绑定挂载
docker run -v /host/path:/container/path myapp
docker run -v $(pwd)/data:/app/data myapp
# 3. tmpfs挂载(内存)
docker run --tmpfs /app/temp myapp
# 卷管理
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune # 清理未使用的卷
5.2 数据备份与恢复
bash
# 备份数据卷
docker run --rm \
-v mydata:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/mydata_backup.tar.gz -C /source .
# 恢复数据卷
docker run --rm \
-v mydata:/target \
-v $(pwd):/backup \
alpine tar xzf /backup/mydata_backup.tar.gz -C /target
# 数据库备份
docker exec mysql mysqldump -u root -p database > backup.sql
# 数据库恢复
docker exec -i mysql mysql -u root -p database < backup.sql
5.3 数据卷最佳实践
yaml
# docker-compose.yml
version: '3.8'
services:
db:
image: postgres:15
volumes:
# 数据持久化
- postgres_data:/var/lib/postgresql/data
# 初始化脚本(只读)
- ./init:/docker-entrypoint-initdb.d:ro
# 配置文件
- ./postgresql.conf:/etc/postgresql/postgresql.conf:ro
app:
build: .
volumes:
# 上传文件持久化
- uploads:/app/uploads
# 日志持久化
- logs:/app/logs
# 开发时挂载源码
- ./src:/app/src:delegated
volumes:
postgres_data:
driver: local
uploads:
logs:
六、生产环境最佳实践
6.1 安全配置
dockerfile
# 1. 使用非root用户
FROM node:18-alpine
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
USER appuser
# 2. 只读文件系统
docker run --read-only --tmpfs /tmp myapp
# 3. 限制capabilities
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapp
# 4. 安全扫描
docker scan myapp:latest
trivy image myapp:latest
6.2 健康检查
dockerfile
# Dockerfile中配置
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
yaml
# docker-compose.yml
services:
backend:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
6.3 日志管理
yaml
# docker-compose.yml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels: "production_status"
env: "os,customer"
bash
# 查看日志
docker logs --tail 100 -f container_name
# 日志驱动选项
# json-file: 默认,JSON格式
# syslog: 系统日志
# fluentd: Fluentd收集
# awslogs: AWS CloudWatch
# gelf: Graylog
6.4 CI/CD集成
yaml
# .github/workflows/docker.yml
name: Docker Build and Push
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
myrepo/myapp:latest
myrepo/myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /app
docker-compose pull
docker-compose up -d
6.5 监控与告警
yaml
# docker-compose.monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
grafana:
image: grafana/grafana
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
cadvisor:
image: gcr.io/cadvisor/cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
volumes:
prometheus_data:
grafana_data:
📊 Docker命令速查表
| 类别 | 命令 | 说明 |
|---|---|---|
| 镜像 | docker build/pull/push | 构建/拉取/推送 |
| 容器 | docker run/start/stop | 运行/启停 |
| 日志 | docker logs -f | 实时日志 |
| 进入 | docker exec -it bash | 进入容器 |
| 网络 | docker network create | 创建网络 |
| 数据 | docker volume create | 创建数据卷 |
| 清理 | docker system prune | 清理资源 |
| 编排 | docker-compose up -d | 启动服务 |
💡 总结
Docker容器化核心要点:
- ✅ 多阶段构建:减小镜像体积
- ✅ 合理分层:利用构建缓存
- ✅ 网络隔离:使用自定义网络
- ✅ 数据持久化:使用命名卷
- ✅ 安全加固:非root用户、资源限制
- ✅ 健康检查:保证服务可用性
掌握Docker,让应用部署更加简单高效!
💬 如果这篇文章对你有帮助,欢迎点赞收藏!有问题欢迎在评论区讨论~