学习中心/工程实践/Docker/Docker 进阶:能发上线的镜像,不是只在本机跑
· Docker · 进阶
Docker 进阶:能发上线的镜像,不是只在本机跑
多阶段构建、钉版本、非 root、健康检查。密钥不要写进图层。

能跑不等于能发
本机 compose up 只证明你的笔记本行。要给别人、给服务器,镜像得小、得可重复、密钥不能在图层里、进程不要用 root。
- 瘦multi-stage
- 钉pin tag
- 人USER
- 活HEALTHCHECK
1. 多阶段:构建和运行分开
编译器、测试、包管理器只在 builder 里。最终镜像只拷产物。少几百兆是常态。
- 写第一阶段:有编译工具
FROM node:22-bookworm AS builder - 写第二阶段:更小的运行基础
FROM node:22-bookworm-slim - 写只把产物拷过来,不要拷 node 的构建缓存
COPY --from=builder /app/dist /app/dist
2. 钉住版本,不要 latest
latest 今天和明天可以不是同一个摘要。FROM 和 compose 里都写小版本。对外发,再钉 digest。
- 标签用你能说清楚的版本,不要 latest
docker build -t ghcr.io/you/myapp:1.4.2 . - 看摘要。部署清单里可以写 image@sha256:…
docker image inspect --format '{{.RepoDigests}}' ghcr.io/you/myapp:1.4.2
3. 容器里不要 root
默认 root。镜像被打穿,就是宿主机上的特权起点。建一个用户,USER 切过去。
- 写系统用户,固定 uid,方便挂卷时权限稳定
RUN useradd --system --uid 10001 app - 写这行之后的进程不再是 root
USER app
4. 健康检查
进程在不等于能服务。Compose 和编排器靠 HEALTHCHECK 决定要不要摘掉这个实例。
- 写容器自己报活。没有 wget 就换 curl 或你的二进制
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://127.0.0.1:8000/health || exit 1
5. 推到仓库
- 先登录。账号和 token 不要写进 Dockerfile
docker login ghcr.io - 把这张标签送到仓库。服务器 pull 这一张,不要在服务器上 build 业务镜像
docker push ghcr.io/you/myapp:1.4.2
6. 资源先写上
没限制的容器可以吃光那台机器。本机 compose 就可以先写 CPU 和内存,习惯带到后面的编排。
- 先在本机用上限跑。撑不住现在就知道,不要等生产
docker run --rm --cpus=1 --memory=512m myapp:1.4.2
7. Compose 是本地,不是集群
Compose 适合笔记本和单机。多机、滚动、服务发现,是 Kubernetes 或同类编排的事。先把镜像做对,再谈那一层。
瘦、钉、非 root、能探活、能推进仓库,这张镜像才叫能发。密钥仍然只在运行时出现。