下面,我们来系统的梳理关于 Docker 容器化部署 的基本知识点:


一、Docker 基础概念

1.1 Docker 核心组件

组件说明应用场景
镜像(Image)只读模板,包含应用运行所需环境应用打包分发
容器(Container)镜像的运行实例应用运行时环境
仓库(Registry)镜像存储和分发服务Docker Hub, 私有仓库
Dockerfile构建镜像的脚本文件自动化构建镜像
Docker Compose多容器应用管理工具本地开发和生产部署

1.2 Docker 核心优势

  • 环境一致性:开发、测试、生产环境完全一致
  • 快速部署:秒级启动和停止应用
  • 资源隔离:容器间资源隔离,互不影响
  • 弹性伸缩:快速水平扩展应用实例
  • 持续集成:无缝集成 CI/CD 流水线

二、Docker 环境搭建

2.1 安装 Docker

# Ubuntu 安装
sudo apt update
sudo apt install docker.io
sudo systemctl enable --now docker

# macOS 安装
brew install --cask docker

# Windows 安装
下载 Docker Desktop: https://www.docker.com/products/docker-desktop

2.2 验证安装

docker --version
docker run hello-world

2.3 配置镜像加速

// 创建或修改 /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}
sudo systemctl daemon-reload
sudo systemctl restart docker

三、Vue 应用 Docker 化

3.1 基础 Dockerfile

# 使用官方 Node 基础镜像
FROM node:18-alpine as builder

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY package*.json ./
RUN npm ci

# 复制源代码
COPY . .

# 构建应用
RUN npm run build

# 使用 Nginx 作为生产服务器
FROM nginx:1.23-alpine

# 复制构建产物到 Nginx 目录
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制自定义 Nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 暴露 80 端口
EXPOSE 80

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

3.2 优化 Nginx 配置

# nginx.conf
server {
    listen 80;
    server_name localhost;
    
    # 静态资源服务
    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }
    
    # 开启 gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_min_length 1000;
    
    # 缓存设置
    location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
        expires 1M;
        access_log off;
        add_header Cache-Control "public";
    }
    
    # 禁止访问 .env 文件
    location ~ /\.env {
        deny all;
        return 404;
    }
}

四、多阶段构建优化

4.1 优化后的 Dockerfile

# 阶段1: 构建应用
FROM node:18-alpine as builder

# 安装依赖 (单独步骤以利用缓存)
WORKDIR /app
COPY package*.json ./
RUN npm ci

# 复制源代码并构建
COPY . .
RUN npm run build

# 阶段2: 构建运行时镜像
FROM nginx:1.23-alpine as runtime

