上一篇 下一篇 分享链接 返回 返回顶部

Docker 跑得慢?从镜像到资源限制的性能优化实战指南

发布人:慈云数据-客服中心 发布时间:20小时前 阅读量:3

Docker 性能优化教程|附源码

在现代软件开发与运维体系中,Docker 已经成为应用交付、环境隔离、持续集成和微服务部署的重要基础设施。相比传统虚拟机,Docker 容器启动更快、资源占用更低、部署更灵活,但这并不意味着 Docker 天然就是“高性能”的。

在实际生产环境中,如果镜像构建不合理、容器资源限制不清晰、存储驱动选择不当、日志无限增长、网络模式使用不当,Docker 依然可能出现 CPU 飙高、内存泄漏、磁盘 IO 变慢、镜像体积巨大、容器启动缓慢、应用响应延迟升高 等问题。

本文将系统介绍 Docker 性能优化的核心思路,并提供可直接参考的 Dockerfile、docker-compose、Shell 脚本和配置示例,帮助你从镜像、容器、资源、网络、存储、日志、监控等多个维度优化 Docker 运行效率。


一、Docker 性能优化的核心目标

Docker 性能优化并不是单纯追求某一个指标的极限,而是让容器在稳定、安全、可维护的前提下获得更好的运行效率。

常见优化目标包括:

  1. 减少镜像体积

    • 加快镜像拉取速度;
    • 减少磁盘占用;
    • 提升 CI/CD 构建效率。
  2. 缩短容器启动时间

    • 更快完成服务扩缩容;
    • 提升故障恢复速度。
  3. 降低 CPU 和内存占用

    • 提高宿主机资源利用率;
    • 避免某个容器拖垮整个服务器。
  4. 优化磁盘 IO

    • 降低日志、缓存、数据库写入导致的性能损耗;
    • 减少 Docker 存储层压力。
  5. 优化网络性能

    • 减少容器间通信延迟;
    • 提高高并发场景下的吞吐能力。
  6. 提升可观测性

    • 及时发现资源瓶颈;
    • 为后续调优提供数据依据。

二、优化镜像构建

镜像优化是 Docker 性能优化中最基础、最重要的一步。一个臃肿的镜像不仅会占用大量磁盘空间,还会导致构建、推送、拉取和启动变慢。


三、选择更小的基础镜像

很多初学者在编写 Dockerfile 时喜欢使用完整系统镜像,例如:

FROM ubuntu:22.04

这种镜像通用性较好,但体积通常较大。如果应用不依赖完整系统环境,可以使用更轻量的镜像。

例如 Node.js 应用可以使用:

FROM node:20-alpine

Go 应用可以使用:

FROM alpine:3.20

甚至对于静态编译后的 Go 程序,可以使用 scratch

FROM scratch
COPY app /app
ENTRYPOINT ["/app"]

alpine 镜像通常只有几 MB,远小于 Ubuntu、Debian 等完整发行版镜像。不过需要注意,Alpine 使用的是 musl libc,在某些依赖 glibc 的应用中可能存在兼容性问题。


四、使用多阶段构建减少镜像体积

多阶段构建是 Dockerfile 优化中非常推荐的方式。它可以把“构建环境”和“运行环境”分离,最终镜像只保留运行所需文件。

下面以 Go 应用为例。

1. 示例项目结构

docker-performance-demo/
├── Dockerfile
├── go.mod
└── main.go

2. main.go 源码

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "runtime"
)

func healthHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    _, _ = w.Write([]byte("ok"))
}

func infoHandler(w http.ResponseWriter, r *http.Request) {
    hostname, _ := os.Hostname()

    msg := fmt.Sprintf(
        "hostname=%s\nos=%s\narch=%s\ncpu=%d\n",
        hostname,
        runtime.GOOS,
        runtime.GOARCH,
        runtime.NumCPU(),
    )

    w.WriteHeader(http.StatusOK)
    _, _ = w.Write([]byte(msg))
}

