#docker-build #docker-image #docker #checksum #dockerfile #container-image #tool

app docker-source-checksum

基于源码的确定性Docker镜像校验和

3个版本

0.2.2 2021年2月16日
0.2.1 2020年3月14日
0.2.0 2020年3月8日

#931开发工具

MPL-2.0 OR MIT OR Apache-2.0

21KB
233

基于源码的确定性Docker镜像校验和

使用案例

您有一个CI管道,该管道构建一个包含许多Dockerfile的单仓。

您希望有效地避免重建没有变化的Dockerfile,即使单仓的其他部分已经更改。

docker-source-checksum 将计算

  • Dockerfile 内容的哈希值
  • Dockerfile中引用的所有源文件(通过解析得出)
  • 可能影响构建的任何额外参数

然后将这些内容一起哈希,在尝试调用docker build之前,为您提供确定性校验和。您可以用它作为基于内容的确定性ID来避免重建已经构建的容器(例如,通过使用该校验和进行标记)。

在您的CI管道中使用

假设,通常您的CI管道会做类似的事情。

docker build -f someproject/Dockerfile .

这种方法存在一些问题

  • 将所有文件发送到docker守护进程需要一些时间。这部分本身可能需要相当长的时间,即使在没有需要重建的情况下,容器镜像已经缓存在本地上,这种情况也不例外。
  • 如果在某些不同的机器上已经完成了完全相同的构建,那么在这个机器上不会重用,除非您已经设置了一些更智能的系统来共享它们。
  • 您需要等待docker build完成以获取构建的唯一ID。

使用DSC,您会

BUILD_FULL_ID=$(docker-source-checksum -f someproject/Dockerfile .)
BUILD_ID=${BUILD_FULL_ID:0:8} # take just first 8 characters
TAG_NAME=my-docker-repository.com/$PACKAGE_NAME:$BUILD_ID

并且在不到一秒钟的时间内,即使对于大型项目,您也会得到构建的确定性加密ID(在此之前,您甚至还没有尝试构建任何内容)。此时,您可能可以尝试性地启动CI的一部分,使用已经知道的docker镜像url。

您的CI脚本的其他部分可以快速检查是否已经存在此确切的构建

if DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect $TAG_NAME > /dev/null; then
  echo "$TAG_NAME already built. Skipping build and push"
  exit 0
fi

(或者如果您想将其缓存在本地上,也可以使用docker pull)。

并且只有在它从未构建过的情况下,您才会本地构建并将其推送到您的注册表

docker build -t $TAG_NAME -f someproject/Dockerfile .
docker push $TAG_NAME

警告和缺失功能

  • 不要在不受信任的Dockerfiles上使用它
  • 确切的校验和尚不稳定,可能在版本之间发生变化
  • 变量扩展不会执行,因此 ADDCOPY 中的源路径内的变量将无法工作。
  • ["src1", "src", "dst"]ADDCOPY 语法不受支持(欢迎提出问题)
  • 忽略文件所有权
  • 它是用2个小时拼凑起来的,所以如果你打算在生产中使用它,也许...审查一下代码,或者告诉我你的想法

话虽如此,似乎工作得很好。

安装

查看 docker-source-checksum 发布版,或者使用 cargo install docker-source-checksum

使用

docker build 类似

$ docker-source-checksum --help
docker-source-checksum 0.2.0
Dockerfile source checksum

USAGE:
    docker-source-checksum [FLAGS] [OPTIONS] <context-path>

FLAGS:
    -h, --help       Prints help information
        --hex        Output hash in hex
    -V, --version    Prints version information

OPTIONS:
        --extra-path <extra-path>...        Path relative to context to include in the checksum
        --extra-string <extra-string>...    String (like arguments to dockerfile) to include in the checksum
    -f, --file <file>                       Path to `Dockerfile`
        --ignore-path <ignore-path>...      Path relative to context to ignore in the checksum

ARGS:
    <context-path>    Dockerfile build context path

依赖

约3–11MB
约110K SLoC