Docker容器化完全指南:从入门到生产实践
本文详细介绍Docker的核心概念、常用命令、镜像构建、容器编排以及在生产环境中的最佳实践。
Docker已经成为现代软件开发和部署的标准工具。通过容器化,我们可以创建一致的开发环境、简化部署流程、提高资源利用率。本文将从Docker的基础概念开始,逐步深入到生产环境的最佳实践,帮助你全面掌握Docker技术。
Docker核心概念#
1. 镜像(Image)#
Docker镜像是创建容器的基础,是一个只读的模板:
1
2
3
4
5
6
7
8
9
| # 拉取官方镜像
docker pull nginx:latest
docker pull node:18-alpine
# 查看本地镜像
docker images
# 删除镜像
docker rmi nginx:latest
|
2. 容器(Container)#
容器是镜像的运行实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 运行容器
docker run -d --name my-nginx -p 8080:80 nginx
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 停止容器
docker stop my-nginx
# 启动容器
docker start my-nginx
# 删除容器
docker rm my-nginx
|
3. 仓库(Repository)#
Docker仓库是存储和分发镜像的地方:
1
2
3
4
5
6
7
8
| # 登录Docker Hub
docker login
# 推送镜像
docker push username/my-app:1.0
# 拉取私有镜像
docker pull private-registry/my-app:latest
|
Dockerfile最佳实践#
基础镜像选择#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # ✅ 使用官方基础镜像
FROM node:18-alpine
# ✅ 使用多阶段构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
FROM node:18-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
|
优化Dockerfile#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| # ❌ 不好的实践
FROM node:18
# 多个RUN指令创建多个层
RUN apt-get update
RUN apt-get install -y python
RUN npm install
# 使用COPY . . 导致缓存失效
COPY . .
RUN npm install
# ✅ 好的实践
FROM node:18-alpine
# 合并RUN指令,减少层数
RUN apk add --no-cache python3 make g++ && \
npm install -g nodemon && \
npm cache clean --force
# 优化COPY顺序,先复制依赖文件
COPY package*.json ./
RUN npm ci --only=production
# 最后复制源代码
COPY . .
# 非root用户运行
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
EXPOSE 3000
CMD ["npm", "start"]
|
多阶段构建示例#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
# 安装依赖
COPY package*.json ./
RUN npm ci
# 构建应用
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine AS production
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制nginx配置
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
|
Docker Compose#
基础配置#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| # docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=database
- REDIS_HOST=redis
depends_on:
- database
- redis
volumes:
- ./logs:/app/logs
restart: unless-stopped
database:
image: postgres:15-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
postgres_data:
redis_data:
|
开发环境配置#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # docker-compose.dev.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
- "9229:9229" # Debug端口
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
volumes:
- .:/app
- /app/node_modules
command: npm run dev
|
生产环境配置#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| # docker-compose.prod.yml
version: '3.8'
services:
app:
image: myapp:latest
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
environment:
- NODE_ENV=production
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- app
|
常用Docker命令#
镜像管理#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 构建镜像
docker build -t myapp:1.0 .
docker build -t myapp:latest -f Dockerfile.prod .
# 查看镜像历史
docker history myapp:1.0
# 导出镜像
docker save -o myapp.tar myapp:1.0
# 导入镜像
docker load -i myapp.tar
# 标记镜像
docker tag myapp:1.0 username/myapp:1.0
|
容器管理#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # 运行容器
docker run -d \
--name myapp \
-p 3000:3000 \
-e NODE_ENV=production \
-v /app/logs:/app/logs \
--restart unless-stopped \
myapp:1.0
# 进入容器
docker exec -it myapp sh
# 查看容器日志
docker logs myapp
docker logs -f myapp # 实时日志
# 查看容器资源使用
docker stats
docker stats myapp
# 复制文件
docker cp myapp:/app/logs ./logs
docker cp ./config myapp:/app/config
|
网络管理#
1
2
3
4
5
6
7
8
9
| # 创建网络
docker network create myapp-network
# 连接容器到网络
docker network connect myapp-network myapp
# 查看网络
docker network ls
docker network inspect myapp-network
|
数据持久化#
数据卷#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 创建数据卷
docker volume create app-data
# 挂载数据卷
docker run -v app-data:/app/data myapp
# 查看数据卷
docker volume ls
docker volume inspect app-data
# 备份数据卷
docker run --rm -v app-data:/data -v $(pwd):/backup \
alpine tar czf /backup/backup.tar.gz -C /data .
# 恢复数据卷
docker run --rm -v app-data:/data -v $(pwd):/backup \
alpine tar xzf /backup/backup.tar.gz -C /data
|
绑定挂载#
1
2
3
4
5
6
7
8
| # 挂载本地目录
docker run -v $(pwd)/logs:/app/logs myapp
# 只读挂载
docker run -v $(pwd)/config:/app/config:ro myapp
# 临时文件系统
docker run --tmpfs /app/temp myapp
|
性能优化#
镜像大小优化#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # ✅ 使用alpine版本
FROM node:18-alpine
# ✅ 使用.npmrc减少依赖大小
RUN echo 'package-lock=false' > .npmrc && \
echo 'audit=false' >> .npmrc
# ✅ 多阶段构建减少最终镜像
FROM node:18-alpine AS builder
# 构建步骤...
FROM node:18-alpine AS runtime
# 只复制必要文件
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
|
构建缓存优化#
1
2
3
4
5
6
7
8
9
10
11
| # ✅ 优化COPY顺序
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ✅ 使用BuildKit缓存挂载
# docker build --mount=type=cache,target=/root/.npm -t myapp .
RUN --mount=type=cache,target=/root/.npm \
npm ci
|
运行时优化#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # docker-compose.yml
version: '3.8'
services:
app:
image: myapp:1.0
# 资源限制
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
# 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
|
安全最佳实践#
镜像安全#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # ✅ 使用非root用户
FROM node:18-alpine
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
# ✅ 使用多阶段构建
FROM node:18-alpine AS builder
# 构建步骤...
FROM node:18-alpine AS runtime
# 生产阶段...
# ✅ 最小化安装
RUN apk add --no-cache dumb-init
|
运行时安全#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # ✅ 只开放必要端口
docker run -p 3000:3000 myapp
# ✅ 只读文件系统
docker run --read-only --tmpfs /tmp myapp
# ✅ 限制特权
docker run --user 1001:1001 --cap-drop ALL myapp
# ✅ 安全扫描
docker scan myapp:1.0
# ✅ 使用AppArmor/SELinux
docker run --security-opt apparmor:myapp-profile myapp
|
网络安全#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # docker-compose.yml
version: '3.8'
services:
app:
image: myapp:1.0
networks:
- frontend
- backend
# 不暴露端口到主机
database:
image: postgres:15
networks:
- backend
# 只有app可以访问数据库
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络,不能访问外网
|
CI/CD集成#
GitHub Actions示例#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| # .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
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: |
username/myapp:latest
username/myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
|
GitLab CI示例#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| # .gitlab-ci.yml
stages:
- build
- deploy
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: "/certs"
build:
stage: build
image: docker:20.10
services:
- docker:20.10-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
only:
- main
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- ssh deploy@server "cd /app && docker-compose pull && docker-compose up -d"
only:
- main
|
监控和日志#
日志管理#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| # docker-compose.yml
version: '3.8'
services:
app:
image: myapp:1.0
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels:
- "logging=promtail"
loki:
image: grafana/loki:2.8
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:2.8
volumes:
- /var/log:/var/log
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
|
监控集成#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-storage:/var/lib/grafana
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
volumes:
grafana-storage:
|
故障排查#
常见问题#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # 查看容器详细信息
docker inspect myapp
# 查看容器内进程
docker exec myapp ps aux
# 查看端口占用
docker port myapp
# 进入调试模式
docker run -it --entrypoint sh myapp
# 查看资源使用
docker stats --no-stream myapp
# 清理未使用的资源
docker system prune -a
docker volume prune
docker network prune
|
性能分析#
1
2
3
4
5
6
7
8
9
| # 使用cAdvisor
docker run -d \
--name=cadvisor \
-p 8080:8080 \
-v /:/rootfs:ro \
-v /var/run:/var/run:rw \
-v /sys:/sys:ro \
-v /var/lib/docker/:/var/lib/docker:ro \
gcr.io/cadvisor/cadvisor:latest
|
Docker容器化技术的核心要点:
基础概念:
- 理解镜像、容器、仓库的关系
- 掌握Dockerfile编写技巧
- 学会使用Docker Compose编排多容器应用
最佳实践:
- 使用多阶段构建优化镜像大小
- 实施数据持久化策略
- 遵循安全最佳实践
- 建立监控和日志系统
生产部署:
- 集成CI/CD流水线
- 实施健康检查
- 配置资源限制
- 建立备份和恢复策略
掌握Docker将大大简化你的开发和部署流程,提高应用的可移植性和可扩展性。
相关资源: