Docker容器化实战:从开发到部署的完整工作流
Docker容器化实战:从开发到部署的完整工作流前言Docker容器化技术彻底改变了现代软件开发和部署方式。本文将分享从开发到部署的完整Docker工作流,包括最佳实践、性能优化和常见问题解决方案。1. Docker基础架构1.1 核心组件Docker由以下核心组件构成:Docker架构 ├── Docker Engine (引擎) │ ├── Docker Daemon (守护进程) │ ├── REST API │ └── CLI (命令行接口) ├── Images (镜像) │ ├── 基础镜像 (Ubuntu, Alpine等) │ ├── 应用镜像 │ └── 多阶段构建 ├── Containers (容器) │ ├── 运行实例 │ ├── 资源限制 │ └── 网络配置 └── Registry (仓库) ├── Docker Hub ├── 私有仓库 └── 镜像分发1.2 Dockerfile最佳实践错误做法:单一RUN指令安装所有依赖# ❌ 错误:单一RUN指令 FROM ubuntu:20.04 RUN apt-get update apt-get install -y \ python3 \ python3-pip \ nginx \ postgresql-client \ curl \ wget \ vim \ rm -rf /var/lib/apt/lists/*正确做法:分层构建,优化缓存# ✅ 正确:分层构建 FROM ubuntu:20.04 # 设置环境变量 ENV DEBIAN_FRONTEND=noninteractive ENV PYTHONUNBUFFERED=1 # 安装系统依赖(单独一层,便于缓存) RUN apt-get update apt-get install -y \ python3 \ python3-pip \ nginx \ postgresql-client \ curl \ rm -rf /var/lib/apt/lists/* \ apt-get clean # 创建应用目录 WORKDIR /app # 复制依赖文件(单独一层,依赖变化时才重建) COPY requirements.txt . # 安装Python依赖 RUN pip3 install --no-cache-dir -r requirements.txt # 复制应用代码(最后复制,代码变化时只重建这一层) COPY . . # 暴露端口 EXPOSE 8000 # 启动命令 CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]2. 多阶段构建2.1 构建优化# 多阶段构建示例 # 阶段1:构建阶段 FROM python:3.11-slim as builder WORKDIR /app # 安装构建依赖 RUN apt-get update apt-get install -y \ build-essential \ libpq-dev \ rm -rf /var/lib/apt/lists/* # 复制依赖文件 COPY requirements.txt . # 安装Python依赖到虚拟环境 RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" RUN pip install --no-cache-dir -r requirements.txt # 阶段2:运行阶段 FROM python:3.11-slim WORKDIR /app # 安装运行时依赖 RUN apt-get update apt-get install -y \ libpq5 \ nginx \ rm -rf /var/lib/apt/lists/* # 从构建阶段复制虚拟环境 COPY --from=builder /opt/venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" # 复制应用代码 COPY . . # 复制nginx配置 COPY nginx.conf /etc/nginx/nginx.conf # 创建非root用户 RUN useradd -m -u 1000 appuser chown -R appuser:appuser /app USER appuser # 暴露端口 EXPOSE 80 8000 # 启动命令 CMD ["sh", "-c", "nginx python manage.py runserver 0.0.0.0:8000"]2.2 Node.js多阶段构建# Node.js多阶段构建 # 阶段1:依赖安装 FROM node:18-alpine as deps WORKDIR /app # 复制包管理文件 COPY package.json package-lock.json ./ # 安装依赖 RUN npm ci --only=production # 阶段2:构建阶段 FROM node:18-alpine as builder WORKDIR /app # 复制依赖 COPY --from=deps /app/node_modules ./node_modules COPY . . # 构建应用 RUN npm run build # 阶段3:运行阶段 FROM node:18-alpine WORKDIR /app # 从构建阶段复制构建结果 COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./ # 创建非root用户 RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 USER nextjs # 暴露端口 EXPOSE 3000 # 启动命令 CMD ["node", "dist/main.js"]3. Docker Compose编排3.1 完整应用栈# docker-compose.ymlversion:'3.8'services:# 数据库服务postgres:image:postgres:15-alpinecontainer_name:app-postgresenvironment:POSTGRES_DB:myappPOSTGRES_USER:appuserPOSTGRES_PASSWORD:${DB_PASSWORD}volumes:-postgres_data:/var/lib/postgresql/data-./init.sql:/docker-entrypoint-initdb.d/init.sqlports:-"5432:5432"networks:-app-networkhealthcheck:test:["CMD-SHELL","pg_isready -U appuser -d myapp"]interval:10stimeout:5sretries:5# 缓存服务redis:image:redis:7-alpinecontainer_name:app-rediscommand:redis-server--appendonly yesvolumes:-redis_data:/dataports:-"6379:6379"networks:-app-networkhealthcheck:test:["CMD","redis-cli","ping"]interval:10stimeout:5sretries:5# 后端APIapi:build:context:./apidockerfile:Dockerfilecontainer_name:app-apienvironment:-DATABASE_URL=postgresql://appuser:${DB_PASSWORD}@postgres:5432/myapp-REDIS_URL=redis://redis:6379-SECRET_KEY=${SECRET_KEY}-DEBUG=${DEBUG:-false}volumes:-./api:/app-/app/node_modulesports:-"8000:8000"networks:-app-networkdepends_on:postgres:condition:service_healthyredis:condition:service_healthyrestart:unless-stopped# 前端应用frontend:build:context:./frontenddockerfile:Dockerfilecontainer_name:app-frontendenvironment:-REACT_APP_API_URL=http://localhost:8000volumes:-./frontend:/app-/app/node_modulesports:-"3000:3000"networks:-app-networkdepends_on:-api# Nginx反向代理nginx:image:nginx:alpinecontainer_name:app-nginxvolumes:-./nginx/nginx.conf:/etc/nginx/nginx.conf-./nginx/ssl:/etc/nginx/sslports:-"80:80"-"443:443"networks:-app-networkdepends_on:-api-frontend# 监控服务prometheus:image:prom/prometheuscontainer_name:app-prometheusvolumes:-./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml-prometheus_data:/prometheusports:-"9090:9090"networks:-app-networkgrafana:image:grafana/grafanacontainer_name:app-grafanaenvironment:-GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}volumes:-grafana_data:/var/lib/grafana-./grafana/provisioning:/etc/grafana/provisioningports:-"3001:3000"networks:-