func main() {
    http.HandleFunc("/health", healthHandler)
    http.HandleFunc("/info", infoHandler)

    port := os.Getenv("APP_PORT")
    if port == "" {
        port = "8080"
    }

    log.Printf("server started at :%s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatal(err)
    }
}

3. go.mod 源码

module docker-performance-demo

go 1.22

4. 未优化 Dockerfile

FROM golang:1.22

WORKDIR /app

COPY . .

RUN go build -o server .

EXPOSE 8080

CMD ["./server"]

这个镜像包含完整 Go 编译环境,体积较大,不适合生产环境。

5. 优化后的多阶段 Dockerfile

# 第一阶段:构建阶段
FROM golang:1.22-alpine AS builder

WORKDIR /src

COPY go.mod ./
RUN go mod download

COPY . .

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
    -ldflags="-s -w" \
    -o server .

# 第二阶段:运行阶段
FROM alpine:3.20

WORKDIR /app

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

COPY --from=builder /src/server /app/server

USER appuser

EXPOSE 8080

ENTRYPOINT ["/app/server"]

这里的优化点包括:

  • 使用 golang:alpine 缩小构建镜像;
  • 使用多阶段构建,最终镜像不包含编译工具链;
  • 使用 -ldflags="-s -w" 减小 Go 二进制体积;
  • 使用非 root 用户运行应用,兼顾安全与稳定;
  • 仅复制最终产物,避免无关文件进入镜像。

五、合理利用 Docker 构建缓存

Docker 构建镜像时会按层缓存。如果 Dockerfile 编写不合理,每次修改业务代码都会导致依赖重新下载,严重影响构建速度。

不推荐写法:

COPY . .
RUN go mod download
RUN go build -o server .

推荐写法:

COPY go.mod ./
RUN go mod download

COPY . .
RUN go build -o server .

这样当业务代码变化但依赖文件未变化时,go mod download 这一层可以复用缓存。

对于 Node.js 项目也是类似:

FROM node:20-alpine AS builder

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci --omit=dev

COPY . .

CMD ["node", "server.js"]

优化原则是:先复制变化少的文件,再复制变化频繁的文件。


六、使用 .dockerignore 减少构建上下文

很多项目在构建镜像时,会把 .git、日志文件、缓存目录、测试报告等无关内容发送给 Docker Daemon,导致构建速度变慢。

推荐在项目根目录添加 .dockerignore

.git
.gitignore
Dockerfile
docker-compose.yml
*.log
tmp
.cache
node_modules
dist
coverage
.idea
.vscode
.env

注意:是否忽略 distnode_modules 需要根据项目实际构建方式决定。如果你的构建产物需要复制进镜像,就不要忽略对应目录。


七、控制容器 CPU 资源

如果不限制容器 CPU,一个异常容器可能会占满宿主机资源,影响其他服务。Docker 提供了多种 CPU 限制方式。

1. 使用 docker run 限制 CPU

docker run -d \
  --name demo-app \
  --cpus="1.5" \
  -p 8080:8080 \
  docker-performance-demo:latest

表示该容器最多使用 1.5 个 CPU 核心。

也可以使用 CPU shares 设置相对权重:

docker run -d \
  --name demo-app \
  --cpu-shares=512 \
  -p 8080:8080 \
  docker-performance-demo:latest

默认值通常是 1024。cpu-shares=512 表示在 CPU 竞争时,该容器获得约一半权重。

2. docker-compose 中限制 CPU

services:
  demo-app:
    image: docker-performance-demo:latest
    container_name: demo-app
    ports:
      - "8080:8080"
    deploy:
      resources:
        limits:
          cpus: "1.5"
        reservations:
          cpus: "0.5"

需要注意,在非 Swarm 模式下,不同版本的 Compose 对 deploy.resources 支持有所差异。更通用的方式可以使用:

services:
  demo-app:
    image: docker-performance-demo:latest
    container_name: demo-app
    ports:
      - "8080:8080"
    cpus: 1.5

