Docker 镜像优化完全指南:从一次"800GB registry 镜像 2.8GB 拉取 15 分钟半夜卡死"看懂为什么写 Dockerfile 远远不够

2022 年我接手一个微服务项目 20 个服务全用 Docker 打包 Kubernetes 部署第一版我让团队各自写 Dockerfile 没人管标准三个月后整个 registry 占用 800GB 平均每个镜像 2.5GB 一次集群 rolling update 拉镜像要 15 分钟上线一次提心吊胆半夜还卡死过两次然后我们陆续踩了一堆坑第一种最让我傻眼一个 Spring Boot 服务镜像 2.8GB 拆开看 base image ubuntu:22.04 800MB JDK 装了完整版 600MB 各种调试工具 vim curl jq net-tools 300MB Maven 缓存 500MB 真正业务代码就 50MB 第二种最难缠我们 Dockerfile 把 COPY . /app 放最前面每次代码改一行整个镜像重新构建缓存全失效 build 一次 8 分钟第三种最离谱一个 Python 服务装 numpy pandas torch 镜像 5GB 拆开发现 .pyc 文件缓存测试目录文档全打进去了还有 50MB 的 cuda lib 我们根本用不上第四种最致命我们镜像里塞了 .env 文件包含数据库密码一个开发把镜像 push 到 Docker Hub public registry 第二天被人扫到密码数据库被人删库第五种最莫名其妙我们用 alpine base 镜像理论上最小但 Python 服务跑起来比 Debian 慢 30% 后来发现 alpine 用的 musl libc 与 glibc 不兼容性能差改回 debian:slim 立马回来我盯着这一连串问题想了很久才彻底想明白第一版错在一个根本的认知上我以为 Dockerfile 就是把代码塞进容器装好依赖就行可这个认知是错的真正能投产的 Docker 镜像是一个多阶段构建加 base 镜像选择加 layer 缓存策略加 .dockerignore 加安全扫描加 size 优化的整套工程方法论

2022 年我接手一个微服务项目 20 个服务全用 Docker 打包 Kubernetes 部署。第一版我让团队各自写 Dockerfile 没人管标准 三个月后整个 registry 占用 800GB 平均每个镜像 2.5GB 一次集群 rolling update 拉镜像要 15 分钟 上线一次提心吊胆 半夜还卡死过两次。然后我们陆续踩了一堆坑。第一种最让我傻眼 一个 Spring Boot 服务镜像 2.8GB 拆开看 base image ubuntu:22.04 800MB JDK 装了完整版 600MB 各种调试工具 vim curl jq net-tools 300MB Maven 缓存 500MB 真正业务代码就 50MB。第二种最难缠 我们 Dockerfile 把 COPY . /app 放最前面 每次代码改一行整个镜像重新构建 缓存全失效 build 一次 8 分钟。第三种最离谱 一个 Python 服务装 numpy pandas torch 镜像 5GB 拆开发现 .pyc 文件 缓存 测试目录 文档全打进去了 还有 50MB 的 cuda lib 我们根本用不上。第四种最致命 我们镜像里塞了 .env 文件包含数据库密码 一个开发把镜像 push 到 Docker Hub public registry 第二天被人扫到密码 数据库被人删库。第五种最莫名其妙 我们用 alpine base 镜像理论上最小 但 Python 服务跑起来比 Debian 慢 30% 后来发现 alpine 用的 musl libc 与 glibc 不兼容 性能差 改回 debian:slim 立马回来。我盯着这一连串问题想了很久才彻底想明白第一版错在一个根本的认知上我以为 Dockerfile 就是把代码塞进容器 装好依赖就行 可这个认知是错的真正能投产的 Docker 镜像是一个 多阶段构建 加 base 镜像选择 加 layer 缓存策略 加 .dockerignore 加 安全扫描 加 size 优化 的整套工程方法论 任何一环没做都可能让你的镜像膨胀部署变慢甚至泄密本文从头梳理 Docker 镜像优化的工程要点 base 怎么选 多阶段怎么写 layer 怎么排 安全怎么扫 size 怎么压 以及一些把 Docker 用扎实要避开的工程坑

