微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 gitlab-ci 作业中将文件从摇杆容器传递到乳胶容器

如何解决在 gitlab-ci 作业中将文件从摇杆容器传递到乳胶容器

我想使用 Gitlab CI 编译一篇 Latex 文章,如 this answer on tex.stackexchange 中所述(gitlab documentation for artifacts显示了类似的 pdf 生成示例)。我使用了期刊编辑提供的特殊乳胶模板。我的 Latex 文章包含使用 R 统计软件制作的数字。 R 和 Latex 是两个具有很多依赖项的大型软件安装,因此我决定使用两个单独的容器进行构建,一个用于使用 R 进行统计分析和可视化,另一个用于将 Latex 文档编译为 pdf。

这里是.gitlab-ci.yml内容

knit_rnw_to_tex:
  image: rocker/verse:4.0.0
  script:
  - Rscript -e "knitr::knit('article.Rnw')"
  artifacts:
    paths:
      - figure/

compile_pdf:
  image: aergus/latex
  script:
  - ls figure
  - latexmk -pdf -bibtex -use-make article.tex
  artifacts:
    paths:
      - article.pdf

在 R "rocker" 容器中执行的 knit_rnw_to_tex 作业成功,我可以从 gitlab "jobs" 页面下载图形工件。第二个作业 compile_pdf 中的问题是 ls figure 向我显示一个文件夹,并且由于缺少数字,Latex 文章编译失败。

  • 应该可以使用工件根据 this answer 和此 well explained forum post 在作业之间传递数据,但它们仅使用一个容器来处理不同的作业。在我的情况下它不起作用。可能是因为我使用了两个不同的容器?
  • 另一种解决方案是仅使用 Rocker/tidyverse 容器并在其中安装 latexmk,但 apt install latexmk 的安装因未知原因而失败。也许是因为它有一百多个依赖项,这对于 gitlab-CI 来说太多了?
  • dependencies”关键字可以根据 that answer 提供帮助,但是在我使用它时仍然无法使用这些工件。
  • 如何将工件从一项工作传递到另一项工作?
  • 我应该按照 docs.gitlab.com / caching 中的说明使用缓存吗?

解决方法

感谢您的评论,因为我想确定您是如何做到的。示例也会有所帮助,但我现在是通用的(使用 docker)。

要运行多个容器,您需要一个 (The Docker executor)

引用上面的 documentation

Docker 执行器与 GitLab CI 一起使用时,连接到 Docker 引擎并使用在单独和隔离的容器中运行每个构建 在 .gitlab-ci.yml 和 符合config.toml

工作流程

Docker executor 将作业分为多个步骤:

  • 准备:创建并启动服务。
  • 预工作:克隆、恢复缓存和下载先前阶段的工件。这是在一个特殊的 Docker 镜像上运行的。
  • 工作:用户构建。这是在用户提供的 Docker 映像上运行的。
  • Post-job:创建缓存,将工件上传到 GitLab。这是在一个特殊的 Docker 镜像上运行的。

您的 config.toml 可能如下所示:

[runners.docker]
  image = "rocker/verse:4.0.0"
  builds_dir = /home/builds/rocker

[[runners.docker.services]]
  name = "aergus/latex"
  alias = "latex"

来自上面链接的文档:

image 关键字

image 关键字是本地 Docker 引擎中存在的 Docker 镜像的名称(列出所有带有 docker 镜像的镜像)或可以在 Docker Hub 上找到的任何镜像。有关镜像和 Docker Hub 的更多信息,请阅读 Docker 基础文档。

简而言之,镜像是指 Docker 镜像,它将用于创建一个容器,您的构建将在该容器上运行。

如果不指定 namespace,Docker 表示包含所有官方镜像的库。这就是为什么您会多次看到 .gitlab-ci.yml 和 config.toml 中省略了库部分的原因。例如,您可以定义像 image: ruby:2.6 这样的图像,它是图像的快捷方式:library/ruby:2.6

然后,对于每个 Docker 镜像,都有标记,表示镜像的版本。这些是在图像名称后用冒号 (:) 定义的。例如,对于 Ruby,您可以在 docker hub 处查看支持的标签。如果您不指定标签(如 image: ruby),则默认为最新。

您选择通过 image 指令运行构建的 image 必须在其操作系统 PATH 中有一个工作外壳。支持的 shell 是 shbashpwsh(从 13.9 开始)用于 Linux,以及用于 Windows 的 PowerShell。 GitLab Runner 无法使用底层操作系统系统调用(例如 exec)执行命令。