# 安装工具并清理缓存
RUN apk add --no-cache curl && \
    rm -rf /var/cache/apk/*

# 复制构建产物和配置
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

# 暴露端口
EXPOSE 80

# 启动命令
CMD ["nginx", "-g", "daemon off;"]

4.2 构建优化技巧

  1. 利用构建缓存:先复制 package.json 安装依赖
  2. 使用 .dockerignore:排除不必要的文件
    node_modules
    .git
    .env
    Dockerfile
    docker-compose.yml
    
  3. 选择合适的基础镜像:使用 alpine 版本减小体积
  4. 多阶段构建:分离构建环境和运行环境
  5. 合并指令:减少镜像层数

五、Docker Compose 集成

5.1 基础 docker-compose.yml

version: '3.8'

services:
  web:
    build: 
      context: .
      dockerfile: Dockerfile
    image: vue-app:latest
    container_name: vue-app
    ports:
      - "8080:80"
    environment:
      - NODE_ENV=production
    restart: unless-stopped
    networks:
      - frontend

networks:
  frontend:
    driver: bridge

5.2 完整开发环境配置

version: '3.8'

services:
  web:
    build: 
      context: .
      dockerfile: Dockerfile.dev
    image: vue-app-dev:latest
    container_name: vue-app-dev
    ports:
      - "8080:8080"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
    command: npm run dev
    networks:
      - frontend

  api:
    image: my-api:1.0
    ports:
      - "3000:3000"
    environment:
      - DB_HOST=db
      - DB_PORT=5432
    networks:
      - backend

  db:
    image: postgres:14-alpine
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - backend

networks:
  frontend:
  backend:

volumes:
  pgdata:

六、生产环境部署策略

6.1 部署架构

用户 → 负载均衡器 (Nginx) → 
  → Docker 容器 1 (Vue App)
  → Docker 容器 2 (Vue App)
  → Docker 容器 3 (Vue App)

6.2 部署步骤

# 1. 构建镜像
docker build -t vue-app:1.0 .

# 2. 推送镜像到仓库
docker tag vue-app:1.0 myregistry.com/vue-app:1.0
docker push myregistry.com/vue-app:1.0

# 3. 在服务器拉取镜像
docker pull myregistry.com/vue-app:1.0

# 4. 运行容器
docker run -d \
  --name vue-app \
  -p 80:80 \
  --restart always \
  myregistry.com/vue-app:1.0

6.3 零停机部署脚本

#!/bin/bash

# 1. 拉取新镜像
docker pull myregistry.com/vue-app:1.1

# 2. 启动新容器
docker run -d --name vue-app-1.1 -p 8081:80 myregistry.com/vue-app:1.1

# 3. 等待新容器启动
while ! curl -s http://localhost:8081 >/dev/null; do
  sleep 1
done

# 4. 切换流量 (使用Nginx反向代理)
docker exec nginx nginx -s reload

# 5. 停止旧容器
docker stop vue-app-1.0
docker rm vue-app-1.0

# 6. 清理旧镜像
docker image prune -f

七、CI/CD 集成

7.1 GitHub Actions 示例

name: Docker Build and Deploy

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      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@v3
      with:
        context: .
        push: true
        tags: myusername/vue-app:latest, myusername/vue-app:${{ github.sha }}
        
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - name: SSH to server
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          docker pull myusername/vue-app:${{ github.sha }}
          docker stop vue-app || true
          docker rm vue-app || true
          docker run -d \
            --name vue-app \
            -p 80:80 \
            --restart always \
            myusername/vue-app:${{ github.sha }}

八、实践与优化

8.1 安全加固

  1. 使用非 root 用户运行

    RUN addgroup -S appgroup && adduser -S appuser -G appgroup
    USER appuser
    
  2. 只读文件系统

    docker run --read-only -d myapp
    
  3. 资源限制

    docker run -d \
      --memory=512m \
      --cpus=1.0 \
      myapp
    

8.2 性能优化

  1. 镜像优化

    • 使用多阶段构建
    • 选择小型基础镜像 (alpine)
    • 合并 RUN 指令减少层数
    • 清理不必要的文件
  2. 启动优化

    # 使用 tini 作为 init 进程
    ENTRYPOINT ["/tini", "--"]
    CMD ["npm", "start"]
    

8.3 监控与日志

# 查看容器日志
docker logs -f vue-app

# 查看资源使用
docker stats vue-app

# 进入容器调试
docker exec -it vue-app sh

# 使用 Prometheus 监控
docker run -d \
  -p 9090:9090 \
  -v ./prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

九、常见问题

9.1 容器启动失败

排查步骤

# 1. 查看容器日志
docker logs <container-id>

# 2. 检查容器状态
docker ps -a

# 3. 进入容器调试
docker run -it --entrypoint sh my-image

# 4. 检查端口冲突
netstat -tuln | grep 80

9.2 文件权限问题

解决方案

# Dockerfile 中设置正确权限
RUN chown -R appuser:appgroup /app
USER appuser

9.3 环境变量管理

# Dockerfile
ARG API_URL
ENV VUE_APP_API_URL=$API_URL
# 构建时传入变量
docker build --build-arg API_URL=https://api.example.com -t myapp .

# 运行时传入变量
docker run -e "VUE_APP_API_URL=https://api.example.com" myapp

十、部署模式

10.1 Kubernetes 部署

# vue-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vue-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: vue-app
  template:
    metadata:
      labels:
        app: vue-app
    spec:
      containers:
      - name: vue-app
        image: myregistry.com/vue-app:1.0
        ports:
        - containerPort: 80
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10

---
apiVersion: v1
kind: Service
metadata:
  name: vue-app-service
spec:
  selector:
    app: vue-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vue-app-ingress
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: vue-app-service
            port:
              number: 80

10.2 蓝绿部署

切换流量
退役
用户流量
负载均衡器
当前生产环境 v1.0
新版本环境 v1.1
移除旧版本

十一、 优势

  1. 环境一致性:消除 “在我机器上能运行” 问题
  2. 快速部署:一键部署应用更新
  3. 资源高效:共享主机内核,轻量级虚拟化
  4. 扩展灵活:轻松实现水平扩展
  5. 生态丰富:完善的工具链和社区支持

生产环境检查清单

  1. 使用多阶段构建减小镜像体积
  2. 配置非 root 用户运行容器
  3. 设置资源限制 (CPU/内存)
  4. 实现健康检查机制
  5. 配置日志收集和监控
  6. 建立 CI/CD 流水线
  7. 制定回滚策略
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