运行 Docker 构建#

我们大多数基于 Linux 的持续集成任务使用 Dockerdocker-compose 与公共 CI 服务分离。保持 CI 配置最小化可以实现本地可重复性。

用法#

有多种方法可以执行基于 docker 的构建。推荐的方式是使用 Archery 工具

示例#

列出可用的镜像

archery docker images

执行构建

archery docker run conda-python

Archery 调用以下 docker-compose 命令

docker-compose pull --ignore-pull-failures conda-cpp
docker-compose pull --ignore-pull-failures conda-python
docker-compose build conda-cpp
docker-compose build conda-python
docker-compose run --rm conda-python

显示 docker-compose 命令而不是执行它们

archery docker run --dry-run conda-python

要禁用镜像拉取

archery docker run --no-cache conda-python

这将转换为

docker-compose build --no-cache conda-cpp
docker-compose build --no-cache conda-python
docker-compose run --rm conda-python

要仅对叶子镜像禁用缓存

用于强制构建依赖项的开发版本。在下面的示例中,该命令构建 conda-cpp > conda-python > conda-python-pandas 镜像树的分支,其中叶子镜像是 conda-python-pandas

PANDAS=upstream_devel archery docker run --no-leaf-cache conda-python-pandas

这将转换为

export PANDAS=upstream_devel
docker-compose pull --ignore-pull-failures conda-cpp
docker-compose pull --ignore-pull-failures conda-python
docker-compose build conda-cpp
docker-compose build conda-python
docker-compose build --no-cache conda-python-pandas
docker-compose run --rm conda-python-pandas

请注意,它不会拉取 conda-python-pandas 镜像,并在构建时禁用缓存。

PANDAS 是一个 构建参数,请参阅 .env 文件中的默认值。

要完全跳过构建镜像

docker-compose 的层级缓存机制可能不如 docker 的可靠,这取决于版本、cache_from 构建条目以及使用的后端(docker-py、docker-cli、docker-cli 和 buildkit)。这会导致不同的层哈希值,即使重复执行相同的构建命令也会导致缓存丢失,最终导致完全镜像重建。

如果镜像已构建但缓存无法正常工作,则可以跳过构建阶段

# first run ensures that the image is built
archery docker run conda-python

# if the second run tries the build the image again and none of the files
# referenced in the relevant dockerfile have changed, then it indicates a
# cache miss caused by the issue described above
archery docker run conda-python

# since the image is properly built with the first command, there is no
# need to rebuild it, so manually disable the pull and build phases to
# spare the some time
archery docker run --no-pull --no-build conda-python

将环境变量传递给容器

容器中使用的构建脚本大多数可以通过环境变量进行配置。使用 --env-e CLI 选项传递它们,类似于 docker rundocker-compose run 接口。

archery docker run --env CMAKE_BUILD_TYPE=release ubuntu-cpp

有关 C++ 构建中的可用环境变量,请参阅 ci/scripts/cpp_build.sh 脚本。

使用自定义命令运行镜像

自定义 docker 命令可以作为 archery docker run 的第二个参数传递。

以下示例在容器中启动交互式 bash 会话,这对于交互式调试构建很有用

archery docker run ubuntu-cpp bash

使用增加的调试输出构建镜像

要为调试启用额外的日志输出,请将 --debug 标志传递给 archery

archery --debug docker run ubuntu-cpp

除了启用 DEBUG 级别的日志记录外,这还将转换为将 --progress=plain 传递给 docker(-compose) 构建命令。

Docker 卷缓存#

大多数 compose 容器都有从主机挂载的特定目录,以重用 ccachemaven 工件。这些 docker 卷位于 .docker 目录中。

要清理缓存,只需删除一个或多个目录(或整个 .docker 目录)。

开发#

docker-compose 配置针对使用分层镜像的可重用开发容器进行了调整。例如,多种语言绑定依赖于 C++ 实现,因此,与其在多个 Dockerfile 中重新定义 C++ 环境,我们可以在构建 Glib、Ruby、R 和 Python 绑定时重用相同的 C++ 基础镜像。这减少了重复并简化了维护,但也使 docker-compose 配置更加复杂。

Docker 构建参数#

构建时参数被下推到 dockerfile 中,以使镜像构建更加灵活。这些参数通常被称为 docker 构建参数,但我们将这些值作为环境变量传递给 docker-compose.yml。构建参数被广泛用于

  • 定义用于缓存的 docker 注册表

  • 平台架构

  • 操作系统和版本

  • 定义依赖项的各种版本

默认参数值存储在顶层的 .env 文件中。有关详细示例,请参阅 docker-compose.yml。

构建脚本#

在 ci/scripts 目录下维护的脚本应保持参数化,但应尽可能简化,以明确封装它负责的任务。就像

  • cpp_build.sh:构建 C++ 实现,但不运行测试。

  • cpp_test.sh:执行 C++ 测试。

  • python_build.sh:构建 Python 绑定,但不运行测试。

  • python_test.sh:执行 Python 测试。

  • docs_build.sh:构建 Sphinx 文档。

  • integration_dask.sh:执行 dask 集成测试。

  • integration_pandas.sh:执行 pandas 集成测试。

  • install_minio.sh:为多个平台安装 minio 服务器。

  • install_conda.sh:为多个平台安装 miniconda。

  • install_gcs_testbench.sh:为多个平台安装 GCS 测试台。

参数化(如 C++ CMake 选项)是通过环境变量实现的,这些环境变量具有有用的默认值,以保持构建配置声明性。

一个很好的例子是 cpp_build.sh 构建脚本,它将环境变量转发为 CMake 选项,因此可以在各种配置中调用相同的脚本,而无需更改它。有关示例,请参阅 docker-compose.yml 的 C++ 镜像中如何传递环境变量。

添加新的镜像#

请参阅 docker-compose.yml 文件中提供的内联注释。