奇点秘诀:如何访问容器内的可执行文件?

Singularity Recipe: How to access executable within container?

我是 Singularity 的初学者。

我想在长运行中实现的目标:我有一个包含一长串依赖关系的编程项目,我希望能够将该程序提供给我公司的其他人,而无需缺少依赖项或错误版本的依赖项导致的错误。
现在的想法是使用 Singularity 来轻松提供工作环境。

为了对此进行测试,我编写了一个 Hello World 应用程序,我现在想将其 运行 放入容器中。我有一个文件夹 HelloWorld/,其中包含 C++ Qt 项目的源代码。然后我写了以下配方文件:

project.recipe

Bootstrap: docker
From: ubuntu:18.04

%setup
    cp -R <some_folder>/HelloWorld ${SINGULARITY_ROOTFS}/HelloWorld

%post
    apt update
    apt-get install -y qt5-default
    apt install -y g++
    apt-get install -y build-essential

    cd HelloWorld
    qmake
    make
    echo "after build:"
    ls

%runscript
    echo "before execution:"
    ls HelloWorld/

    ./HelloWorld/HelloWorld

回声和目录列表用于我当前的调试过程。

我可以使用 sudo singularity build --writable project.img project.recipe 成功构建图像文件。 (我的调试输出显示可执行文件已成功构建。)

现在的问题是,如果我尝试使用 ./project.imgsingularity run project.img 运行 它,它将找不到可执行文件。
使用我的调试输出,我发现 %runscript 中的行使用了容器外部的文件夹。
https://sylabs.io/guides/3.1/user-guide/build_a_container.html 之类的教程让我觉得我的食谱是可行的,但显然不是?

我的问题:

  1. 有什么方法可以让我访问我的可执行文件吗?我叫错了吗?
  2. 我做事的方式是应该做的吗?或者通常会做一些事情,比如将可执行文件从容器外部获取,然后使用容器调用该外部文件?或者是否有不同的最佳实践?
  3. 如果编译后要将可执行文件复制到容器外,我该怎么做?当我在 %post 时如何访问外部文件夹?
  4. 这是我想要实现的最佳工作流程吗?后来,我的想法是将大项目同样复制到容器中,安装或复制依赖项,然后编译项目,最后删除其源代码。我也考虑过使用存储库,但我不能将项目放在一个开放的存储库中,而且我不想存储任何密码。
  1. 首先,使用%files,不要使用%setup%setup 是 运行 作为 root 并且可以直接修改主机服务器。您可能很容易不小心弄坏东西而没有意识到。您可以通过这种方式获得相同的效果:
%files
    some_folder/HelloWorld /HelloWorld
  1. 你说错了。在您的 %setup(希望现在在您的 %files)步骤中,您正在将数据复制到 /HelloWorld。在您的 %runscript 中,您正在调用 ./HelloWorld/HelloWorld,这相当于 $PWD/HelloWorld/HelloWorld。由于奇点自动安装在 $PWD(以及 $HOME 和其他一些目录)中,因此您没有调用您想要调用的内容。

  2. 您不需要将可执行文件复制到容器外部,您只需要确保您正在执行的内容在您认为的位置即可。

  3. 无法访问 %post 中的主机文件系统,您应该先通过 %files 复制所需的所有内容。

  4. 这是一个合理的工作流程。拥有代码的本地私有存储库可能是跟踪您的更改的好主意,但这是您的决定。