Docker 基础体系 · 第 51/70 篇。示例以现代 Docker Engine、BuildKit 与 Compose 规范为基础,并明确 Linux 容器边界。
Docker 时区、Locale 与 CA 证书:最小镜像中的运行时基础
最小镜像通常只保留“运行程序所必需的文件”。问题在于,程序需要的并不只有可执行文件和动态库:时间格式化需要时区数据库,文本处理可能需要 Locale 数据,HTTPS 校验需要 CA 信任库。
因此,下面三个目录或配置经常决定一个程序在开发环境正常、进入容器后却出现异常:
/etc/localtime
/usr/share/zoneinfo/
/etc/ssl/certs/
它们分别与时区数据、时区选择和 CA 证书信任库有关。Locale 则通常由环境变量和 libc 提供的数据共同决定,例如:
LANG
LC_ALL
LC_TIME
LC_NUMERIC
LC_COLLATE
这三类运行时基础彼此独立:
- 时区解决“同一个时间点如何显示”;
- Locale 解决“文本、数字、日期如何按某种语言和区域规则解释或格式化”;
- CA 证书解决“某个 TLS 证书链是否被本地信任”。
安装了 CA 证书,不会自动获得时区;设置了 TZ,也不会自动安装时区数据库;复制了时区文件,也不会改变 Locale。
1. Linux 容器到底提供了什么
Linux 容器不是一个拥有独立内核的虚拟机。容器中的进程通常共享宿主机 Linux 内核,但拥有相对隔离的:
- 根文件系统;
- 进程空间;
- 网络命名空间;
- 用户和权限视图;
- 挂载视图。
时间是一个容易混淆的例子。容器中的 clock_gettime() 等系统调用由宿主机内核提供,因此容器通常读取的是同一个内核时间源;但“把 Unix 时间戳格式化成上海时间”所需的时区规则,来自容器自己的用户态文件系统。
可以把时间处理拆成三层:
内核时钟
│
│ 返回 Unix 时间戳,例如 1714521600
▼
用户态运行库或语言运行时
│
│ 读取 TZ、/etc/localtime、zoneinfo
▼
格式化结果,例如 2024-05-01 08:00:00 +0800
因此:
- 容器不会因为缺少
tzdata而“没有时间”; - 容器可能能获得正确的 Unix 时间戳,却无法正确解析
Asia/Shanghai; - 容器的时区配置不会改变内核时钟,也不会改变数据库中保存的 UTC 时间。
1.1 时间点与本地时间不是一回事
Unix 时间戳表示一个绝对时间点。设时间点为 ,时区规则为 ,本地显示结果可以写成:
其中:
- 是绝对时间;
- 是时区规则,包括 UTC 偏移和夏令时变化;
- 是展示给用户的本地日期时间。
同一个 ,在两个时区下可能得到不同的日期:
UTC 2024-05-01 00:30:00
Asia/Shanghai 2024-05-01 08:30:00
America/New_York 2024-04-30 20:30:00
反过来,同一个本地时间不一定唯一对应一个时间点。夏令时切换时,某些本地时间可能不存在,或者重复出现。因此,日志和事件数据更适合保存 UTC 时间点,并在展示边界进行时区转换。
2. 时区:TZ、/etc/localtime 与 zoneinfo
2.1 TZ 只是选择,不是数据
TZ 是用户态程序常见的时区选择方式:
TZ=Asia/Shanghai date
但这个命令能否成功,取决于运行库是否能找到对应的时区规则。常见查找路径包括:
/usr/share/zoneinfo/Asia/Shanghai
/etc/localtime
所以以下 Dockerfile 并不完整:
FROM alpine:3.20
ENV TZ=Asia/Shanghai
COPY app /app
CMD ["/app"]
ENV TZ=Asia/Shanghai 只设置了一个字符串。若镜像中没有 tzdata,程序可能出现:
找不到时区
无法加载 location
使用 UTC 回退
时间格式化结果与预期不一致
在 Alpine 中,通常这样安装:
FROM alpine:3.20
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
COPY app /app
ENTRYPOINT ["/app"]
在 Debian 或 Ubuntu 中,通常这样安装:
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends tzdata \
&& rm -rf /var/lib/apt/lists/*
ENV TZ=Asia/Shanghai
COPY app /app
ENTRYPOINT ["/app"]
这里有两个不同动作:
- 安装
tzdata,提供/usr/share/zoneinfo下的规则文件; - 设置
TZ,告诉程序选择哪一份规则。
二者不能混为一谈。
2.2 /etc/localtime 是系统默认时区入口
很多 Linux 程序不直接读取 TZ,而是使用 /etc/localtime。它通常是一个指向 zoneinfo 文件的符号链接,或者是该文件的副本:
ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
完整 Alpine 示例:
FROM alpine:3.20
RUN apk add --no-cache tzdata \
&& ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo Asia/Shanghai > /etc/timezone
COPY app /app
ENTRYPOINT ["/app"]
/etc/timezone 主要是某些发行版工具使用的记录文件,不是所有运行库都依赖它。真正决定时区行为的通常是 TZ、/etc/localtime 以及 zoneinfo 数据。
如果程序明确使用:
time.LoadLocation("Asia/Shanghai")
它需要能找到名为 Asia/Shanghai 的时区数据;仅仅存在 /etc/localtime 不一定足够。
2.3 只复制一个时区文件
对于极小镜像,可以只复制需要的时区:
FROM alpine:3.20 AS tzdata
FROM scratch
COPY --from=tzdata /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
COPY --from=tzdata /usr/share/zoneinfo/UTC /usr/share/zoneinfo/UTC
ENV TZ=Asia/Shanghai
COPY app /app
ENTRYPOINT ["/app"]
但这有明确边界:
- 只能加载复制进去的区域;
- 某些程序需要
/etc/localtime,此时还要复制或创建对应入口; - zoneinfo 规则会随系统数据更新,固定复制意味着需要重新构建镜像;
- 如果程序依赖时区别名或其他区域,单文件复制可能不够。
在生产环境中,UTC 通常是最简单且最稳定的默认值:
ENV TZ=UTC
这并不表示用户界面不能展示本地时间,而是把转换推迟到明确的展示边界。
3. libc 决定了时区和 Locale 的实现边界
容器运行时不只有应用程序。动态链接程序还依赖 libc;即使是静态链接程序,语言运行时也可能自行读取系统文件。
常见组合如下:
| 基础环境 | libc | 典型特征 |
|---|---|---|
| Debian、Ubuntu | glibc | Locale 能力完整,系统包较丰富 |
| Alpine | musl | 体积小,Locale 与 glibc 行为不同 |
| Distroless | 取决于变体 | 通常缺少 shell 和包管理器 |
| Scratch | 无 libc、无用户态工具 | 只包含显式复制的文件 |
“镜像很小”不等于“程序只需要一个二进制文件”。需要分析程序的依赖方式:
应用程序
├─ 动态加载器和 libc
├─ 时区数据库
├─ Locale 数据
├─ CA 信任库
└─ 用户、DNS、临时目录等运行时文件
静态链接只能消除某些动态库依赖,不能自动提供 CA、zoneinfo 或 Locale 数据。
4. Locale:不只是语言环境变量
Locale 是一组区域化规则,可能影响:
- 字符分类,例如字母、数字、空白;
- 大小写转换;
- 字符串排序和比较;
- 数字格式,例如小数点和千位分隔符;
- 日期、时间和月份名称;
- 错误消息语言;
- 字符编码。
常见变量的优先关系可简化为:
LC_ALL
覆盖所有 LC_* 类别
LC_TIME、LC_NUMERIC、LC_COLLATE ...
覆盖对应类别
LANG
提供未单独设置类别的默认值
例如:
LC_ALL=C
LANG=zh_CN.UTF-8
此时 LC_ALL=C 优先,整个进程通常使用 C/POSIX Locale,而不是中文 UTF-8 Locale。
4.1 LANG 不会凭空安装 Locale
下面的配置只设置了名称:
ENV LANG=zh_CN.UTF-8
ENV LC_ALL=zh_CN.UTF-8
如果镜像没有对应 Locale 数据,glibc 程序可能报告:
warning: setlocale: LC_ALL: cannot change locale
或者回退到 C Locale。程序仍可能运行,但排序、日期名称、数字格式和非 ASCII 文本处理可能改变。
在 Debian 中,可以使用 locales 生成目标 Locale:
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends locales \
&& sed -i 's/^# *zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen \
&& locale-gen \
&& rm -rf /var/lib/apt/lists/*
ENV LANG=zh_CN.UTF-8
ENV LC_ALL=zh_CN.UTF-8
这里的关键不是变量,而是 locale-gen 生成了 glibc 可读取的数据。
4.2 Alpine 的 Locale 不能按 glibc 习惯处理
Alpine 使用 musl。musl 的 Locale 支持模型与 glibc 不同,不能直接套用:
locale-gen
localedef
这类 glibc 工作流。很多 Alpine 程序主要依赖 UTF-8 字节处理,并不提供完整的 glibc Locale 数据库。需要特定排序、区域化数字或本地化日期的程序,应先验证实际运行库和应用行为,而不是仅复制 LANG。
可执行验证示例:
FROM alpine:3.20
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
RUN printf '%s\n' "$LANG" "$LC_ALL"
这只能证明环境变量存在,不能证明每个程序都获得了完整的区域化功能。应使用目标语言运行时进行测试,例如测试:
- Unicode 字符是否能正确编码和解码;
- 排序是否符合业务要求;
- 小数格式是否符合预期;
- 日期月份名称是否可用。
4.3 C Locale 与 UTF-8 的工程取舍
C Locale 通常提供稳定、可预测的字节序或 ASCII 规则,适合协议字段、机器日志和可复现构建。UTF-8 则适合用户文本,但“使用 UTF-8 编码”和“启用完整中文 Locale”不是同一件事。
例如,一个程序可能正确处理 UTF-8 字符串,却仍然按字节排序;另一个程序可能根据 Locale 改变排序顺序。数据库排序、应用排序和 shell 排序也可能使用不同实现。
因此,Locale 选择必须对应业务语义:
- 协议、配置、机器日志:倾向明确使用 UTF-8,并避免依赖隐式本地化;
- 用户界面:在展示层显式设置语言和区域;
- 需要稳定排序的程序:不要把
LC_ALL交给宿主机或 Compose 环境随机继承; - 需要特定 glibc Locale 的程序:不要未经验证地迁移到 Alpine。
5. CA 证书:TLS 信任验证依赖的文件
CA 是 Certificate Authority,证书颁发机构。HTTPS 连接中,服务器通常发送自己的证书以及部分中间证书。客户端需要验证:
- 服务器证书的签名链能否连接到本地信任的根 CA;
- 证书的主机名是否匹配目标主机;
- 证书是否在有效期内;
- 密钥用途、签名算法等约束是否满足;
- 如果启用吊销检查,吊销状态是否满足要求。
可以把基本信任条件抽象为:
其中:
cert是服务器证书链;host是请求的主机名;roots是客户端信任库;now是当前时间。
因此 CA 证书和时区虽然是两个独立问题,却都可能导致 TLS 失败:
- 缺少 CA:无法建立信任链;
- 系统时间错误:证书可能显示“尚未生效”或“已过期”;
- 时区显示错误:会误导诊断人员,但证书有效期通常以绝对时间验证,不应简单归因于显示时区。
5.1 安装系统 CA 信任库
Alpine:
FROM alpine:3.20
RUN apk add --no-cache ca-certificates
COPY app /app
ENTRYPOINT ["/app"]
Debian:
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY app /app
ENTRYPOINT ["/app"]
常见系统文件包括:
/etc/ssl/certs/ca-certificates.crt
/etc/ssl/certs/
具体路径取决于发行版和程序。不能只凭文件名假设所有运行时都使用同一位置。
5.2 应用程序可能有自己的 CA 查找规则
不同程序可能使用:
- 系统 CA 目录;
- 系统 CA bundle;
- OpenSSL;
- Go 的
crypto/x509; - Java truststore;
- Python 或 Node.js 的运行时规则;
- 应用自己的证书配置;
SSL_CERT_FILE、SSL_CERT_DIR等环境变量。
Go 程序通常会尝试加载系统根证书;如果运行环境没有系统 CA,可能需要显式指定 SSL_CERT_FILE,或者在构建阶段将 CA bundle 复制到最终镜像。具体行为还与 Go 版本、是否启用 cgo、目标操作系统以及环境变量有关,不能把“静态编译”当成“自带 CA”。
5.3 企业内部 CA 与公有 CA 不是一回事
如果服务使用企业内部 CA,安装公共 ca-certificates 仍然不够。应将内部根证书加入信任库:
FROM alpine:3.20
RUN apk add --no-cache ca-certificates
COPY company-root-ca.crt /usr/local/share/ca-certificates/company-root-ca.crt
RUN update-ca-certificates
COPY app /app
ENTRYPOINT ["/app"]
风险包括:
- 把错误或过度授权的根 CA 放入所有服务;
- 把私钥误复制进镜像;
- 根 CA 更新后没有重建镜像;
- 只修改了容器内 trust store,却没有验证目标语言运行时是否读取它。
根 CA 是高权限信任材料,镜像构建上下文、代码仓库和发布日志都不应泄露私钥。客户端证书私钥通常应通过 Secret 或运行时安全注入提供,而不是写入镜像层。
6. 最小镜像中的三类数据流
下面的关系比“安装几个包”更重要:
flowchart TD
A[应用程序] --> B[语言运行时或 libc]
B --> C[TZ / etc localtime]
B --> D[zoneinfo 数据]
B --> E[Locale 环境变量与数据]
B --> F[CA 查找规则]
F --> G[系统 CA Bundle]
G --> H[TLS 服务器证书链]
H --> I[主机名与有效期校验]
C --> J[本地时间格式化]
D --> J
E --> K[排序/数字/日期/字符处理]
关键路径分别是:
- 时区:
时间点 → zoneinfo → 本地时间字符串; - Locale:
环境变量 → libc/运行时 Locale 数据 → 文本规则; - CA:
服务器证书链 → 本地信任根 → 主机名/有效期校验。
三条路径中的任何一条缺失,程序都可能启动成功,但在特定功能第一次执行时失败。
7. 一个可验证的多阶段镜像
下面的 Dockerfile 以 Go 应用为例,展示 Debian 运行时中如何显式准备三类基础。它假设应用入口包位于当前目录,并且构建上下文中有 go.mod 和 go.sum。
# syntax=docker/dockerfile:1
FROM golang:1.23-bookworm AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -trimpath -ldflags="-s -w" -o /out/app .
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
tzdata \
&& rm -rf /var/lib/apt/lists/*
ENV TZ=UTC
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
COPY --from=build /out/app /usr/local/bin/app
USER 65532:65532
ENTRYPOINT ["/usr/local/bin/app"]
每一步的作用不同:
CGO_ENABLED=0让该示例尽量避免动态 libc 依赖;ca-certificates提供 HTTPS 信任根;tzdata提供时区规则;TZ=UTC选择默认时区;LANG和LC_ALL让 Locale 选择显式化;USER避免以 root 运行,但它不会自动创建主目录或写权限;ENTRYPOINT使用 JSON 形式,让应用直接成为容器主进程。
若程序需要 Asia/Shanghai:
ENV TZ=Asia/Shanghai
同时必须保留 tzdata,并用应用测试 time.LoadLocation("Asia/Shanghai") 是否成功。
7.1 Scratch 版本需要显式复制全部依赖
FROM scratch 没有 shell、包管理器、证书、时区数据、/etc/passwd 和 CA bundle。一个可能的结构是:
FROM alpine:3.20 AS assets
RUN apk add --no-cache ca-certificates tzdata
FROM golang:1.23-bookworm AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -trimpath -ldflags="-s -w" -o /out/app .
FROM scratch
COPY --from=assets /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=assets /usr/share/zoneinfo/UTC /usr/share/zoneinfo/UTC
COPY --from=assets /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ=UTC
COPY --from=build /out/app /app
USER 65532:65532
ENTRYPOINT ["/app"]
这个镜像仍有边界:
- 没有
/bin/sh,docker exec ... sh会失败; - 没有 CA 更新工具,证书必须在构建时准备;
- 没有完整
/etc/passwd,某些程序无法把 UID 映射为用户名; - 没有 DNS 配置文件时,名称解析行为可能不符合程序预期;
- 没有时区文件时,命名时区加载会失败。
Scratch 适合依赖集合已经明确且验证充分的应用,不适合作为默认“更安全”的替代品。它减少了可见组件,也减少了现场诊断能力。
8. Compose 中的配置边界
Compose 的 environment 可以传递配置,但不能安装文件:
services:
api:
image: example/api:1.0
environment:
TZ: UTC
LANG: C.UTF-8
LC_ALL: C.UTF-8
这只改变进程环境。镜像仍然需要包含:
- 对应的 zoneinfo;
- 应用所需的 Locale 数据;
- CA 信任库。
不要把宿主机的 /etc/localtime 当作跨平台、可复现的镜像依赖:
volumes:
- /etc/localtime:/etc/localtime:ro
这种做法会让容器行为依赖宿主机文件,并可能在不同 Linux 发行版或非 Linux Docker 环境中表现不同。若业务要求固定时区,优先在镜像中安装并配置;若业务要求 UTC,直接在镜像和 Compose 中明确设置 TZ=UTC。
9. 端到端验证:不要只检查环境变量
9.1 验证时区
在有工具的镜像中:
docker run --rm -e TZ=Asia/Shanghai alpine:3.20 sh -c '
apk add --no-cache tzdata >/dev/null &&
date &&
date -u &&
test -f /usr/share/zoneinfo/Asia/Shanghai
'
预期现象:
date显示TZ指定的本地时间;date -u显示 UTC;- 目标 zoneinfo 文件存在。
若只执行:
docker run --rm -e TZ=Asia/Shanghai alpine:3.20 date
结果不应被当作完整验证,因为官方 Alpine 基础镜像未必预装 tzdata。
9.2 验证 CA
docker run --rm alpine:3.20 sh -c '
apk add --no-cache ca-certificates wget >/dev/null &&
wget -qO- https://example.com >/dev/null &&
echo TLS_OK
'
预期输出:
TLS_OK
失败时要区分:
certificate verify failed:优先检查 CA、系统时间、主机名和证书链;network unreachable:不是 CA 问题;- DNS 解析失败:先检查 DNS;
- 只有某个语言运行时失败:检查该运行时的 CA 查找路径。
不要通过关闭证书验证来“修复”问题:
InsecureSkipVerify=true
verify=False
curl -k
这会移除服务器身份验证,不能作为生产解决方案。
9.3 验证 Locale
docker run --rm \
-e LANG=C.UTF-8 \
-e LC_ALL=C.UTF-8 \
debian:bookworm-slim \
sh -c 'printf "LANG=%s\nLC_ALL=%s\n" "$LANG" "$LC_ALL"'
这只能检查变量。对需要完整 Locale 的程序,还应在目标镜像中执行真实测试,例如:
locale
locale -a
如果没有 locale 命令,不代表 Locale 一定不可用;它只说明镜像没有该诊断工具。最终证据应来自应用行为和运行库文档。
10. 常见失败路径与诊断顺序
10.1 日志时间偏移,但事件顺序正确
常见原因是:
- 应用保存的是 UTC;
- 日志查看器按宿主机时区展示;
- 容器内
TZ与观察端不同。
诊断时同时输出:
Unix 时间戳
UTC 格式
本地格式
时区名称或偏移
不要只比较日期字符串。优先确认绝对时间点是否一致。
10.2 程序启动正常,调用 HTTPS 时失败
这是 CA 缺失的典型延迟故障。启动阶段没有建立 TLS 连接,因此容器健康检查可能仍然通过。
检查:
ls -l /etc/ssl/certs/
test -f /etc/ssl/certs/ca-certificates.crt
然后使用与应用相同的运行时进行测试。curl 成功不能完全证明 Java、Node.js 或 Go 的 trust store 一定正确,因为它们可能使用不同实现。
10.3 TZ=Asia/Shanghai 已设置,但程序仍是 UTC
按以下顺序检查:
- 进程是否真正继承了
TZ; /usr/share/zoneinfo/Asia/Shanghai是否存在;- 程序是否使用自己的时区数据库;
- 程序是否只读取
/etc/localtime; - 语言运行时是否在编译时嵌入了 tzdata;
- 是否存在应用级配置覆盖环境变量。
10.4 Locale 警告被忽略后,排序出现业务错误
setlocale 警告不一定导致进程退出,但可能使程序回退到 C Locale。对于依赖本地化排序、金额格式和日期名称的程序,这种回退可能是静默的数据展示错误,而不是明显崩溃。
应将 Locale 行为加入测试,而不是仅在 Dockerfile 中写:
ENV LANG=zh_CN.UTF-8
11. 版本、更新与供应链边界
时区规则和 CA 根证书都会变化:
- 时区数据库会修正历史规则和未来政策;
- CA 信任库会增加、删除或调整受信任根;
- 基础镜像标签可能移动到新的补丁版本;
- 构建缓存可能保留旧的包索引或旧的证书数据。
因此,镜像构建应使用发行版推荐的包管理方式,并在发布流程中定期重建和扫描。tzdata 与 ca-certificates 不是一次安装、永久不变的运行时常量。
同时要区分三个时间:
镜像构建时间
容器启动时的内核时间
证书校验时读取的当前时间
构建时复制的 CA 和 zoneinfo 是静态文件;运行时的时间点来自内核。更新 CA 或时区规则通常需要发布新镜像,而不是只重启现有容器。
12. 选择基础镜像时的实际取舍
Debian 或 Ubuntu
适合:
- 依赖 glibc;
- 需要完整 Locale;
- 依赖系统工具进行诊断;
- 运行时依赖较多且希望包管理简单。
代价是镜像和依赖集合通常更大。
Alpine
适合:
- 应用已经验证兼容 musl;
- 需要较小的常规 Linux 用户态;
- 能接受与 glibc 不同的 Locale、DNS 和 ABI 行为。
不能只因为镜像小就迁移。需要特别验证动态链接、Locale、时间、TLS、DNS 和第三方原生库。
Distroless
适合:
- 依赖已经固定;
- 不需要 shell 和包管理器;
- 通过外部工具或临时调试容器完成诊断。
必须确认对应变体中是否包含 CA、zoneinfo、动态库和非 root 所需文件。
Scratch
适合:
- 静态链接或自带完整运行时;
- 明确知道所有外部文件依赖;
- 有成熟的日志、监控和调试方式。
它不是“没有依赖”,而是“不会替你提供依赖”。
一个最小但可用的 Linux 容器运行时,至少应回答四个问题:
- 应用保存和展示的时间分别采用什么语义,命名时区数据在哪里;
- 应用使用的 libc 或语言运行时是否支持目标 Locale;
- TLS 客户端从哪里读取公共或企业内部 CA;
- 镜像更新后如何验证时区规则、Locale 行为和证书信任仍然正确。
只设置 TZ、LANG 或 LC_ALL,并不能完成这些配置;只复制二进制文件,也不能假设 CA、zoneinfo 和 Locale 会自动存在。最小镜像的正确做法不是盲目删除文件,而是先识别运行时数据流,再逐项保留、验证和更新真正的依赖。
系列导航与关联阅读
- 系列入口:Docker 完整学习路线:从镜像与容器到安全、可观测和生产交付
- 上一篇:Docker PID 1 与 Init:信号、子进程回收、Shell Form 和 Tini
- 下一篇:数据库运行在 Docker:持久化、初始化、备份、资源和生产边界
- 延伸:Docker Alpine、Distroless 与 Scratch:libc、证书、时区和调试取舍
- 延伸:Go 应用 Docker 镜像:静态链接、CA、时区、非 root 和优雅退出
官方资料
本文依据 Docker、OCI 与 CNCF 官方文档重新梳理;正文与生产检查清单由 WR BLOG 编写。

评论
0 条讨论