八、控制容器内存资源

内存限制同样重要。如果容器没有内存上限,应用内存泄漏可能拖垮宿主机。

1. docker run 限制内存

docker run -d \
  --name demo-app \
  --memory=512m \
  --memory-swap=512m \
  -p 8080:8080 \
  docker-performance-demo:latest

参数说明:

  • --memory=512m:限制容器最多使用 512MB 内存;
  • --memory-swap=512m:限制内存加 swap 总量为 512MB,即基本不允许额外使用 swap。

如果允许使用 swap,可以设置更高:

--memory=512m --memory-swap=1g

2. 避免 Java 应用忽略容器内存限制

Java 应用在容器中运行时,需要确保 JVM 能正确感知容器资源。现代 JDK 已经支持容器感知,但仍建议显式设置:

docker run -d \
  --name java-app \
  --memory=1g \
  -e JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0" \
  java-app:latest

这样 JVM 最大堆内存约为容器内存的 75%,避免堆外内存、线程栈、Metaspace 等导致 OOM。


九、优化容器日志

Docker 默认日志驱动通常是 json-file。如果不限制日志大小,容器长时间运行后日志文件可能非常大,导致磁盘空间耗尽、IO 性能下降。

1. docker run 设置日志限制

docker run -d \
  --name demo-app \
  --log-driver=json-file \
  --log-opt max-size=100m \
  --log-opt max-file=3 \
  -p 8080:8080 \
  docker-performance-demo:latest

表示单个日志文件最大 100MB,最多保留 3 个文件。

2. docker-compose 设置日志限制

services:
  demo-app:
    image: docker-performance-demo:latest
    ports:
      - "8080:8080"
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "3"

3. Docker Daemon 全局日志配置

可以修改 /etc/docker/daemon.json

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

修改后重启 Docker:

sudo systemctl restart docker

生产环境中,建议将日志采集到 ELK、Loki、ClickHouse、云日志服务等系统,不建议长期依赖宿主机本地日志文件。


十、优化存储性能

Docker 的镜像和容器写入层通常不适合承载高频写入业务数据。数据库、消息队列、搜索引擎等有大量磁盘 IO 的服务,应优先使用 volume 或绑定宿主机目录。

1. 使用 volume 保存数据

docker volume create mysql-data

docker run -d \
  --name mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

2. docker-compose 中使用 volume

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
      MYSQL_DATABASE: "demo"
    volumes:
      - mysql-data:/var/lib/mysql
    ports:
      - "3306:3306"

volumes:
  mysql-data:

3. 避免把高频写入放在容器层

不推荐:

docker run -d mysql:8.0

这样数据库数据会写入容器可写层,容器删除后数据也容易丢失,并且性能和可维护性都较差。

推荐:

docker run -d \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

十一、选择合适的存储驱动

在 Linux 环境下,Docker 常见存储驱动包括 overlay2aufsdevicemapper 等。当前大多数生产环境推荐使用 overlay2

查看当前存储驱动:

docker info | grep "Storage Driver"

如果显示:

Storage Driver: overlay2

通常就是比较理想的状态。

overlay2 优点包括:

  • 性能较好;
  • 稳定性高;
  • 支持广泛;
  • 适合现代 Linux 内核。

如果你的环境仍在使用旧驱动,建议评估迁移。但迁移存储驱动可能影响现有镜像和容器,生产环境需要提前备份并安排维护窗口。


十二、网络性能优化

Docker 默认 bridge 网络适合大多数单机部署场景,但在极致性能需求下,需要根据业务场景选择更合适的网络模式。

1. bridge 网络

默认模式,隔离性较好,适合普通服务:

docker run -d \
  --name demo-app \
  -p 8080:8080 \
  docker-performance-demo:latest

2. host 网络

容器直接使用宿主机网络命名空间,网络性能更好,减少 NAT 开销,但隔离性降低。

docker run -d \
  --name demo-app \
  --network host \
  docker-performance-demo:latest

