dockerfile-optimizer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Dockerfile Optimizer

Dockerfile 优化指南

Build optimized, secure, and cache-efficient Docker images following production best practices.
遵循生产环境最佳实践,构建经过优化、安全且缓存高效的Docker镜像。

Core Workflow

核心工作流程

  1. Analyze current Dockerfile: Identify optimization opportunities
  2. Implement multi-stage builds: Separate build and runtime
  3. Optimize layer caching: Order instructions efficiently
  4. Minimize image size: Use slim base images and cleanup
  5. Add security hardening: Non-root user, minimal permissions
  6. Configure health checks: Ensure container health monitoring
  1. 分析现有Dockerfile:识别优化机会
  2. 实现多阶段构建:分离构建与运行环境
  3. 优化层缓存:合理排序指令
  4. 最小化镜像体积:使用轻量基础镜像并清理冗余内容
  5. 添加安全加固:使用非root用户、最小权限
  6. 配置健康检查:确保容器健康监控

Base Image Selection

基础镜像选择

Image Size Comparison

镜像体积对比

Base ImageSizeUse Case
node:20
~1GBDevelopment only
node:20-slim
~200MBGeneral production
node:20-alpine
~130MBSize-critical production
gcr.io/distroless/nodejs20
~120MBMaximum security
基础镜像体积使用场景
node:20
~1GB仅用于开发环境
node:20-slim
~200MB通用生产环境
node:20-alpine
~130MB对体积要求严格的生产环境
gcr.io/distroless/nodejs20
~120MB最高安全级别场景

Recommendations by Language

按语言推荐

dockerfile
undefined
dockerfile
undefined

Node.js

Node.js

FROM node:20-alpine
FROM node:20-alpine

Python

Python

FROM python:3.12-slim
FROM python:3.12-slim

Go

Go

FROM golang:1.22-alpine AS builder FROM scratch AS runtime # Or gcr.io/distroless/static
FROM golang:1.22-alpine AS builder FROM scratch AS runtime # Or gcr.io/distroless/static

Rust

Rust

FROM rust:1.75-alpine AS builder FROM alpine:3.19 AS runtime
FROM rust:1.75-alpine AS builder FROM alpine:3.19 AS runtime

Java

Java

FROM eclipse-temurin:21-jdk-alpine AS builder FROM eclipse-temurin:21-jre-alpine AS runtime
undefined
FROM eclipse-temurin:21-jdk-alpine AS builder FROM eclipse-temurin:21-jre-alpine AS runtime
undefined

Multi-Stage Builds

多阶段构建

Node.js Application

Node.js 应用

dockerfile
undefined
dockerfile
undefined

==================== Build Stage ====================

==================== Build Stage ====================

FROM node:20-alpine AS builder
WORKDIR /app
FROM node:20-alpine AS builder
WORKDIR /app

Install dependencies first (cache layer)

Install dependencies first (cache layer)

COPY package.json package-lock.json ./ RUN npm ci --ignore-scripts
COPY package.json package-lock.json ./ RUN npm ci --ignore-scripts

Copy source and build

Copy source and build

COPY . . RUN npm run build
COPY . . RUN npm run build

Prune dev dependencies

Prune dev dependencies

RUN npm prune --production
RUN npm prune --production

==================== Production Stage ====================

==================== Production Stage ====================

FROM node:20-alpine AS production
FROM node:20-alpine AS production

Security: Create non-root user

Security: Create non-root user

RUN addgroup -g 1001 -S nodejs &&
adduser -S nextjs -u 1001
WORKDIR /app
RUN addgroup -g 1001 -S nodejs &&
adduser -S nextjs -u 1001
WORKDIR /app

Copy only necessary files

Copy only necessary files

COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist COPY --from=builder --chown=nextjs:nodejs /app/package.json ./
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist COPY --from=builder --chown=nextjs:nodejs /app/package.json ./

Security: Switch to non-root user

Security: Switch to non-root user

USER nextjs
USER nextjs

Health check

Health check

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
EXPOSE 3000
CMD ["node", "dist/index.js"]
undefined
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
EXPOSE 3000
CMD ["node", "dist/index.js"]
undefined

Next.js Application

Next.js 应用

dockerfile
undefined
dockerfile
undefined

==================== Dependencies ====================

==================== Dependencies ====================

FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./ RUN npm ci
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./ RUN npm ci

==================== Builder ====================

==================== Builder ====================

FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY . .
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY . .

Disable telemetry during build