问题背景:为什么默认 Dockerfile 是地雷

Docker 上手简单 写个 Dockerfile FROM 一下 COPY 一下 RUN 装下依赖就能跑起来。但这个简单背后藏着无数地雷 base 镜像选错 一个服务 2GB layer 顺序写错 缓存失效一次构建 10 分钟 把整个 .git 目录打进去镜像被人 git log 看到内部代码。问题的根源在于:

  • base 镜像决定底子:ubuntu 800MB debian:slim 80MB alpine 5MB distroless 2MB 差 400 倍 还涉及兼容性。
  • layer 顺序决定缓存命中:常变的放下面 不变的放上面 反了缓存全失效。
  • 多阶段构建是减肥关键:build 阶段装编译工具 final 阶段只留 binary 镜像可以从 1GB 降到 50MB。
  • .dockerignore 是必备:不写它整个 .git node_modules 都进镜像 不仅大还有泄密风险。
  • 安全扫描必须做:trivy clair 扫 CVE 不扫的镜像可能带高危漏洞被攻击。
  • distroless 与非 root 是底线:生产容器不应该有 shell 不应该 root 跑 攻击面要最小化。

一 base 镜像选择:从 800MB 到 80MB

base 镜像选错 后面优化再多也是徒劳。下面是几种常见 base 的实测对比 选择时要看你的服务类型 编译型语言(Go Rust C++)首选 distroless 解释型语言(Python Node Ruby)首选 debian:slim 或 alpine 但 alpine 有兼容性坑要小心。

# 1 base 镜像对比 实测大小 仅 base 不含 app
# +----------------------------+--------+----------------------+
# | Image                      | Size   | 适用场景             |
# +----------------------------+--------+----------------------+
# | ubuntu:22.04               | 800MB  | 别用 太大            |
# | debian:12                  | 350MB  | 别用 太大            |
# | debian:12-slim             | 80MB   | 推荐 Python Node     |
# | alpine:3.19                | 5MB    | 静态二进制 Go Rust   |
# | gcr.io/distroless/static   | 2MB    | Go 静态二进制最佳    |
# | gcr.io/distroless/python3  | 50MB   | Python 生产推荐      |
# | scratch                    | 0B     | 极致优化 Go          |
# +----------------------------+--------+----------------------+

# 2 Go 服务 用 scratch 终极优化
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 静态编译 关键 不依赖 libc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /app/server ./cmd/server

FROM scratch
# 必须从 builder 拷 ca-certificates 否则 HTTPS 不能用
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/server /server
# 必须从 builder 拷 timezone 数据 否则时区不对
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
EXPOSE 8080
ENTRYPOINT ["/server"]
# 最终镜像 12MB

# 3 Python 服务 用 distroless 生产推荐
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
COPY . .

FROM gcr.io/distroless/python3-debian12
WORKDIR /app
# 注意 distroless 用户是 nonroot 不是 root
COPY --from=builder --chown=nonroot:nonroot /root/.local /home/nonroot/.local
COPY --from=builder --chown=nonroot:nonroot /app /app
ENV PYTHONPATH=/home/nonroot/.local/lib/python3.11/site-packages
USER nonroot
EXPOSE 8000
ENTRYPOINT ["python", "main.py"]
# 最终镜像 180MB(含 Python + 依赖)

alpine 的兼容性坑要特别注意 它用 musl libc 不是 glibc 跑 Python 装包要重新编译耗时长 跑 Node 某些 native 模块(node-canvas sqlite3)直接不工作 跑 Java 性能差 20% 跑 Go 没问题。Python 与 Node 服务建议直接 debian:slim 或 distroless 别去 alpine 折腾。

二 多阶段构建:把 1GB 降到 50MB

多阶段构建(multi-stage build)是 Docker 镜像优化最强大的武器。原理简单 build 阶段你可以用 800MB 的镜像装编译工具下载依赖编译代码 但最终 final 阶段只 COPY 你需要的产物到一个干净的 base 镜像。下面是几种常见语言的多阶段范例。

# 1 Node.js 多阶段
FROM node:20 AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci  # 包含 devDependencies 编译用
COPY . .
RUN npm run build

