shellless 容器、binaryless 容器以及 distroless 容器

大家可能对 rootless 容器有一定的了解,rootless 容器说的是不要以 root 用户启动容器,以便简单 限制一下容器内进程的权限,一方面更符合安全上对权限控制的要求, 另一方面也可以抵御部分容器逃逸问题。

这里要介绍另一个容器安全方面的建议,那就是,应当尽可能的使用 shellless/shell-less 容器, 或使用 binaryless/binary-less 容器,甚至是使用 distroless 容器。

shellless/shell-less 容器

shellless 或者说 shell-less 容器, 顾名思义指的是 容器内不包含 shell

因为容器内不包含 shell,所以 shellless 容器可以免疫部分的 get shell 攻击和 部分利用任意命令执行漏洞进行的攻击以及其他依赖 shell 的攻击 (依赖 shell 的渗透攻击以及后渗透攻击)。

binaryless/binary-less 容器

binaryless 或者说 binary-less 容器,在 shellless 容器的基础上更进一步, 容器内不包含除用户业务程序外的任何其他二进制可执行文件和脚本

因为不包含任何额外的二进制可执行文件,所以 binaryless 容器比 shellless 容器能够免疫更多的利用任意命令执行漏洞进行的攻击以及其他依赖容器内有二进制执行文件的攻击。

distroless 容器

distroless 容器在 binaryless 容器的基础上又跟进了一步, 容器内不包含除用户业务程序及业务程序的运行时依赖外的任何其他程序、库以及非必须的系统文件

因为只包含业务程序及其依赖,所以 distroless 容器又比 binaryless 容器能进一步提升容器安全性。

实现方案

目前社区使用的一些容器方案可以实现 shellless 、 binaryless 或 distroless 容器:

  • 一个是使用 scratch 作为基础镜像,并且通过多阶段构建的方式 COPY 业务所需的内容,类似下面这样:

    FROM golang:1.16 as builder
    # ...
    RUN go build xxx
    
    FROM scratch
    COPY --from=builder /path/to/buld-files  /path/to/save
    # ...
    
  • 一个是使用 https://github.com/GoogleContainerTools/distroless 项目提供的镜像作为基础镜像,并且通过多阶段构建的方式 COPY 业务所需的内容,类似下面这样:

    FROM golang:1.16 as builder
    # ...
    RUN go build xxx
    
    FROM gcr.io/distroless/base-debian10
    COPY --from=builder /path/to/buld-files  /path/to/save
    # ...
    
  • 还有就是使用 docker-slim 工具对镜像做二次精简,删除不需要的内容。

当然,也可以其他方法实现类似 scratchgcr.io/distroless 这样的 shellless 、 binaryless 或 distroless 的基础镜像, 然后按照类似上面的方法使用这些基础镜像来构建相应的业务镜像。

大家下次构建镜像的时候,推荐构建一个 shellless 或 binaryless 的镜像,也可以尝试 distroless 镜像或者使用 docker-slim 工具对镜像进行二次精简。

我后面也会根据自己的实践维护一个类似 https://github.com/GoogleContainerTools/distroless 的项目, 提供一些 binaryless 的基础镜像,以及相应的各个场景下使用 binaryless 可能会面临的一些问题的可行的解决方法。

更新:

我维护的 binaryless 基础镜像项目地址: https://github.com/mozillazg/binaryless


Comments