Disable telemetry during build

ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build

==================== Runner ====================

==================== Runner ====================

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs &&
adduser --system --uid 1001 nextjs
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs &&
adduser --system --uid 1001 nextjs

Copy static assets

Copy static assets

COPY --from=builder /app/public ./public
COPY --from=builder /app/public ./public

Set correct permissions for prerender cache

Set correct permissions for prerender cache

RUN mkdir .next && chown nextjs:nodejs .next
RUN mkdir .next && chown nextjs:nodejs .next

Copy build output

Copy build output

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"
HEALTHCHECK --interval=30s --timeout=3s
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
CMD ["node", "server.js"]
undefined
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"
HEALTHCHECK --interval=30s --timeout=3s
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
CMD ["node", "server.js"]
undefined

Python Application

Python 应用

dockerfile
undefined
dockerfile
undefined

==================== Builder ====================

==================== Builder ====================

FROM python:3.12-slim AS builder
WORKDIR /app
FROM python:3.12-slim AS builder
WORKDIR /app

Install build dependencies

Install build dependencies

RUN apt-get update && apt-get install -y --no-install-recommends
build-essential
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y --no-install-recommends
build-essential
&& rm -rf /var/lib/apt/lists/*

Create virtual environment

Create virtual environment

RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH"
RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH"

Install dependencies

Install dependencies

COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt
COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt

==================== Production ====================

==================== Production ====================

FROM python:3.12-slim AS production
WORKDIR /app
FROM python:3.12-slim AS production
WORKDIR /app

Create non-root user

Create non-root user

RUN groupadd -r appuser && useradd -r -g appuser appuser
RUN groupadd -r appuser && useradd -r -g appuser appuser

Copy virtual environment from builder

Copy virtual environment from builder

COPY --from=builder /opt/venv /opt/venv ENV PATH="/opt/venv/bin:$PATH"
COPY --from=builder /opt/venv /opt/venv ENV PATH="/opt/venv/bin:$PATH"

Copy application code

Copy application code

COPY --chown=appuser:appuser . .
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
undefined
COPY --chown=appuser:appuser . .
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
undefined

Go Application

Go 应用

dockerfile
undefined
dockerfile
undefined

==================== Builder ====================

==================== Builder ====================

FROM golang:1.22-alpine AS builder
RUN apk add --no-cache git ca-certificates tzdata
WORKDIR /app
FROM golang:1.22-alpine AS builder
RUN apk add --no-cache git ca-certificates tzdata
WORKDIR /app

Download dependencies

Download dependencies

COPY go.mod go.sum ./ RUN go mod download && go mod verify
COPY go.mod go.sum ./ RUN go mod download && go mod verify

Build

Build

COPY . . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
-ldflags="-w -s -X main.version=$(git describe --tags --always)"
-o /app/server ./cmd/server
COPY . . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
-ldflags="-w -s -X main.version=$(git describe --tags --always)"
-o /app/server ./cmd/server

==================== Production ====================

==================== Production ====================

FROM scratch AS production
FROM scratch AS production

Copy CA certificates for HTTPS

Copy CA certificates for HTTPS

COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo

Copy binary

Copy binary

COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
undefined
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
undefined

Layer Caching Optimization

层缓存优化

Order Instructions by Change Frequency

按变更频率排序指令

dockerfile
undefined
dockerfile
undefined

✓ GOOD: Least changing → Most changing

✓ GOOD: Least changing → Most changing

FROM node:20-alpine
FROM node:20-alpine

1. System dependencies (rarely change)

1. System dependencies (rarely change)

RUN apk add --no-cache dumb-init
RUN apk add --no-cache dumb-init

2. Create user (rarely changes)

2. Create user (rarely changes)

RUN adduser -D appuser
RUN adduser -D appuser

3. Set working directory

3. Set working directory

WORKDIR /app
WORKDIR /app

4. Copy dependency files (change occasionally)

4. Copy dependency files (change occasionally)

COPY package.json package-lock.json ./
COPY package.json package-lock.json ./

5. Install dependencies (cached if package files unchanged)

5. Install dependencies (cached if package files unchanged)

RUN npm ci --production
RUN npm ci --production

6. Copy source code (changes frequently)

6. Copy source code (changes frequently)

COPY --chown=appuser:appuser . .
USER appuser CMD ["dumb-init", "node", "index.js"]

```dockerfile
COPY --chown=appuser:appuser . .
USER appuser CMD ["dumb-init", "node", "index.js"]

```dockerfile

✗ BAD: Source code before dependencies

✗ BAD: Source code before dependencies

FROM node:20-alpine WORKDIR /app COPY . . # Invalidates cache on ANY file change RUN npm install # Must reinstall every time CMD ["node", "index.js"]
undefined
FROM node:20-alpine WORKDIR /app COPY . . # Invalidates cache on ANY file change RUN npm install # Must reinstall every time CMD ["node", "index.js"]
undefined

.dockerignore

.dockerignore 配置

dockerignore
undefined
dockerignore
undefined

Version control

Version control

.git .gitignore
.git .gitignore

Dependencies (reinstalled in container)

Dependencies (reinstalled in container)

node_modules .pnpm-store
node_modules .pnpm-store

Build outputs

Build outputs

dist build .next out
dist build .next out

Development files

Development files

.env*.local *.log coverage .nyc_output
.env*.local *.log coverage .nyc_output

IDE

IDE

.idea .vscode *.swp *.swo
.idea .vscode *.swp *.swo

Docker

Docker

Dockerfile* docker-compose* .docker
Dockerfile* docker-compose* .docker

Documentation

Documentation

*.md docs
*.md docs

Tests (unless needed in container)

Tests (unless needed in container)

tests *.test.ts .spec.ts jest.config.
undefined
tests *.test.ts .spec.ts jest.config.
undefined

Image Size Reduction

镜像体积缩减

Clean Up in Same Layer

在同一层中清理

dockerfile
undefined
dockerfile
undefined

✓ GOOD: Install and clean in one layer

✓ GOOD: Install and clean in one layer

RUN apt-get update &&
apt-get install -y --no-install-recommends
curl
ca-certificates
&& rm -rf /var/lib/apt/lists/*
&& apt-get clean
RUN apt-get update &&
apt-get install -y --no-install-recommends
curl
ca-certificates
&& rm -rf /var/lib/apt/lists/*
&& apt-get clean

✗ BAD: Separate layers (cleanup doesn't reduce size)

✗ BAD: Separate layers (cleanup doesn't reduce size)

RUN apt-get update RUN apt-get install -y curl RUN rm -rf /var/lib/apt/lists/* # Too late, already in previous layer
undefined
RUN apt-get update RUN apt-get install -y curl RUN rm -rf /var/lib/apt/lists/* # Too late, already in previous layer
undefined

Use --no-install-recommends

使用 --no-install-recommends 参数

dockerfile
undefined
dockerfile
undefined

✓ Minimal installation

✓ Minimal installation

RUN apt-get install -y --no-install-recommends package-name
RUN apt-get install -y --no-install-recommends package-name

✗ Installs unnecessary recommended packages

✗ Installs unnecessary recommended packages

RUN apt-get install -y package-name
undefined
RUN apt-get install -y package-name
undefined

Alpine Package Management

Alpine 包管理

dockerfile
undefined
dockerfile
undefined

Alpine uses apk, not apt

Alpine uses apk, not apt

RUN apk add --no-cache
curl
git
&& rm -rf /var/cache/apk/*
undefined
RUN apk add --no-cache
curl
git
&& rm -rf /var/cache/apk/*
undefined

Security Hardening

安全加固

Non-Root User

非root用户

dockerfile
undefined
dockerfile
undefined

Create user in Debian/Ubuntu

Create user in Debian/Ubuntu

RUN groupadd -r appgroup && useradd -r -g appgroup appuser
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

Create user in Alpine

Create user in Alpine

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

Set ownership and switch user

Set ownership and switch user

COPY --chown=appuser:appgroup . . USER appuser
undefined
COPY --chown=appuser:appgroup . . USER appuser
undefined

Read-Only Filesystem

只读文件系统

dockerfile
undefined
dockerfile
undefined

In docker-compose.yml or docker run

In docker-compose.yml or docker run

services: app: read_only: true tmpfs: - /tmp - /var/run
undefined
services: app: read_only: true tmpfs: - /tmp - /var/run
undefined

Security Scanning

安全扫描

dockerfile
undefined
dockerfile
undefined

Add labels for security scanning

Add labels for security scanning

LABEL org.opencontainers.image.source="https://github.com/org/repo" LABEL org.opencontainers.image.description="Application description" LABEL org.opencontainers.image.licenses="MIT"
undefined
LABEL org.opencontainers.image.source="https://github.com/org/repo" LABEL org.opencontainers.image.description="Application description" LABEL org.opencontainers.image.licenses="MIT"
undefined

Minimal Capabilities

最小权限配置

yaml
undefined
yaml
undefined

docker-compose.yml

docker-compose.yml

services: app: cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Only if binding to port < 1024 security_opt: - no-new-privileges:true
undefined
services: app: cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Only if binding to port < 1024 security_opt: - no-new-privileges:true
undefined

Health Checks

健康检查

HTTP Health Check

HTTP 健康检查

dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1
dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

Without curl (smaller image)

不使用curl(更小镜像)

dockerfile
undefined
dockerfile
undefined

Node.js

Node.js

HEALTHCHECK --interval=30s --timeout=3s --retries=3
CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
HEALTHCHECK --interval=30s --timeout=3s --retries=3
CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"

Python

Python

HEALTHCHECK --interval=30s --timeout=3s --retries=3
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
HEALTHCHECK --interval=30s --timeout=3s --retries=3
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1

wget (Alpine)

wget (Alpine)

HEALTHCHECK --interval=30s --timeout=3s --retries=3
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
undefined
HEALTHCHECK --interval=30s --timeout=3s --retries=3
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
undefined

Environment Variables

环境变量

dockerfile
undefined
dockerfile
undefined

Build-time arguments

Build-time arguments

ARG NODE_ENV=production ARG APP_VERSION=unknown
ARG NODE_ENV=production ARG APP_VERSION=unknown

Runtime environment variables

Runtime environment variables

ENV NODE_ENV=$NODE_ENV ENV APP_VERSION=$APP_VERSION
ENV NODE_ENV=$NODE_ENV ENV APP_VERSION=$APP_VERSION

Don't include secrets in Dockerfile

Don't include secrets in Dockerfile

Use docker run --env-file or secrets management

Use docker run --env-file or secrets management

undefined
undefined

Docker Compose for Development

开发环境Docker Compose配置

yaml
undefined
yaml
undefined

docker-compose.yml

docker-compose.yml

version: '3.8'
services: app: build: context: . dockerfile: Dockerfile target: development # Multi-stage target volumes: - .:/app - /app/node_modules # Anonymous volume for node_modules ports: - "3000:3000" environment: - NODE_ENV=development command: npm run dev
app-prod: build: context: . dockerfile: Dockerfile target: production ports: - "3000:3000" environment: - NODE_ENV=production healthcheck: test: ["CMD", "wget", "--spider", "http://localhost:3000/health"] interval: 30s timeout: 3s retries: 3
undefined
version: '3.8'
services: app: build: context: . dockerfile: Dockerfile target: development # Multi-stage target volumes: - .:/app - /app/node_modules # Anonymous volume for node_modules ports: - "3000:3000" environment: - NODE_ENV=development command: npm run dev
app-prod: build: context: . dockerfile: Dockerfile target: production ports: - "3000:3000" environment: - NODE_ENV=production healthcheck: test: ["CMD", "wget", "--spider", "http://localhost:3000/health"] interval: 30s timeout: 3s retries: 3
undefined

CI/CD Integration

CI/CD 集成

GitHub Actions Build

GitHub Actions 构建配置

yaml
undefined
yaml
undefined

.github/workflows/docker.yml

.github/workflows/docker.yml

name: Docker Build
on: push: branches: [main] pull_request: 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 Container Registry
    uses: docker/login-action@v3
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - name: Build and push
    uses: docker/build-push-action@v5
    with:
      context: .
      push: ${{ github.event_name != 'pull_request' }}
      tags: |
        ghcr.io/${{ github.repository }}:latest
        ghcr.io/${{ github.repository }}:${{ github.sha }}
      cache-from: type=gha
      cache-to: type=gha,mode=max

  - name: Scan for vulnerabilities
    uses: aquasecurity/trivy-action@master
    with:
      image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
      format: 'table'
      exit-code: '1'
      severity: 'CRITICAL,HIGH'
undefined
name: Docker Build
on: push: branches: [main] pull_request: 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 Container Registry
    uses: docker/login-action@v3
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - name: Build and push
    uses: docker/build-push-action@v5
    with:
      context: .
      push: ${{ github.event_name != 'pull_request' }}
      tags: |
        ghcr.io/${{ github.repository }}:latest
        ghcr.io/${{ github.repository }}:${{ github.sha }}
      cache-from: type=gha
      cache-to: type=gha,mode=max

  - name: Scan for vulnerabilities
    uses: aquasecurity/trivy-action@master
    with:
      image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
      format: 'table'
      exit-code: '1'
      severity: 'CRITICAL,HIGH'
undefined

Common Optimizations

常见优化技巧

Pin Versions

固定版本

dockerfile
undefined
dockerfile
undefined

✓ Pinned versions for reproducibility

✓ Pinned versions for reproducibility

FROM node:20.11.0-alpine3.19
FROM node:20.11.0-alpine3.19

✗ Latest tags can break builds

✗ Latest tags can break builds

FROM node:latest FROM node:20-alpine
undefined
FROM node:latest FROM node:20-alpine
undefined

Use COPY Instead of ADD

使用 COPY 而非 ADD

dockerfile
undefined
dockerfile
undefined

✓ COPY is explicit and preferred

✓ COPY is explicit and preferred

COPY package.json .
COPY package.json .

✗ ADD has extra features rarely needed

✗ ADD has extra features rarely needed

ADD package.json . # Only use for URLs or tar extraction
undefined
ADD package.json . # Only use for URLs or tar extraction
undefined

Combine RUN Commands

合并 RUN 命令

dockerfile
undefined
dockerfile
undefined

✓ Single layer, smaller image

✓ Single layer, smaller image

RUN apt-get update &&
apt-get install -y package1 package2 &&
rm -rf /var/lib/apt/lists/*
RUN apt-get update &&
apt-get install -y package1 package2 &&
rm -rf /var/lib/apt/lists/*

✗ Multiple layers, larger image

✗ Multiple layers, larger image

RUN apt-get update RUN apt-get install -y package1 RUN apt-get install -y package2
undefined
RUN apt-get update RUN apt-get install -y package1 RUN apt-get install -y package2
undefined

Debugging

调试方法

Inspect Image Layers

检查镜像层

bash
undefined
bash
undefined

View layer history

View layer history

docker history image-name
docker history image-name

Analyze image with dive

Analyze image with dive

docker run --rm -it
-v /var/run/docker.sock:/var/run/docker.sock
wagoodman/dive:latest image-name
undefined
docker run --rm -it
-v /var/run/docker.sock:/var/run/docker.sock
wagoodman/dive:latest image-name
undefined

Build with Progress

带进度信息构建

bash
undefined
bash
undefined

Detailed build output

Detailed build output

docker build --progress=plain -t myapp .
docker build --progress=plain -t myapp .

Build specific stage

Build specific stage

docker build --target builder -t myapp:builder .
undefined
docker build --target builder -t myapp:builder .
undefined

Best Practices

最佳实践

  1. Use multi-stage builds: Separate build and runtime environments
  2. Order layers by change frequency: Maximize cache hits
  3. Use .dockerignore: Exclude unnecessary files
  4. Run as non-root: Always create and use a non-root user
  5. Pin base image versions: Ensure reproducible builds
  6. Clean up in same layer: Reduce image size
  7. Add health checks: Enable container orchestration
  8. Scan for vulnerabilities: Use Trivy, Snyk, or similar
  9. Use slim/alpine bases: Minimize attack surface
  10. Don't store secrets: Use runtime injection
  1. 使用多阶段构建:分离构建与运行环境
  2. 按变更频率排序层:最大化缓存命中率
  3. 配置.dockerignore:排除不必要的文件
  4. 以非root用户运行:始终创建并使用非root用户
  5. 固定基础镜像版本:确保构建可复现
  6. 在同一层中清理:减小镜像体积
  7. 添加健康检查:支持容器编排
  8. 扫描漏洞:使用Trivy、Snyk等工具
  9. 使用轻量/Alpine基础镜像:最小化攻击面
  10. 不存储敏感信息:使用运行时注入方式

Output Checklist

输出检查清单

Every optimized Dockerfile should include:
  • Multi-stage build separating build and runtime
  • Slim or Alpine base image
  • Pinned base image version
  • Layer caching optimization (deps before source)
  • Non-root user configuration
  • Health check defined
  • .dockerignore file
  • No secrets in image
  • Minimal installed packages
  • Cleanup in same layer as install
  • Labels for metadata
  • Security scanning in CI
每个优化后的Dockerfile应包含:
  • 分离构建与运行环境的多阶段构建
  • 轻量或Alpine基础镜像
  • 固定版本的基础镜像
  • 层缓存优化(依赖文件在源代码之前)
  • 非root用户配置
  • 定义健康检查
  • .dockerignore文件
  • 镜像中无敏感信息
  • 最小化安装的包
  • 安装与清理在同一层
  • 元数据标签
  • CI中的安全扫描