生产环境Docker:多阶段构建和容器安全

Docker在现代软件开发中无处不在,但在生产环境中正确使用它需要了解几种入门教程中不明显的模式。多阶段构建、镜像安全和运行时配置是大多数随意使用Docker的团队出错的地方。

多阶段构建

单阶段Docker构建的问题:你构建应用程序所需的每个工具(编译器、构建依赖项、测试框架、开发工具)都会出现在最终镜像中——通常向只需要编译输出的镜像添加数百兆字节。多阶段构建通过将构建环境与运行时环境分离来解决这个问题:
“`dockerfile
# 阶段1:构建
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci –only=production=false
COPY . .
RUN npm run build

# 阶段2:运行时
FROM node:20-alpine AS runtime
WORKDIR /app
COPY –from=builder /app/dist ./dist
COPY –from=builder /app/node_modules ./node_modules
EXPOSE 3000
USER node
CMD [“node”, “dist/index.js”]
“`
最终镜像只包含运行时阶段复制的内容——构建工具、测试依赖项和源文件不包含在内。单阶段构建可能为800MB的典型Node.js应用程序,使用多阶段可以降至150MB。`–from=builder`指令从命名阶段复制。你也可以从任意Docker镜像复制(`–from=nginx:latest`)以获取特定文件而不继承完整镜像。`.dockerignore`文件:相当于`.gitignore`但用于Docker构建上下文——始终包含`node_modules`、`.git`、`*.md`、测试文件和其他不应发送到Docker守护进程的构建产物。发送大型构建上下文是Docker构建缓慢最常见的原因。

容器安全

以非root用户运行:默认情况下,容器以root身份运行——如果容器被攻破,这是一个重大安全风险(容器中的root可能映射到主机上的root)。在生产镜像中始终切换到非root用户。对于Node.js,官方镜像包含一个`node`用户:`USER node`。对于自定义用户:`RUN addgroup -S appgroup && adduser -S appuser -G appgroup`。最小基础镜像:优先选择`alpine`基础镜像(5MB)或`distroless`镜像(Google的镜像,没有shell、包管理器或其他工具——只有应用程序和运行时)。distroless Python镜像可以低于50MB;标准Python镜像超过1GB。密钥和环境变量:永远不要用`ENV`或`ARG`将密钥烘焙到镜像中——它们在镜像层和`docker inspect`中可见。使用Docker secrets(用于Swarm)、Kubernetes secrets,或通过编排器在运行时注入密钥。扫描镜像:`docker scout`(内置于Docker Desktop)、`trivy`或`snyk`扫描镜像以查找基础镜像和依赖项中的已知CVE。在CI流水线中推送到注册表之前运行扫描。只读文件系统:`docker run –read-only`防止向容器文件系统进行任何写入(为需要写入访问的目录如/tmp挂载tmpfs)。显著减少攻击面。资源限制:在生产中始终设置CPU和内存限制——没有限制的容器可以消耗所有主机资源。健康检查:在Dockerfile中定义`HEALTHCHECK`或在Compose中定义`healthcheck`——编排器使用此来确定容器何时准备好以及何时重启它。

上一篇 墨西哥食物:墨西哥卷饼、摩尔酱和地区多样性
下一篇 Montenegro: Kotor Bay and the Balkans Adriatic Coast