Docker自动化部署全流程实战:从镜像构建到生产发布的完整方案

Docker镜像构建的最佳实践

生产级Docker镜像不是把代码拷进容器就完事了。一个合格的镜像要满足三个条件:体积小、构建快、安全无漏洞。从Dockerfile的写法开始就有讲究。

多阶段构建是减小镜像体积的核心手段:

# 阶段1:构建依赖
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build

# 阶段2:运行时镜像
FROM node:20-alpine AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

# 安全加固
RUN addgroup -S appgroup && adduser -S appuser -G appgroup && chown -R appuser:appgroup /app
USER appuser

EXPOSE 3000
CMD ["node", "dist/main.js"]

这个Dockerfile把最终镜像从1.2GB压缩到180MB左右,构建缓存命中率从40%提升到85%。关键操作:构建依赖不进运行时镜像,非root用户运行,alpine替代full镜像。

镜像层缓存优化策略

Docker构建速度取决于缓存命中。Dockerfile指令顺序决定缓存层:

# 错误写法:代码变更导致所有层重建
COPY . /app
RUN npm install
RUN npm run build

# 正确写法:依赖不变则跳过install层
COPY package*.json /app/
RUN npm ci
COPY . /app
RUN npm run build

原则:变化频率低的指令放前面,变化频率高的放后面。package.json的变更频率远低于源代码,先拷贝依赖文件再安装,只有package.json变化时才重新执行npm ci。

.dockerignore文件同样关键:

# .dockerignore
node_modules
.git
.github
.env*
*.log
coverage
.vscode
dist
.next
__pycache__
*.pyc
.pytest_cache

把不需要的文件排除在外,一是减小构建上下文体积,二是防止敏感信息(.env文件)意外进入镜像。

Docker Compose多服务编排

单容器部署只适合简单场景,微服务架构至少需要应用、数据库、缓存多个容器协同。Docker Compose编排的关键是依赖关系和健康检查:

version: "3.8"
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
      interval: 5s
      timeout: 3s
      retries: 10

  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://appuser:password@postgres:5432/appdb
      REDIS_URL: redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "1.0"

volumes:
  pgdata:

depends_on配合condition: service_healthy确保应用容器只在数据库和缓存就绪后启动。Docker Secrets管理敏感配置,不把密码写进docker-compose.yml。

CI/CD流水线集成Docker部署

GitLab CI的完整Docker部署流水线:

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
  LATEST_TAG: $CI_REGISTRY_IMAGE:latest

test:
  stage: test
  image: node:20-alpine
  script:
    - npm ci
    - npm run test:ci
    - npm run lint

build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
    - docker pull $LATEST_TAG || true
    - docker build --cache-from $LATEST_TAG -t $IMAGE_TAG -t $LATEST_TAG .
    - docker push $IMAGE_TAG
    - docker push $LATEST_TAG
  only:
    - main

deploy:
  stage: deploy
  image: alpine:3.19
  script:
    - ssh -o StrictHostKeyChecking=no deploy@prod-server "docker pull $IMAGE_TAG && docker-compose up -d --force-recreate app"
  only:
    - main
  when: manual

生产部署放在manual触发,避免测试环境变更直接上生产。docker pull配合up –force-recreate实现零停机更新。

生产环境Docker安全加固

容器的安全边界比虚拟机弱得多,默认配置下容器逃逸并不困难。生产环境必须做的加固:

1. 只读根文件系统

app:
  read_only: true
  tmpfs:
    - /tmp:size=100M
    - /app/logs:size=50M

2. 限制内核能力

app:
  cap_drop:
    - ALL
  cap_add:
    - NET_BIND_SERVICE

3. 资源限制防DoS

app:
  deploy:
    resources:
      limits:
        memory: 512M
        cpus: "1.0"
        pids: 100

4. 镜像漏洞扫描

trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE_TAG

5. 非root运行:所有生产容器必须指定USER指令,禁止以root身份运行应用进程。

Docker自动化部署的核心不是写Dockerfile,而是把镜像构建、依赖编排、流水线集成、安全加固串成一个闭环。任何一环缺失,生产环境的稳定性就会打折。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/docker-zi-dong-hua-bu-shu-quan-liu-cheng-shi-zhan-cong-jing/

(0)
小编小编
上一篇 18小时前
下一篇 18小时前

相关推荐