当前位置: 首页 > news >正文

Docker 前端部署:别再手动配环境了

Docker 前端部署:别再手动配环境了

毒舌时刻

这代码写得跟网红滤镜似的——仅供参考。

各位前端同行,咱们今天聊聊 Docker。别告诉我你还在手动配环境,那感觉就像每次吃饭都要重新买菜做饭——能吃,但累死人。

为什么你需要 Docker

最近看到一个项目,开发环境、测试环境、生产环境配置都不一样,每次部署都要改一堆配置。我就想问:你是在写代码还是在玩"找不同"?

反面教材

# 反面教材:手动部署流程 # 开发环境 $ npm install $ npm run dev # 测试环境 $ npm install --production $ npm run build $ scp -r dist/ user@test-server:/var/www/ # 报错:Node 版本不对 # 报错:依赖安装失败 # 报错:环境变量缺失 # 😭😭😭 # 生产环境 $ npm install --production $ npm run build $ rsync -avz dist/ user@prod-server:/var/www/ # 又报一堆错 # 环境不一致,问题难复现

毒舌点评:这流程,部署一次要 2 小时,你是在写代码还是在做运维?

Docker 的正确姿势

1. 基础 Dockerfile

# 正确姿势:多阶段构建 # Dockerfile # 阶段1:构建 FROM node:20-alpine AS builder WORKDIR /app # 先复制依赖文件,利用缓存 COPY package*.json ./ RUN npm ci # 复制源代码 COPY . . # 构建 RUN npm run build # 阶段2:运行 FROM node:20-alpine AS runner WORKDIR /app # 只复制必要文件 COPY --from=builder /app/dist ./dist COPY --from=builder /app/package*.json ./ # 只安装生产依赖 RUN npm ci --only=production # 暴露端口 EXPOSE 3000 # 启动 CMD ["node", "dist/server.js"]

2. Next.js 专用

# 正确姿势:Next.js Docker 配置 # Dockerfile FROM node:20-alpine AS base # 安装依赖 FROM base AS deps RUN apk add --no-cache libc6-compat WORKDIR /app COPY package*.json ./ RUN npm ci # 构建 FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . ENV NEXT_TELEMETRY_DISABLED 1 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 RUN mkdir .next RUN chown nextjs:nodejs .next 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"]

3. Docker Compose

# 正确姿势:docker-compose.yml version: '3.8' services: # 前端应用 app: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: - NODE_ENV=production - API_URL=http://api:8080 depends_on: - api networks: - frontend-network # Nginx 反向代理 nginx: image: nginx:alpine ports: - "80:80" - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf - ./ssl:/etc/nginx/ssl depends_on: - app networks: - frontend-network # 后端 API(示例) api: image: my-api:latest ports: - "8080:8080" environment: - DATABASE_URL=postgres://db:5432/mydb networks: - frontend-network networks: frontend-network: driver: bridge

4. Nginx 配置

# nginx.conf upstream app { server app:3000; } server { listen 80; server_name example.com; # 重定向到 HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; # Gzip gzip on; gzip_types text/plain text/css application/json application/javascript; # 静态资源缓存 location /_next/static { alias /app/.next/static; expires 1y; add_header Cache-Control "public, immutable"; } location /static { alias /app/public; expires 1y; add_header Cache-Control "public, immutable"; } # 代理到应用 location / { proxy_pass http://app; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }

毒舌点评:这才叫现代部署,一次构建,到处运行,环境完全一致。

实战技巧:Docker 最佳实践

1. 优化镜像大小

# 正确姿势:最小化镜像 FROM node:20-alpine # 使用非 root 用户 RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 # 只复制必要文件 COPY --chown=nextjs:nodejs package*.json ./ RUN npm ci --only=production && npm cache clean --force COPY --chown=nextjs:nodejs . . USER nextjs EXPOSE 3000 CMD ["node", "server.js"]

2. 开发环境

# docker-compose.dev.yml version: '3.8' services: app: build: context: . dockerfile: Dockerfile.dev ports: - "3000:3000" volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development - CHOKIDAR_USEPOLLING=true command: npm run dev
# Dockerfile.dev FROM node:20-alpine WORKDIR /app # 安装依赖 COPY package*.json ./ RUN npm install EXPOSE 3000 CMD ["npm", "run", "dev"]

3. CI/CD 集成

# .github/workflows/docker.yml name: Docker Build and Push on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push uses: docker/build-push-action@v5 with: context: . push: true tags: | ${{ secrets.DOCKER_USERNAME }}/myapp:latest ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max

4. 环境变量管理

