通常有两种方法可以从存储库中获取可供您构建和运行的 Docker 容器使用的文件。您可以 (1) 在构建映像时将文件添加到映像中,或者 (2) 在运行映像时将文件装载到容器中。还有其他一些方法,例如指定卷,但这可能超出了本例的范围。
Dockerfiledocker-action/Dockerfile
不复制任何文件,除了entrypoint.sh
脚本。你的entrypoint.sh
运行容器时也不提供任何挂载点。因此,您观察到的结果是基于这些事实的预期结果。
为了解决这个问题,您必须 (1) 添加COPY
/ADD
对 Dockerfile 执行以下语句,将文件复制到映像中(并设置适当的构建上下文)或 (2) 在运行时将文件安装到容器中,方法是添加-v /source-path:/container-path
to the docker run
命令在你的entrypoint.sh
.
参见参考资料:
-
COPY
参考 https://docs.docker.com/engine/reference/builder/#copy
- Docker 运行参考 https://docs.docker.com/engine/reference/commandline/run
不过,这种构建另一个容器只是为了获取用户提供的 python 版本的方法对于 GitHub Actions 来说是一种非常值得怀疑的做法,应该避免。考虑依靠安装Python https://github.com/actions/setup-python行动代替。
docker-in-docker 问题
然而,如果您继续此路线并想要安装目录,则必须记住,在调用时docker
在 GitHub 上的 docker 操作中,挂载规范中的文件系统是指 docker 主机的文件系统,而不是容器的文件系统。
它可以在我的机器上运行吗?
与您跑步时可能遇到的情况相反docker
例如,在本地系统上,这在 GitHub 中不起作用——工作目录未安装:
docker run -v $(pwd):/opt/workspace \
--workdir /opt/workspace \
--entrypoint /bin/ls \
my-container "-R"
这也不起作用:
docker run -v $GITHUB_WORKSPACE:$GITHUB_WORKSPACE \
--workdir $GITHUB_WORKSPACE \
--entrypoint /bin/ls \
my-container "-R"
如果你在本地运行 docker 的系统上尝试的话,这种事情会工作得很好。是什么赋予了?
对付恶魔(守护进程)
在操作中,文件检出到的起始工作目录$GITHUB_WORKSPACE
。在 docker actions 中,就是/github/workspace
。工作区文件将在以下情况下填充到工作区中:your由 Actions 运行程序运行的操作mounting运行 docker 守护进程的主机的工作区。
您可以在操作开始时运行的命令中看到:
/usr/bin/docker run --name f884202608aa2bfab75b6b7e1f87b3cd153444_f687df --label f88420 --workdir /github/workspace --rm -e INPUT_ALPINE-VERSION -e HOME -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE -e RUNNER_TEMP -e RUNNER_WORKSPACE -e ACTIONS_RUNTIME_URL -e ACTIONS_RUNTIME_TOKEN -e ACTIONS_CACHE_URL -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/my-repo/my-repo":"/github/workspace" f88420:2608aa2bfab75b6b7e1f87b3cd153444 "3.9.5"
重要的是:
-v "/home/runner/work/my-repo/my-repo":"/github/workspace"
-v "/var/run/docker.sock":"/var/run/docker.sock"
/home/runner/work/my-repo/my-repo
是主机上存储库文件所在的路径。如前所述,第一行是将其安装到/github/workspace
当它运行时在你的操作容器中。
第二行是将 docker 套接字从主机安装到操作容器。这意味着任何时候你打电话docker
在您的操作中,您实际上是在与容器外部的 docker 守护进程进行对话。这很重要,因为这意味着当you使用-v
争论inside您的操作中,参数需要反映容器外部存在的目录。
所以,你实际上需要做的是:
docker run -v /home/runner/work/my-repo/my-repo:/opt/workspace \
--workdir /opt/workspace \
--entrypoint /bin/ls \
my-container "-R"
成为对别人有用的人
那行得通。如果您仅将其用于项目本身。但是,如果您希望其他项目可以使用此操作,那么您(除其他外)还有一个遗留问题。您如何知道工作区在主机上的位置?毕竟,每个存储库的该路径都会改变。 GitHub 也不保证这些路径。它们在不同平台上可能有所不同,或者您的操作可能在自托管运行器上运行。
那么你对这个问题满意吗?不幸的是,没有内置的环境变量指向您特别需要的这个目录。但是,通过依赖实现细节,您可能能够摆脱使用$RUNNER_WORKSPACE
变量,在本例中将指向/home/runner/work/your-project
。这里和原产地不是同一个地方$GITHUB_WORKSPACE
但已经很接近了。您可以使用GITHUB_REPOSITORY
变量来构建路径,尽管不能保证始终如此:afaik:
PROJECT_NAME="$(basename ${GITHUB_REPOSITORY})"
WORKSPACE="${RUNNER_WORKSPACE}/${PROJECT_NAME}"
您还需要修复一些其他问题,例如您构建的工作目录形式。
TL;DR
运行时需要在容器中挂载文件。在 GitHub 中,您正在运行 docker-in-docker,因此您需要用于挂载文件的路径会有所不同,因此您需要找到要传递到的正确路径docker
当从操作容器内调用时。
您链接的示例项目的最低工作解决方案是这样的entrypoint.sh
在仓库的根目录中看起来像这样:
#!/usr/bin/env sh
ALPINE_VERSION=$1
docker build -t docker-action \
-f ./docker-action/Dockerfile \
--build-arg alpine_version="$ALPINE_VERSION" \
./docker-action
PROJECT_NAME="$(basename ${GITHUB_REPOSITORY})"
WORKSPACE="${RUNNER_WORKSPACE}/${PROJECT_NAME}"
docker run --workdir=$GITHUB_WORKSPACE \
-v $WORKSPACE:$GITHUB_WORKSPACE \
docker-action "$@"
您的操作可能还有更多问题,具体取决于它的作用,例如为“内部”容器提供该操作的所有默认和用户定义的环境变量(如果这很重要)。
那么,这可能吗?当然。仅仅获得 alpine/python 的动态版本是否合理?我不这么认为。可能有更好的方法来完成你想做的事情,比如使用setup-python
,但这听起来像是一个不同的问题。