FROM node:20-slim AS runner
WORKDIR /app
# 只拷 production 依赖
COPY --from=deps /app/node_modules ./node_modules
# 只拷编译后产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]
# 从 1.5GB 降到 200MB

# 2 Java Spring Boot 多阶段
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
# 依赖单独一层 利用缓存
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn clean package -DskipTests

FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
# layered jar 解压后多层 不要一坨 jar 拷过去
RUN mkdir -p target/dependency
COPY --from=builder /app/target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
# 按层拷贝 缓存命中更高
COPY --from=builder /app/target/dependency/BOOT-INF/lib /app/lib
COPY --from=builder /app/target/dependency/META-INF /app/META-INF
COPY --from=builder /app/target/dependency/BOOT-INF/classes /app
EXPOSE 8080
ENTRYPOINT ["java", "-cp", "/app:/app/lib/*", "com.example.Application"]
# 从 2.8GB 降到 350MB

# 3 Rust 多阶段
FROM rust:1.75 AS builder
WORKDIR /app
# 先 copy Cargo.toml 装依赖 单独层
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main(){}" > src/main.rs
RUN cargo build --release
RUN rm -rf src target/release/deps/myapp*
# 然后再 COPY 真实代码
COPY src ./src
RUN cargo build --release

FROM gcr.io/distroless/cc-debian12
COPY --from=builder /app/target/release/myapp /myapp
EXPOSE 8080
ENTRYPOINT ["/myapp"]
# 最终 15MB

多阶段构建的核心思路就是 builder 阶段重 final 阶段轻 final 只拷必要的产物。Java 项目要特别注意用 layered jar 不要一坨 fat jar 否则 jar 一改全部缓存失效 用了 layered jar 改业务代码只重新拉最小那层。

三 layer 缓存策略:从 8 分钟到 30 秒

Docker 镜像是分层的 每条指令一层 上层基于下层 如果某一层变了 它以下所有层缓存都失效。所以 layer 顺序非常重要 不变的放上面 常变的放下面 否则每次构建都是 cache miss。下面是几个高频踩坑的对比。

# 1 错误写法 缓存几乎不命中
FROM node:20-slim
WORKDIR /app
COPY . .                    # 任何一行代码改就失效
RUN npm ci                  # 每次都重新装依赖 浪费 5 分钟
CMD ["node", "index.js"]

# 2 正确写法 缓存最大化
FROM node:20-slim
WORKDIR /app
# 先 COPY 不常变的 package.json
COPY package*.json ./
# 装依赖单独一层 package.json 不变就不重装
RUN npm ci --only=production
# 后 COPY 经常变的源码
COPY . .
CMD ["node", "index.js"]

# 3 Python 同理
FROM python:3.11-slim
WORKDIR /app
# requirements.txt 不变就不重装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 源码后 COPY
COPY . .
CMD ["python", "main.py"]

除了 COPY 顺序之外 另一个高频踩坑是 RUN 指令的写法。一个 apt-get 拆成多条 RUN layer 翻倍 镜像也大;不删 apt cache 又会留 100MB 垃圾。再进一步 BuildKit 的 cache mount 可以让 pip apt npm 等包管理器的 cache 跨构建复用 build 速度再翻一倍。下面是这两个高级技巧的标准写法。