services 关键字

services 关键字仅定义了在构建期间运行的另一个 Docker 映像,并链接到 image 关键字定义的 Docker 映像。这允许您在构建期间访问服务映像。

service 映像可以运行任何应用程序,但最常见的用例是运行数据库容器,例如 mysql。与每次构建项目时都安装 mysql 相比,使用现有映像并将其作为附加容器运行更容易、更快捷。

您可以在 CI services examples 的相关文档中看到一些广泛使用的服务示例。

如果需要,您可以为每个服务分配一个 alias

至于您的问题:

应该可以使用工件在作业之间传递数据 根据这个答案和这个解释得很好的论坛帖子,但是 他们只使用一个容器来处理不同的工作。它不适用于我的 案件。可能是因为我使用了两个不同的容器?

构建和缓存存储(来自文档)

默认情况下,Docker 执行器将所有构建存储在 /builds/<namespace>/<project-name> 中,所有缓存存储在 /cache(容器内部)中。您可以通过在 /builds 中的 /cache 部分下定义 builds_dircache_dir 选项来覆盖 [[runners]]config.toml 目录。这将修改数据在容器内的存储位置。

如果您修改了 /cache 存储路径,您还需要通过在 volumes = ["/my/cache/"][runners.docker] 部分下的 config.toml 中定义来确保将此目录标记为持久性.

  • builds_dir -> 构建存储在所选执行程序上下文中的目录的绝对路径。例如,本地、Docker 或 SSH。

The [[runners]] section documentation

您可能已经注意到我已将您的 build_dir 文件中的 toml 自定义为 /home/builds/rocker,请将其调整为您自己的路径。

如何将工件从一项工作传递到另一项工作?

您可以使用 build_dir 指令。第二种选择是使用 Job Artifacts API

我应该按照 docs.gitlab.com/caching 中的说明使用缓存吗?

是的,您应该使用 cache 来存储项目依赖项。优点是您只从 Internet 获取依赖项一次,然后后续运行速度要快得多,因为它们可以跳过此步骤。 Artifacts 用于在构建阶段之间共享结果。

我希望现在更清楚了,我已经为您指明了正确的方向。

,

这两个不同的图像不是您出现问题的原因。工件保存在一个图像中(似乎有效),然后在另一个图像中恢复。因此,我建议不要构建(和维护)单个图像,因为这在这里不是必需的。

您遇到问题的原因是您缺少通知 gitlab 作业之间依赖关系的构建阶段。因此,我建议您在 .gitlab-ci.yml 中指定阶段及其各自的工作:

stages:
  - do_stats
  - do_compile_pdf

knit_rnw_to_tex:
  stage: do_stats
  image: rocker/verse:4.0.0
  script:
  - Rscript -e "knitr::knit('article.Rnw')"
  artifacts:
    paths:
      - figure/

compile_pdf:
  stage: do_compile_pdf
  image: aergus/latex
  script:
  - ls figure
  - latexmk -pdf -bibtex -use-make article.tex
  artifacts:
    paths:
      - article.pdf

上下文:

默认情况下,如果您添加相应的规范,先前构建阶段的所有工件都将在后续阶段可用。

如果不指定任何阶段,gitlab 会将所有作业放入默认的 test 阶段并并行执行,假设它们是独立的并且不需要彼此的工件。它仍然会存储工件,但不会在作业之间提供它们。这大概是导致您出现问题的原因。

至于 cache:工件是您在构建阶段之间传递文件的方式。缓存很好,缓存。在实践中,它们用于诸如外部包之类的东西,以避免多次下载它们,see here。在有多个不同跑步者的情况下,缓存有点不可预测。它们仅用于性能原因,并且使用 cache 而不是使用工件系统在作业之间传递文件是一个巨大的反模式。

编辑:我不太清楚您的 knitr 设置是什么,但是如果您从 article.tex 生成 article.Rnw,那么您可能需要将其添加到您的 {{ 1}} 也是。

此外,artifacts 用于测试数据库的 MySQL 服务器,或用于构建 docker 镜像的 dind(docker 中的 docker)守护进程。在您的情况下,这应该不是必需的。同样,您应该不需要从默认值更改任何运行器配置(在它们各自的 services 中)。

Edit2:我添加了一个 MWE here,它适用于我的 gitlab 设置。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。