# Dockerfile FROM node:20-alpine # 构建参数 ARG NODE_ENV=production ARG API_URL ENV NODE_ENV=${NODE_ENV} ENV API_URL=${API_URL} WORKDIR /app COPY . . RUN npm ci && npm run build EXPOSE 3000 CMD ["node", "dist/server.js"]
# 构建时传入参数 docker build \ --build-arg NODE_ENV=production \ --build-arg API_URL=https://api.example.com \ -t myapp:latest . # 运行时传入环境变量 docker run -e API_URL=https://api.example.com -p 3000:3000 myapp:latest

5. 健康检查

# Dockerfile FROM node:20-alpine WORKDIR /app COPY . . RUN npm ci --only=production EXPOSE 3000 # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/api/health || exit 1 CMD ["node", "server.js"]

6. 常见陷阱

# 陷阱1:不使用 .dockerignore # .dockerignore node_modules npm-debug.log .next .git .env .env.local .env.production # 陷阱2:不使用多阶段构建 FROM node:20-alpine COPY . . RUN npm ci RUN npm run build # ❌ 镜像包含所有依赖和源码,体积巨大 # 正确做法:使用多阶段构建 ✅ # 陷阱3:使用 root 用户运行 # ❌ 安全风险 # 正确做法:创建非 root 用户 ✅ RUN adduser -S appuser USER appuser # 陷阱4:不清理缓存 RUN npm ci # ❌ 缓存留在镜像中 # 正确做法:清理缓存 ✅ RUN npm ci && npm cache clean --force

最后想说的

Docker 不是可选的,是现代部署的标准。别再手动配环境了——用上 Docker,你的部署会简单 100 倍。

记住:好的部署应该是一致的,开发、测试、生产环境完全一致。Docker 让这一切变得简单。

http://www.jsqmd.com/news/553309/

相关文章:

  • 美团天天神券自动化脚本终极指南:告别手动抢券,每月轻松省下200元
  • NPU加速!DeepSeek-V3大模型极速体验攻略
  • 企业网实战:用H3C交换机的VLANIF接口,5步搭建财务与研发部门的安全隔离网络
  • Wan2.2-I2V-A14B混合精度推理实战:BF16+FP16显存节省与画质平衡
  • 2026诚信聚氨酯密封件优质厂家推荐榜:定制化真空吸盘、桥梁建筑阻尼器密封、橡胶真空吸盘密封件、氮气弹簧密封、汽车油缸密封件选择指南 - 优质品牌商家
  • 一键部署!OFA图像语义蕴含模型Web应用实战体验
  • 29、【Agent】【OpenCode】模型配置(OpenCode Zen)(二)
  • STM8 BootLoader 串口烧录实战指南(STM8AF624x系列)
  • 如何通过CPUDoc免费优化CPU性能:5大核心功能全面指南
  • coze-loop效果可视化:热力图对比优化前后CPU占用与内存波动
  • 川内冶金行业高评价耐火材料品牌推荐:四川耐火材料、四川耐火砖、成都耐火材料、成都耐火砖、耐火材料供应厂家、耐火材料厂商选择指南 - 优质品牌商家
  • 弦音墨影部署避坑指南:Qwen2.5-VL依赖冲突解决与水墨前端兼容性修复
  • Source Han Serif CN:7种字重如何改变你的中文排版体验?
  • 风电机组变桨控制:OpenFast 与 Simulink 联合仿真探秘
  • AI净界-RMBG-1.4企业落地:制造业产品手册高清图自动透明化处理
  • 3个高效功能让Maccy成为macOS必备剪贴板管理器
  • 2026年口碑好的多用炉生产线/日式多用炉/密封箱式多用炉厂家推荐与采购指南 - 行业平台推荐
  • Qwen2.5-7B能否替代13B?数学能力对比实测报告
  • YOLOFuse训练教程:如何准备自己的RGB/红外配对数据集并开始训练
  • 百川2-13B-4bits量化版.NET开发者集成指南:C#调用大模型API
  • Alpamayo-R1-10B详细步骤:从supervisorctl服务管理到日志实时监控
  • MediaPipe人体骨骼检测:零配置Web应用,上传图片秒出骨架图
  • Mirage Flow 模型精调实战:解决代码耦合过度问题的重构建议生成
  • 高效掌握小熊猫Dev-C++:从入门到精通的完全指南
  • EmbeddingGemma-300m+Ollama:专利文本向量化与检索实战
  • LFM2.5-1.2B-Thinking-GGUF部署案例:从CSDN GPU实例到外网可访问服务全流程
  • 为什么你的Polars清洗脚本仍触发Python GIL?3个被文档隐藏的unsafe_mode调用点(源码定位+修复方案)
  • 零代码基础!用MogFace实现人脸检测透明框,效果惊艳
  • 架构革新与纯粹体验:铜钟音乐平台的现代Web音频解决方案
  • 工业软件集成:在SolidWorks中嵌入Qwen3-ASR-0.6B实现语音指令操作