# 4 layer 合并减少层数
# 错误 每个 RUN 一层 layer 多还占空间
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y jq
RUN rm -rf /var/lib/apt/lists/*

# 正确 一个 RUN 完成 用 && 串
RUN apt-get update \
    && apt-get install -y --no-install-recommends curl jq \
    && rm -rf /var/lib/apt/lists/*

# 5 BuildKit cache mount 进一步加速
# syntax=docker/dockerfile:1
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt
COPY . .

# 6 BuildKit cache mount 配合 apt
RUN --mount=type=cache,target=/var/cache/apt \
    --mount=type=cache,target=/var/lib/apt \
    apt-get update && apt-get install -y curl jq

# 7 npm 同理
RUN --mount=type=cache,target=/root/.npm \
    npm ci --only=production

layer 缓存策略遵循一个原则:从最不常变到最常变。base 镜像不常变 在最上 系统包不常变 接着装 应用依赖中等频率 接着装 源码最常变 放最后。这样大部分构建只需要重新跑最后几层 时间从分钟级降到秒级。BuildKit 的 cache mount 还可以让 pip / npm / apt 的 cache 跨构建复用 加速更明显。

四 .dockerignore 与镜像内容审查

不写 .dockerignore 你的 .git 目录 node_modules 测试数据 IDE 配置全打进镜像 不仅镜像膨胀 还可能泄露源码或者密钥。.dockerignore 是必备 不是可选。

# .dockerignore 必备项 适用大多数项目
# 1 版本控制
.git
.gitignore
.gitattributes

# 2 IDE
.idea/
.vscode/
*.swp
.DS_Store

# 3 依赖 与缓存(Docker 内会重新装)
node_modules/
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/
target/
build/
dist/

# 4 测试与文档
tests/
test/
*.test.js
docs/
README.md
*.md

# 5 环境变量(密钥不能进镜像!)
.env
.env.local
.env.*.local
*.pem
*.key
secrets/

# 6 Docker 自己
Dockerfile
docker-compose*.yml
.dockerignore

# 7 CI/CD 配置
.github/
.gitlab-ci.yml
.circleci/

# 8 日志与临时文件
*.log
logs/
tmp/
temp/

# 检查镜像内容 看有没有不该有的东西
# docker image inspect myapp:latest --format='{{.RootFS.Layers}}'
# docker history myapp:latest --no-trunc
# 进入镜像 grep 密钥
# docker run --rm -it myapp:latest sh -c "grep -r 'password\|secret\|api_key' / 2>/dev/null"

除了 .dockerignore 还要定期审查镜像内容 用 dive 工具可以可视化看每一层增加了什么文件 经常能发现意外打进去的大文件。我们一次发现一个 50MB 的 .DS_Store 还有一个 200MB 的测试数据集 全是 .dockerignore 漏写导致的。

五 安全扫描与非 root 用户

镜像安全有两个关键 一是 CVE 扫描 base 镜像和依赖里的已知漏洞 二是非 root 运行 攻击成功后限制权限。生产环境这两项都不能省。

# 1 用 trivy 扫描镜像 CVE
trivy image myapp:latest

# 输出示例
# myapp:latest (debian 12.4)
# Total: 23 (HIGH: 3, CRITICAL: 1)
# Library  Vulnerability   Severity  Fixed Version
# libssl3  CVE-2024-1234   HIGH      3.0.13-1
# zlib1g   CVE-2024-5678   CRITICAL  1:1.2.13-2

# 2 严格模式 只允许 HIGH 以下
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest

# 3 CI/CD 集成 GitHub Actions
# - name: Scan image with Trivy
#   uses: aquasecurity/trivy-action@master
#   with:
#     image-ref: myapp:${{ github.sha }}
#     severity: 'CRITICAL,HIGH'
#     exit-code: '1'

# 4 hadolint 扫描 Dockerfile 静态检查
hadolint Dockerfile
# Dockerfile:5 DL3008 warning: Pin versions in apt get install
# Dockerfile:10 DL3009 info: Delete the apt-get lists after install
# Dockerfile:15 DL3025 warning: Use arguments JSON notation for CMD

# 5 docker scout 官方扫描 类似 trivy
docker scout cves myapp:latest
docker scout recommendations myapp:latest

非 root 运行是生产容器的底线 默认 Docker 容器是 root 跑 一旦应用被 RCE 攻击者拿到容器内 root 然后可能逃逸到宿主机。下面是非 root 配置的标准做法。

# 1 创建非 root 用户
FROM debian:12-slim
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --chown=appuser:appuser . /app
USER appuser
ENTRYPOINT ["./myapp"]

# 2 distroless 自带 nonroot 用户
FROM gcr.io/distroless/static:nonroot
COPY --chown=nonroot:nonroot myapp /myapp
USER nonroot
ENTRYPOINT ["/myapp"]

# 3 K8s 层面强制非 root
# pod spec
# securityContext:
#   runAsNonRoot: true
#   runAsUser: 1000
#   readOnlyRootFilesystem: true
#   allowPrivilegeEscalation: false
#   capabilities:
#     drop: ["ALL"]

# 4 验证容器内是否 root
docker run --rm myapp:latest id
# uid=1000(appuser) gid=1000(appuser) groups=1000(appuser)  正确
# uid=0(root)  错误 必须修

K8s 层面也要配合 SecurityContext runAsNonRoot=true readOnlyRootFilesystem=true 进一步限制容器权限。这两项在生产集群应该是默认必开。

[mermaid]
flowchart TD
A[源代码 + Dockerfile] --> B[hadolint 静态检查]
B --> C[BuildKit 多阶段构建]
C --> D[builder 阶段 编译 + 依赖]
D --> E[final 阶段 distroless + nonroot]
E --> F[trivy 安全扫描 CVE]
F --> G{CRITICAL/HIGH 漏洞}
G -->|有| Z[阻断 push]
G -->|无| H[push registry]
H --> I[K8s 拉取]
I --> J[SecurityContext nonroot + readonly]
J --> K[运行时容器]
K --> L[runtime 监控 Falco]

六 常见工程坑与最佳实践

除了前面五大主题 还有一些容易踩的坑值得单独说。Dockerfile 写不好 镜像不仅大还慢还可能挂。

# 1 不要把 secret 写进镜像
# 错误
ENV DATABASE_PASSWORD=mysecret123

# 正确 用 BuildKit secret mount
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=db_pass \
    cat /run/secrets/db_pass | psql ...

# 或者完全运行时注入 K8s Secret / env

# 2 HEALTHCHECK 必加
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# 3 ENTRYPOINT 用 exec form 不要 shell form
# 错误 shell form 父进程是 sh 信号传不到 app
ENTRYPOINT myapp --port 8080

# 正确 exec form 直接 exec 信号能传到 app
ENTRYPOINT ["myapp", "--port", "8080"]

# 4 用 STOPSIGNAL 与正确信号处理
STOPSIGNAL SIGTERM
# K8s 默认发 SIGTERM 30 秒后 SIGKILL
# 应用必须 graceful shutdown 不然 502

# 5 镜像标签策略
# 不要用 latest 生产
# myapp:latest             错误 不可追溯
# myapp:1.2.3              好 语义版本
# myapp:1.2.3-abc123       更好 + git sha
# myapp:1.2.3-abc123-20260524  最好 + 时间戳

# 6 镜像 size 检查脚本
docker image ls myapp --format "{{.Size}}"
# 超过 500MB 警报
# 超过 1GB 阻断 CI

# 7 dive 工具看每层
dive myapp:latest
# 检查 efficiency score 应该 95% 以上
# 看每层增加多少 wasted space 排查臃肿层

# 8 .dockerignore 检查
# 用 docker build --no-cache 看 sending build context 多少
# 应该 < 10MB 大了说明没排除好

另外强烈推荐 multi-arch build 用 BuildKit 一次构建 amd64 与 arm64 两版镜像 ARM 在 M 系列 Mac 上开发与在 AWS Graviton 上跑都需要。命令是 docker buildx build --platform linux/amd64,linux/arm64 -t myapp:1.0 --push 。

关键概念速查

概念 说明 推荐 备注
base 镜像 容器基础层 distroless / debian:slim 不用 ubuntu 太大
多阶段构建 builder + final 分离 必用 能降 90% 大小
layer 缓存 分层复用机制 不变在上 常变在下 缓存命中率决定 build 速度
.dockerignore 排除文件 必写 避免 .git secret 进镜像
BuildKit 新构建后端 必开 支持 cache mount secret
非 root 用户 USER nonroot 必配 限制 RCE 后果
HEALTHCHECK 容器健康检查 必配 K8s livenessProbe 协同
trivy CVE 扫描 必跑 CI 阻断 HIGH 漏洞
hadolint Dockerfile linter 必跑 静态规范检查
dive 分层可视化 开发用 排查臃肿层

避坑清单

  1. 不要用 ubuntu 当 base 800MB 大马拉小车 改 debian:slim 或 distroless。
  2. 不要把 COPY . /app 放最前面 缓存全失效 先 COPY 依赖文件后 COPY 源码。
  3. 不要把 .git node_modules 测试数据打进镜像 .dockerignore 必须写全。
  4. 不要在镜像里塞 .env 数据库密码 用 BuildKit secret 或运行时 K8s Secret 注入。
  5. 不要用 alpine 跑 Python Java 性能差 30% 兼容性坑多 用 debian:slim。
  6. 不要 root 跑容器 用 USER nonroot 或 distroless:nonroot 限制攻击面。
  7. 不要用 latest 标签生产 用 semver + git sha + 时间戳 可追溯。
  8. 不要 shell form ENTRYPOINT 用 exec form 否则信号传不到 app graceful shutdown 失败。
  9. 不要跳过 trivy 扫描 HIGH CRITICAL 漏洞必须修 CI 应阻断。
  10. 不要忽视 HEALTHCHECK 配上 livenessProbe readinessProbe 才能 K8s 自动恢复。

总结

把 Docker 镜像优化这套从我们踩过的所有坑里反过来看 你会发现真正影响生产成败的不是 Docker 本身 而是工程化的全栈能力。同样一个 Spring Boot 服务 用默认写法 2.8GB rolling update 拉 15 分钟 半夜卡死 用多阶段 + layered jar + distroless 350MB rolling update 30 秒 半夜安睡;同样一个 Python 服务 用 alpine 装包要重新编译 build 30 分钟跑起来还慢 30% 改 debian:slim build 2 分钟跑得飞快。Docker 不是写个 Dockerfile FROM 一下就完事的玩具 它是一个 base 镜像选择 + 多阶段构建 + layer 缓存 + .dockerignore + 安全扫描 + 非 root + HEALTHCHECK + 标签策略 的完整系统工程。

另一个常见的认知误区是把 Docker 当成纯部署工具 觉得能跑就行。但在大规模生产环境 镜像每多 100MB 集群每多 100 个节点就多浪费 10GB 存储与 10 分钟拉取时间 镜像里每多一个 CVE 都是潜在的攻击入口 镜像里每多一个未排除的 secret 都是直接的安全事故。任何一个工程环节没做好 你的 Docker 镜像都会拖累整个集群 让运维背锅。

打个比方 Docker 镜像就像快递公司的标准货运箱。base 镜像是箱子本身(选木箱 还是纸箱 还是塑料箱) 多阶段构建是装箱流程(车间组装 但只把成品装箱) layer 缓存是预打包模板(常用规格预制好 来订单只调最后几步) .dockerignore 是分拣清单(哪些东西不进箱) 安全扫描是 X 光检查(危险品不放行) 非 root 是封箱与铅封(防止半路被人撬) HEALTHCHECK 是货运追踪(随时知道在哪) 标签策略是货单号(可追溯责任)。哪一项缺了 这批货要么超重要么被海关扣要么半路出事故 都不能顺利送到客户手里 即使你的箱子选得再好。

所以下一次再有人跟你说 Docker 简单 写个 Dockerfile 就行 你可以反问他 你的 base 选好了吗 多阶段构建做了吗 layer 顺序排对了吗 .dockerignore 写全了吗 trivy 扫了吗 非 root 跑了吗 HEALTHCHECK 配了吗 这些工作没做完 Docker 只是一个能让你跑通 demo 的玩具 不是一个能扛业务的工程工具。从踩坑到投产 中间隔着一整套工程方法论 这条路没有捷径 但走完之后 你的镜像会从 2.8GB 降到 50MB 部署时间会从 15 分钟降到 30 秒 安全事故会从频发变成零发生。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

Stable Diffusion 文生图工程化完全指南:从一次"运营生成米老鼠营销图法务找上门"看懂为什么 pip install 远远不够

2026-5-24 17:04:11

技术教程

LLM 微调工程化完全指南:从一次"医疗客服模型把感冒诊断成败血症吓退用户"看懂为什么数据加训练远远不够

2026-5-24 17:12:46

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索