使用精简的基础镜像

  • Alpine

Alpine一个基于 musl libc 和 busybox、面向安全的轻量级 Linux 发行版,压缩体积只有 3M 左右,很多流行的镜像都有基于 alpine 的制作的基础镜像。

  • scratch

scratch 是一个空镜像,如果我们的应用是一个不依赖动态链接库的、包含所有依赖的二进制文件,则可以使用 scratch 作为基础镜像,此时镜像的体积差不多就是二进制文件的体积。

  • busybox

如果希望镜像里可以包含一些常用的 Linux 工具,busybox 镜像是个不错选择,它集成了一百多个最常用 Linux 命令和工具的软件工具箱,镜像压缩体积只有不到 1M,非常便于构建小镜像。

  • distroless

distroless 镜像仅包含应用程序及其运行时依赖项。不包含包管理器、shell或任何其他程序。

但因此如果黑客入侵了应用程序并获取了容器的访问权限,也无法造成太大的损害。

生产环境中也不应该将 Shell附加到容器中进行调试,而应依靠正确的日志收集和监控。

 1FROM node:8 as build
 2
 3WORKDIR /app
 4COPY package.json index.js ./
 5RUN npm install
 6
 7FROM gcr.io/distroless/nodejs
 8
 9COPY --from=build /app /
10EXPOSE 3000
11CMD ["index.js"]

清理包管理器缓存

在 Dockerfile 中使用包管理器安装依赖的软件包时,往往会产生一些缓存数据,可以清理掉以减少镜像体积。

  • Alpine

如果使用 alpine 基础镜像,可以在用 apk add 安装软件包时加 –no-cache

1FROM alpine:latest
2
3RUN apk add --no-cache tzdata ca-certificates
  • Ubuntu/Debian
1FROM ubuntu:latest
2
3RUN apt update -y && apt install -y curl
4
5RUN apt-get clean autoclean && \
6  apt-get autoremove --yes && \
7  rm -rf /var/lib/{apt,dpkg,cache,log}/

多阶段构建

Dockerfile 支持多阶段构建,即有多个 FROM 指令,最终构建出的镜像由由最后一个 FROM 之后的指令决定,通常可以把这之前的指令用作编译,之后的指令用作打包,打包阶段可以将编译阶段产生的文件拷贝过来,这样可以实现在最终镜像中只保留运行程序所需要的内容。

以下例子使用 Golang 静态编译二进制文件,然后 COPY 到 scratch 镜像中。

 1FROM golang:latest AS build
 2WORKDIR /workspace
 3COPY . .
 4# 静态编译二进制
 5RUN CGO_ENABLED=0 go build -o app -ldflags '-w -extldflags "-static"' .
 6
 7FROM scratch
 8# 拷贝二进制到空镜像
 9COPY --from=build /workspace/app /usr/local/bin/app
10CMD ["app"]

参考资料