🐳 Docker 完全指南
📌 Docker 核心概念
什么是 Docker?
Docker 是一个开源的应用容器引擎,使用 Go 语言开发,基于 Linux 内核的 cgroup、namespace、Union FS 等技术,对应用进程进行封装隔离,属于操作系统层面的虚拟化技术。
核心组件
| 组件 | 说明 | 类比 |
|---|---|---|
| Docker Daemon | Docker 守护进程,负责创建、运行容器 | 工厂的生产线 |
| Docker Client | 客户端,通过 CLI 与 Daemon 交互 | 工厂的控制台 |
| Images | 只读模板,用于创建容器 | 产品的设计图纸 |
| Containers | 运行中的镜像实例 | 根据图纸生产的产品 |
| Registry | 镜像仓库(Docker Hub) | 产品仓库 |
| Dockerfile | 构建镜像的指令文件 | 产品生产说明书 |
🚀 快速开始
1. 安装 Docker
# macOS (使用 Homebrew)
brew install --cask docker
# Ubuntu/Debian
sudo apt update
sudo apt install docker.io docker-compose
# CentOS/RHEL
sudo yum install docker
sudo systemctl start docker
sudo systemctl enable docker
# Windows
# 下载 Docker Desktop: https://www.docker.com/products/docker-desktop
# 验证安装
docker --version
docker-compose --version
docker run hello-world
2. 配置镜像加速(中国用户)
// Docker Desktop: Preferences → Docker Engine
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
],
"experimental": false,
"features": {
"buildkit": true
}
}
// Linux: /etc/docker/daemon.json
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
EOF
sudo systemctl restart docker
🛠️ Docker 基础命令
镜像管理
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:latest
docker pull node:18-alpine
# 查看本地镜像
docker images
docker image ls
# 删除镜像
docker rmi nginx:latest
docker image rm <image_id>
# 清理未使用镜像
docker image prune -a
# 查看镜像详情
docker inspect nginx:latest
# 导出/导入镜像
docker save -o nginx.tar nginx:latest
docker load -i nginx.tar
容器管理
# 运行容器
docker run nginx
docker run -d --name my-nginx -p 8080:80 nginx
docker run -it node:18-alpine sh
# 查看容器
docker ps # 运行中的容器
docker ps -a # 所有容器
docker ps -q # 只显示容器ID
# 停止/启动容器
docker stop my-nginx
docker start my-nginx
docker restart my-nginx
# 进入容器
docker exec -it my-nginx bash
docker exec -it my-nginx sh
# 查看日志
docker logs my-nginx
docker logs -f my-nginx # 实时日志
docker logs --tail 100 my-nginx
# 删除容器
docker rm my-nginx
docker rm -f my-nginx # 强制删除运行中的容器
docker container prune # 清理已停止的容器
# 复制文件
docker cp ./file.txt my-nginx:/app/file.txt
docker cp my-nginx:/app/logs ./logs
# 查看资源使用
docker stats
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
网络管理
# 查看网络
docker network ls
# 创建网络
docker network create my-network
# 连接容器到网络
docker network connect my-network my-nginx
# 断开网络
docker network disconnect my-network my-nginx
# 查看网络详情
docker network inspect bridge
# 清理未使用网络
docker network prune
数据卷管理
# 创建数据卷
docker volume create my-volume
# 查看数据卷
docker volume ls
docker volume inspect my-volume
# 使用数据卷
docker run -v my-volume:/data nginx
docker run --mount source=my-volume,target=/data nginx
# 删除数据卷
docker volume rm my-volume
docker volume prune
📦 Dockerfile 深度指南
基础结构
# Dockerfile 示例
# 1. 基础镜像
FROM node:18-alpine AS builder
# 2. 元数据标签
LABEL maintainer="your-email@example.com"
LABEL version="1.0"
LABEL description="Frontend application"
# 3. 工作目录
WORKDIR /app
# 4. 环境变量
ENV NODE_ENV=production
ENV PORT=3000
# 5. 复制文件
COPY package*.json ./
COPY .npmrc ./
# 6. 安装依赖
RUN npm ci --only=production
# 7. 复制源代码
COPY . .
# 8. 构建应用
RUN npm run build
# 9. 多阶段构建 - 生产阶段
FROM nginx:alpine AS production
# 10. 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
# 11. 暴露端口
EXPOSE 80
# 12. 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# 13. 启动命令
CMD ["nginx", "-g", "daemon off;"]
最佳实践指南
# ✅ 最佳实践 Dockerfile
# 1. 使用官方镜像作为基础
FROM node:18-alpine AS base
# 2. 设置非root用户(安全)
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# 3. 安装系统依赖(最小化)
RUN apk add --no-cache \
curl \
git \
python3 \
make \
g++
# 4. 设置工作目录和权限
WORKDIR /app
RUN chown -R nodejs:nodejs /app
USER nodejs
# 5. 环境变量(构建参数)
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
ENV PATH=/app/node_modules/.bin:$PATH
# 6. 复制包管理文件(利用缓存层)
COPY --chown=nodejs:nodejs package*.json ./
# 7. 根据环境安装依赖
RUN if [ "$NODE_ENV" = "development" ]; \
then npm install; \
else npm ci --only=production; \
fi
# 8. 复制源代码(最后一步,避免缓存失效)
COPY --chown=nodejs:nodejs . .
# 9. 构建应用
RUN npm run build
# 10. 生产阶段
FROM nginx:alpine
# 11. 复制构建产物
COPY --from=base /app/dist /usr/share/nginx/html
# 12. 自定义Nginx配置
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
# 13. 暴露端口
EXPOSE 80
# 14. 健康检查
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1
# 15. 启动命令
CMD ["nginx", "-g", "daemon off;"]
前端项目 Dockerfile 模板
React 项目
# 多阶段构建:开发 → 构建 → 生产
FROM node:18-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
FROM development AS builder
RUN npm run build
FROM nginx:alpine AS production
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Vue 项目
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
RUN apk add --no-cache curl
COPY --from=builder /app/dist /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost/ || exit 1
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
Next.js 项目
# 使用官方 Next.js Docker 镜像
FROM node:18-alpine AS base
# 安装依赖
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
# 重新构建源码
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# 生产镜像
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
构建和优化
# 构建镜像
docker build -t myapp:latest .
docker build -t myapp:v1.0.0 .
# 多阶段构建指定阶段
docker build --target development -t myapp:dev .
# 构建参数
docker build \
--build-arg NODE_ENV=production \
--build-arg API_URL=https://api.example.com \
-t myapp:latest .
# 使用 BuildKit(性能更好)
DOCKER_BUILDKIT=1 docker build -t myapp:latest .
# 查看镜像构建历史
docker history myapp:latest
# 镜像优化技巧
# 1. 使用 .dockerignore 文件
echo "node_modules
npm-debug.log
.git
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
build
dist
coverage" > .dockerignore
# 2. 多阶段构建减少镜像大小
# 3. 使用 Alpine 基础镜像
# 4. 合并 RUN 命令减少层数
# 5. 按顺序复制文件利用缓存
🐙 Docker Compose 完全指南
docker-compose.yml 基础
version: '3.8'
services:
# 前端应用
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
NODE_ENV: development
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
environment:
- NODE_ENV=development
- REACT_APP_API_URL=http://backend:5000
depends_on:
- backend
networks:
- app-network
# 后端 API
backend:
build: ./backend
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- app-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# 数据库
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
# Redis
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- app-network
# Nginx 反向代理
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./ssl:/etc/nginx/ssl
depends_on:
- frontend
- backend
networks:
- app-network
# 监控服务
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/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'
ports:
- "9090:9090"
networks:
- app-network
# 日志收集
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
networks:
- app-network
grafana:
image: grafana/grafana:latest
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3001:3000"
depends_on:
- prometheus
- loki
networks:
- app-network
# 网络配置
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
# 数据卷配置
volumes:
postgres-data:
driver: local
redis-data:
driver: local
prometheus-data:
driver: local
grafana-data:
driver: local
多环境配置
# docker-compose.yml
version: '3.8'
services:
app:
build: .
env_file:
- .env.${ENV:-development}
environment:
NODE_ENV: ${ENV:-development}
ports:
- "${PORT:-3000}:3000"
configs:
- source: app_config
target: /app/config.json
secrets:
- db_password
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
configs:
app_config:
file: ./config/${ENV:-development}.json
secrets:
db_password:
file: ./secrets/db_password.txt
# .env.development
ENV=development
PORT=3000
LOG_LEVEL=debug
# .env.production
ENV=production
PORT=80
LOG_LEVEL=info
Docker Compose 命令
# 启动服务
docker-compose up
docker-compose up -d # 后台运行
docker-compose up --build # 重新构建
# 指定环境文件
docker-compose --env-file .env.production up
# 指定项目名称
docker-compose -p myproject up
# 管理服务
docker-compose ps
docker-compose logs
docker-compose logs -f frontend
docker-compose exec frontend sh
docker-compose stop
docker-compose start
docker-compose restart
# 清理
docker-compose down
docker-compose down -v # 删除数据卷
docker-compose down --rmi all # 删除镜像
# 扩展配置
docker-compose -f docker-compose.yml -f docker-compose.override.yml up
docker-compose -f docker-compose.prod.yml up
# 查看服务状态
docker-compose top
docker-compose config # 查看合并后的配置
🌐 网络配置深度解析
网络模式
# 1. Bridge 模式(默认)
docker run --network bridge nginx
# 2. Host 模式(直接使用宿主机网络)
docker run --network host nginx
# 3. None 模式(无网络)
docker run --network none nginx
# 4. 自定义网络
docker network create --driver bridge my-network
docker run --network my-network nginx
# 5. 容器网络
docker run --network container:existing-container nginx
自定义网络配置
# docker-compose.yml 网络配置
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
gateway: 172.20.0.1
backend:
driver: bridge
internal: true # 内部网络,外部无法访问
monitoring:
driver: overlay # Swarm 集群使用
attachable: true
services:
web:
networks:
- frontend
- backend
dns:
- 8.8.8.8
- 1.1.1.1
api:
networks:
backend:
aliases:
- api.service
- internal-api
database:
networks:
- backend
ports:
- "5432:5432"
extra_hosts:
- "host.docker.internal:host-gateway"
💾 存储与数据持久化
数据卷类型
# 1. 命名卷(推荐)
volumes:
db-data:
driver: local
driver_opts:
type: none
o: bind
device: /path/on/host
# 2. 绑定挂载
services:
app:
volumes:
- ./data:/app/data
- /var/log/app:/app/logs
# 3. 临时文件系统
services:
cache:
volumes:
- type: tmpfs
target: /tmp
tmpfs:
size: 100000000 # 100MB
# 4. 只读挂载
services:
app:
volumes:
- config:/app/config:ro
- ./static:/app/static:ro
备份与恢复
# 备份数据卷
docker run --rm -v db-data:/source -v $(pwd):/backup alpine \
tar czf /backup/db-backup-$(date +%Y%m%d).tar.gz -C /source .
# 恢复数据卷
docker run --rm -v db-data:/target -v $(pwd):/backup alpine \
tar xzf /backup/db-backup.tar.gz -C /target
# 复制数据卷
docker volume create new-db-data
docker run --rm -v db-data:/source -v new-db-data:/target alpine \
cp -a /source/. /target/
🔒 安全最佳实践
1. 容器安全配置
services:
app:
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE # 只添加必要的权限
read_only: true # 只读文件系统
tmpfs:
- /tmp
- /run
user: "1000:1000" # 非root用户
2. 镜像安全扫描
# 使用 Trivy 扫描漏洞
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image myapp:latest
# 使用 Docker Scout
docker scout quickview myapp:latest
docker scout cves myapp:latest
# 使用 Snyk
docker scan myapp:latest
# 构建时扫描
docker build \
--secret id=mysecret,src=./secret.txt \
--no-cache \
-t myapp:secure .
3. 秘密管理
# Docker Swarm Secrets
echo "mysecretpassword" | docker secret create db_password -
# Docker Compose v3.8+ Secrets
# docker-compose.yml
services:
db:
image: postgres
secrets:
- db_password
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt
# 使用外部 Secret 管理
# AWS Secrets Manager
docker run --rm \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
amazon/aws-cli secretsmanager get-secret-value \
--secret-id production/db/password
# HashiCorp Vault
docker run --rm \
-e VAULT_TOKEN \
vault:latest \
vault kv get -field=password secret/db
🚀 生产环境部署
Docker Swarm 集群
# 初始化 Swarm
docker swarm init --advertise-addr <MANAGER-IP>
# 加入工作节点
docker swarm join --token <TOKEN> <MANAGER-IP>:2377
# 部署服务
docker stack deploy -c docker-compose.prod.yml myapp
# 查看服务
docker service ls
docker service ps myapp_web
docker service logs myapp_web
# 伸缩服务
docker service scale myapp_web=5
# 更新服务
docker service update \
--image myapp:2.0.0 \
--update-parallelism 2 \
--update-delay 10s \
myapp_web
# 回滚
docker service update \
--rollback \
myapp_web
# 查看节点
docker node ls
生产环境 Compose 文件
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: myapp:${TAG:-latest}
deploy:
replicas: 3
update_config:
parallelism: 2
delay: 10s
order: start-first
failure_action: rollback
monitor: 30s
rollback_config:
parallelism: 1
delay: 5s
order: stop-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
placement:
constraints:
- node.role == worker
preferences:
- spread: node.labels.zone
resources:
limits:
cpus: '1'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
networks:
- traefik-public
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
- "traefik.http.services.myapp.loadbalancer.server.port=80"
redis:
image: redis:7-alpine
deploy:
replicas: 1
placement:
constraints:
- node.labels.redis == true
volumes:
- redis-data:/data
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
postgres:
image: postgres:15-alpine
deploy:
replicas: 1
placement:
constraints:
- node.labels.database == true
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
traefik:
image: traefik:v3.0
deploy:
placement:
constraints:
- node.role == manager
ports:
- "80:80"
- "443:443"
- "8080:8080" # Dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./letsencrypt:/letsencrypt
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.swarmMode=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=admin@example.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
networks:
traefik-public:
external: true
volumes:
redis-data:
driver: local
postgres-data:
driver: local
📊 监控与日志
监控栈配置
# docker-compose.monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/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'
ports:
- "9090:9090"
networks:
- monitoring
grafana:
image: grafana/grafana:latest
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- monitoring
node-exporter:
image: prom/node-exporter:latest
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
networks:
- monitoring
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
networks:
- monitoring
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
networks:
- monitoring
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log
- /var/lib/docker/containers:/var/lib/docker/containers:ro
command: -config.file=/etc/promtail/config.yml
networks:
- monitoring
volumes:
prometheus-data:
grafana-data:
networks:
monitoring:
driver: bridge
日志配置
# docker-compose.yml 日志配置
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
tag: "{{.Name}}/{{.ID}}"
# 使用 Loki 收集日志
app:
logging:
driver: loki
options:
loki-url: "http://loki:3100/api/prom/push"
loki-external-labels: "job=docker-logs,container_name={{.Name}},image={{.ImageName}}"
# 使用 Fluentd
fluentd:
image: fluent/fluentd:v1.16-debian-1
volumes:
- ./fluentd.conf:/fluentd/etc/fluent.conf
- ./logs:/fluentd/log
ports:
- "24224:24224"
- "24224:24224/udp"
app:
logging:
driver: "fluentd"
options:
fluentd-address: "localhost:24224"
tag: "docker.{{.Name}}"
🔧 开发工作流优化
开发环境配置
# docker-compose.dev.yml
version: '3.8'
services:
frontend:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
- /app/.next # Next.js 缓存
environment:
- WATCHPACK_POLLING=true # 文件监听
- CHOKIDAR_USEPOLLING=true
command: npm run dev
develop:
watch:
- action: rebuild
path: ./package.json
- action: sync
path: ./src
target: /app/src
backend:
build:
context: ./api
dockerfile: Dockerfile.dev
ports:
- "5000:5000"
volumes:
- ./api:/app
- /app/node_modules
environment:
- NODE_ENV=development
command: npm run dev:watch
database:
image: postgres:15-alpine
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app_dev
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
redis:
image: redis:7-alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes
mailhog:
image: mailhog/mailhog:latest
ports:
- "8025:8025" # Web UI
- "1025:1025" # SMTP
# 开发工具
adminer:
image: adminer:latest
ports:
- "8080:8080"
portainer:
image: portainer/portainer-ce:latest
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer-data:/data
volumes:
postgres-data:
portainer-data:
热重载配置
# Dockerfile.dev
FROM node:18-alpine
WORKDIR /app
# 安装依赖
COPY package*.json ./
RUN npm install
# 安装开发工具
RUN npm install -g nodemon
# 复制源代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令(支持热重载)
CMD ["nodemon", "--exec", "npm", "start"]
🧪 测试环境
测试配置
# docker-compose.test.yml
version: '3.8'
services:
test:
build:
context: .
target: test
depends_on:
test-db:
condition: service_healthy
test-redis:
condition: service_healthy
environment:
NODE_ENV: test
DATABASE_URL: postgres://test:test@test-db:5432/test
REDIS_URL: redis://test-redis:6379
command: >
sh -c "
npm run test:e2e &&
npm run test:integration &&
npm run test:coverage
"
volumes:
- ./coverage:/app/coverage
test-db:
image: postgres:15-alpine
environment:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: test
healthcheck:
test: ["CMD-SHELL", "pg_isready -U test"]
interval: 5s
timeout: 5s
retries: 5
test-redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5
test-report:
image: nginx:alpine
volumes:
- ./coverage:/usr/share/nginx/html
ports:
- "8081:80"
🚢 CI/CD 集成
GitHub Actions 示例
# .github/workflows/docker.yml
name: Docker Build and Push
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Run tests
run: docker-compose -f docker-compose.test.yml up --abort-on-container-exit
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v3
- name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Deploy to Production
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_KEY }}
script: |
cd /opt/app
docker-compose pull
docker-compose up -d
docker system prune -f
📚 学习资源
官方文档
书籍推荐
- 《Docker Deep Dive》 - Nigel Poulton
- 《Using Docker》 - Adrian Mouat
- 《Docker in Action》 - Jeff Nickoloff
在线课程
🎯 实战项目
项目结构示例
my-docker-project/
├── docker-compose.yml
├── docker-compose.dev.yml
├── docker-compose.prod.yml
├── docker-compose.test.yml
├── .env.example
├── .dockerignore
├── frontend/
│ ├── Dockerfile
│ ├── Dockerfile.dev
│ └── ...
├── backend/
│ ├── Dockerfile
│ ├── Dockerfile.dev
│ └── ...
├── nginx/
│ ├── nginx.conf
│ └── ssl/
├── prometheus/
│ └── prometheus.yml
├── grafana/
│ └── provisioning/
├── scripts/
│ ├── deploy.sh
│ └── backup.sh
└── README.md
部署脚本
#!/bin/bash
# deploy.sh
set -e # 出错时退出
ENV=${1:-production}
TAG=${2:-latest}
echo "🚀 部署环境: $ENV"
echo "🏷️ 镜像标签: $TAG"
# 拉取最新镜像
docker-compose -f docker-compose.$ENV.yml pull
# 停止旧容器
docker-compose -f docker-compose.$ENV.yml down
# 启动新容器
docker-compose -f docker-compose.$ENV.yml up -d
# 清理未使用的镜像
docker image prune -f
# 健康检查
sleep 10
curl -f http://localhost/health || exit 1
echo "✅ 部署完成!"
🔧 故障排查
常用诊断命令
# 查看容器状态
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"
# 查看容器资源使用
docker stats --no-stream
# 查看容器日志
docker logs --tail 100 -f container_name
# 进入容器调试
docker exec -it container_name bash
# 查看容器进程
docker top container_name
# 查看容器元数据
docker inspect container_name
# 网络诊断
docker network inspect bridge
docker exec container_name ping google.com
docker exec container_name curl -I http://service:port
# 存储诊断
docker system df
docker volume ls
常见问题解决
1. 容器启动失败
# 查看详细错误
docker logs container_name
# 检查端口冲突
netstat -tulpn | grep :80
# 检查卷挂载
docker volume inspect volume_name
ls -la /path/to/mount
2. 内存/CPU 问题
# 限制资源使用
docker run --memory="512m" --cpus="1.5" nginx
# 查看资源使用
docker stats
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
# 设置内存交换
docker run --memory="512m" --memory-swap="1g" nginx
3. 网络问题
# 检查 DNS
docker run --rm alpine nslookup google.com
# 检查网络连接
docker run --rm alpine ping -c 4 google.com
# 查看网络配置
docker network inspect network_name
📈 性能优化
镜像优化
# 使用多阶段构建
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
# 使用 Alpine 基础镜像
FROM node:18-alpine
# 合并 RUN 命令减少层数
RUN apk add --no-cache \
curl \
git \
python3 \
make \
g++ && \
npm ci --only=production && \
apk del curl git python3 make g++
# 使用 .dockerignore
# 排除不必要的文件
构建优化
# 使用 BuildKit
DOCKER_BUILDKIT=1 docker build -t myapp .
# 构建缓存
docker build \
--cache-from myapp:latest \
-t myapp:new .
# 并行构建
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t myapp:multiarch .
🎓 认证与培训
Docker 认证路径
- DCA (Docker Certified Associate) - 基础认证
- DCP (Docker Certified Professional) - 专业认证
- Docker Security Specialist - 安全专家
学习路径
- 初学者:Docker Basics → Docker Compose → Docker Networking
- 中级:Dockerfile 优化 → Docker Security → Docker Registry
- 高级:Docker Swarm → Kubernetes → CI/CD Integration

浙公网安备 33010602011771号