使用 host 网络后,应用监听的端口就是宿主机端口,不需要 -p 映射。

适用场景:

  • 高性能网关;
  • 高并发代理;
  • 对网络延迟极其敏感的服务;
  • 监控 Agent。

不适用场景:

  • 多个容器需要监听相同端口;
  • 对网络隔离要求较高;
  • 需要复杂端口映射的场景。

3. 自定义 bridge 网络

相比默认 bridge,自定义 bridge 支持容器名 DNS 解析,适合服务间通信:

docker network create app-net

docker run -d \
  --name app \
  --network app-net \
  docker-performance-demo:latest

十三、优化 Docker Compose 部署

下面提供一个较完整的 docker-compose.yml 示例,包含资源限制、日志限制、健康检查、网络和 volume。

version: "3.9"

services:
  demo-app:
    build:
      context: .
      dockerfile: Dockerfile
    image: docker-performance-demo:latest
    container_name: demo-app
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      APP_PORT: "8080"
    cpus: 1.5
    mem_limit: 512m
    memswap_limit: 512m
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "3"
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 10s
    networks:
      - app-net

networks:
  app-net:
    driver: bridge

如果基础镜像中没有 wget,健康检查会失败。可以改用 curl,或者在镜像中安装对应工具。对于极简镜像,也可以直接在应用内部提供轻量检测接口,并使用专门的探针工具。


十四、使用健康检查提升稳定性

健康检查可以帮助 Docker 或编排系统判断应用是否正常运行。需要注意,健康检查不是越频繁越好,过高频率会增加应用压力。

Dockerfile 中也可以添加:

HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost:8080/health || exit 1

优化建议:

  • 健康检查接口应尽量轻量;
  • 不要在健康检查中执行复杂数据库查询;
  • 检查频率应根据服务重要性和负载情况设置;
  • 对启动慢的应用设置合理的 start_period

十五、减少容器内不必要进程

容器最佳实践是:一个容器运行一个主进程

不推荐在一个容器中同时运行:

  • Nginx;
  • 后端应用;
  • 定时任务;
  • 日志采集;
  • 数据库。

这样会导致容器难以监控、扩缩容和故障恢复。更推荐的方式是拆分为多个容器,通过 Docker Compose 或 Kubernetes 编排。

如果确实需要多进程,建议使用 tini 或专业进程管理工具,避免僵尸进程。

示例:

FROM alpine:3.20

RUN apk add --no-cache tini

ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/app/server"]

十六、清理无用资源

长期运行 Docker 的服务器会积累大量无用镜像、停止的容器、悬空层、无用 volume 和构建缓存。

查看磁盘占用:

docker system df

清理停止容器、无用网络、悬空镜像和构建缓存:

docker system prune

清理所有未使用镜像:

docker system prune -a

清理未使用 volume:

docker volume prune

生产环境慎用:

docker system prune -a --volumes

因为它可能删除未使用但仍有价值的数据卷。建议在清理前确认:

docker volume ls
docker ps -a
docker images

十七、自动清理脚本源码

下面提供一个相对安全的 Docker 清理脚本,会展示空间占用,并要求用户确认。

docker-clean.sh

#!/usr/bin/env bash

set -e

echo "=============================="
echo " Docker Disk Usage"
echo "=============================="
docker system df

echo
echo "This script will clean:"
echo "1. stopped containers"
echo "2. dangling images"
echo "3. unused networks"
echo "4. build cache"
echo
echo "It will NOT remove volumes by default."
echo

read -r -p "Continue? [y/N] " confirm

if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
  echo "Canceled."
  exit 0
fi

echo
echo "Cleaning stopped containers..."
docker container prune -f

echo
echo "Cleaning dangling images..."
docker image prune -f

echo
echo "Cleaning unused networks..."
docker network prune -f

echo
echo "Cleaning build cache..."
docker builder prune -f

echo
echo "=============================="
echo " Docker Disk Usage After Clean"
echo "=============================="
docker system df

echo "Done."

赋予执行权限:

