如何解决在 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 是 sh
、bash
和 pwsh
(从 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_dir
和 cache_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 举报,一经查实,本站将立刻删除。