chmod +x docker-clean.sh

执行:

./docker-clean.sh

十八、监控容器性能

没有监控就没有优化。Docker 自带了一些基础命令,可以快速查看容器资源使用情况。

1. 查看实时资源占用

docker stats

输出通常包括:

CONTAINER ID   NAME       CPU %   MEM USAGE / LIMIT   MEM %   NET I/O       BLOCK I/O

如果某个容器 CPU 长期过高,可能存在:

  • 死循环;
  • 请求量过大;
  • 线程池配置不合理;
  • GC 频繁;
  • 数据库慢查询;
  • 日志打印过多。

如果内存持续增长,可能存在:

  • 内存泄漏;
  • 缓存无上限;
  • goroutine/thread 泄漏;
  • 大对象未释放;
  • 连接池配置不合理。

2. 查看容器进程

docker top demo-app

3. 查看容器详细信息

docker inspect demo-app

4. 查看容器日志

docker logs --tail=100 demo-app

持续观察:

docker logs -f --tail=100 demo-app

十九、压测验证优化效果

优化不能只凭感觉,需要通过压测数据验证。可以使用 wrkabhey 等工具。

hey 为例:

hey -n 10000 -c 100 http://127.0.0.1:8080/info

参数说明:

  • -n 10000:总请求数 10000;
  • -c 100:并发数 100。

如果使用 wrk

wrk -t4 -c200 -d30s http://127.0.0.1:8080/info

压测时建议关注:

  • QPS;
  • P95/P99 延迟;
  • CPU 使用率;
  • 内存使用率;
  • 网络吞吐;
  • 磁盘 IO;
  • 错误率。

不要只看平均响应时间。平均值可能掩盖长尾延迟,生产环境更应该关注 P95、P99。


二十、Docker Daemon 优化配置

Docker Daemon 的全局配置文件通常位于:

/etc/docker/daemon.json

一个常见的优化配置如下:

{
  "storage-driver": "overlay2",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "features": {
    "buildkit": true
  },
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65535,
      "Soft": 65535
    }
  }
}

配置说明:

  • storage-driver:指定存储驱动;
  • log-driver:指定默认日志驱动;
  • log-opts:限制日志大小;
  • buildkit:启用 BuildKit,提高构建性能;
  • default-ulimits.nofile:提高文件描述符限制,适合高并发服务。

修改配置后重启 Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker

检查配置是否生效:

docker info

二十一、启用 BuildKit 加速构建

BuildKit 是 Docker 新一代构建后端,支持更高效的缓存、更好的并发构建能力和更安全的 secret 挂载方式。

临时启用:

DOCKER_BUILDKIT=1 docker build -t docker-performance-demo:latest .

长期启用可以在 daemon.json 中配置:

{
  "features": {
    "buildkit": true
  }
}

BuildKit 还支持缓存挂载,例如 Go 项目:

# syntax=docker/dockerfile:1.7

FROM golang:1.22-alpine AS builder

WORKDIR /src

COPY go.mod ./

RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .

RUN --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
    -ldflags="-s -w" \
    -o server .

FROM alpine:3.20

WORKDIR /app

COPY --from=builder /src/server /app/server

EXPOSE 8080

ENTRYPOINT ["/app/server"]

这种方式可以明显提升 Go 项目的重复构建速度。


二十二、生产环境 Docker 性能优化清单

下面给出一份实用检查清单:

  • [ ] 使用轻量基础镜像,例如 Alpine、distroless、scratch;
  • [ ] 使用多阶段构建;
  • [ ] 配置 .dockerignore
  • [ ] 合理利用构建缓存;
  • [ ] 启用 BuildKit;
  • [ ] 使用非 root 用户运行容器;
  • [ ] 设置 CPU 限制;
  • [ ] 设置内存限制;
  • [ ] 配置日志大小和保留数量;
  • [ ] 数据库等高 IO 服务使用 volume;
  • [ ] 避免高频写入容器可写层;
  • [ ] 使用 overlay2 存储驱动;
  • [ ] 根据场景选择 bridge、host 或自定义网络;
  • [ ] 配置健康检查;
  • [ ] 设置合理的 restart 策略;
  • [ ] 定期清理无用镜像和缓存;
  • [ ] 使用 docker stats 或监控系统观察资源;
  • [ ] 压测验证优化效果;
  • [ ] 关注 P95/P99 延迟,而不只看平均值;
  • [ ] 生产环境谨慎执行 docker system prune -a --volumes

二十三、完整源码汇总

1. main.go

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "runtime"
)

func healthHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    _, _ = w.Write([]byte("ok"))
}

func infoHandler(w http.ResponseWriter, r *http.Request) {
    hostname, _ := os.Hostname()

    msg := fmt.Sprintf(
        "hostname=%s\nos=%s\narch=%s\ncpu=%d\n",
        hostname,
        runtime.GOOS,
        runtime.GOARCH,
        runtime.NumCPU(),
    )

    w.WriteHeader(http.StatusOK)
    _, _ = w.Write([]byte(msg))
}

func main() {
    http.HandleFunc("/health", healthHandler)
    http.HandleFunc("/info", infoHandler)

    port := os.Getenv("APP_PORT")
    if port == "" {
        port = "8080"
    }

    log.Printf("server started at :%s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatal(err)
    }
}

2. go.mod

module docker-performance-demo

go 1.22

3. Dockerfile

# syntax=docker/dockerfile:1.7

FROM golang:1.22-alpine AS builder

WORKDIR /src

COPY go.mod ./

RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .

RUN --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
    -ldflags="-s -w" \
    -o server .

FROM alpine:3.20

WORKDIR /app

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

COPY --from=builder /src/server /app/server

USER appuser

EXPOSE 8080

HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost:8080/health || exit 1

ENTRYPOINT ["/app/server"]

4. .dockerignore

.git
.gitignore
*.log
tmp
.cache
coverage
.idea
.vscode
.env

5. docker-compose.yml

version: "3.9"

services:
  demo-app:
    build:
      context: .
      dockerfile: Dockerfile
    image: docker-performance-demo:latest
    container_name: demo-app
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      APP_PORT: "8080"
    cpus: 1.5
    mem_limit: 512m
    memswap_limit: 512m
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "3"
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 10s
    networks:
      - app-net

networks:
  app-net:
    driver: bridge

6. docker-clean.sh

#!/usr/bin/env bash

set -e

echo "=============================="
echo " Docker Disk Usage"
echo "=============================="
docker system df

echo
echo "This script will clean stopped containers, dangling images,"
echo "unused networks and build cache."
echo "Volumes will not be removed."
echo

read -r -p "Continue? [y/N] " confirm

if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
  echo "Canceled."
  exit 0
fi

docker container prune -f
docker image prune -f
docker network prune -f
docker builder prune -f

echo
echo "=============================="
echo " Docker Disk Usage After Clean"
echo "=============================="
docker system df

echo "Done."

二十四、总结

Docker 性能优化是一项系统工程,不能只关注某个单点。镜像体积、构建缓存、运行资源、日志策略、存储方式、网络模式、健康检查、监控压测都会影响最终表现。

对于大多数项目,可以优先从以下几个方面入手:

  1. 使用多阶段构建和轻量基础镜像;
  2. 添加 .dockerignore,减少构建上下文;
  3. 启用 BuildKit,提高构建速度;
  4. 为容器设置 CPU 和内存限制;
  5. 限制 Docker 日志文件大小;
  6. 使用 volume 保存高频写入数据;
  7. 定期清理无用资源;
  8. 通过 docker stats 和压测工具验证优化效果。

真正有效的优化一定建立在数据之上。建议在每次调整前后记录镜像大小、启动时间、CPU、内存、QPS、P95/P99 延迟等指标,避免盲目调参。只有持续观测、持续验证、持续迭代,才能让 Docker 在生产环境中稳定、高效地运行。

目录结构
全文