{"meta":{"title":"Dockerfile 对 GitHub Actions 的支持","intro":"在为 Docker 容器动作创建 Dockerfile 时，你应该了解一些 Docker 指令如何与 GitHub Actions 以及动作的元数据文件进行交互。","product":"GitHub Actions","breadcrumbs":[{"href":"/zh/actions","title":"GitHub Actions"},{"href":"/zh/actions/reference","title":"参考"},{"href":"/zh/actions/reference/workflows-and-actions","title":"工作流和操作"},{"href":"/zh/actions/reference/workflows-and-actions/dockerfile-support","title":"Dockerfile 支持"}],"documentType":"article"},"body":"# Dockerfile 对 GitHub Actions 的支持\n\n在为 Docker 容器动作创建 Dockerfile 时，你应该了解一些 Docker 指令如何与 GitHub Actions 以及动作的元数据文件进行交互。\n\n### 用户\n\nDocker 操作必须由默认 Docker 用户 (root) 运行。 不要在 `USER` 中使用 `Dockerfile` 指令，因为你将无法访问 `GITHUB_WORKSPACE` 目录。 有关详细信息，请参阅 Docker 文档中的“[变量参考](/zh/actions/reference/workflows-and-actions/variables#default-environment-variables)”和“[USER 参考](https://docs.docker.com/engine/reference/builder/#user)”。\n\n### FROM\n\n`Dockerfile` 中的第一条指令必须为 `FROM`，该指令用于选择 Docker 基础映像。 有关详细信息，请参阅 Docker 文档中的 [FROM 参考](https://docs.docker.com/engine/reference/builder/#from)。\n\n以下是设置 `FROM` 参数时的一些最佳做法：\n\n* 建议使用正式的 Docker 映像。 例如，`python` 或 `ruby`。\n* 使用版本标记（如果有），最好使用主要版本。 例如，请使用 `node:10` 而不是 `node:latest`。\n* 建议使用基于 [Debian](https://www.debian.org/) 操作系统的 Docker 映像。\n\n### WORKDIR\n\nGitHub 设置环境变量中的 `GITHUB_WORKSPACE` 工作目录路径。 建议不要在 `WORKDIR` 中使用 `Dockerfile` 指令。 在操作执行之前，GitHub 会将 `GITHUB_WORKSPACE` 目录挂载到 Docker 镜像中该位置原有内容之上，并将 `GITHUB_WORKSPACE` 设为工作目录。 有关详细信息，请参阅 Docker 文档中的“[变量参考](/zh/actions/reference/workflows-and-actions/variables#default-environment-variables)”和“[WORKDIR 参考](https://docs.docker.com/engine/reference/builder/#workdir)”。\n\n### ENTRYPOINT\n\n如果在操作的元数据文件中定义 `entrypoint`，它将替代 `ENTRYPOINT` 中定义的 `Dockerfile`。 有关详细信息，请参阅“[元数据语法参考](/zh/actions/reference/workflows-and-actions/metadata-syntax#runsentrypoint)”。\n\nDocker `ENTRYPOINT` 指令具有 shell 形式和 exec 形式 。 Docker `ENTRYPOINT` 文档建议使用 \\_\\_ 指令的 `ENTRYPOINT` 形式。 有关 exec 和 shell 形式的详细信息，请参阅 Docker 文档中的 *ENTRYPOINT 参考* 。\n\n不应使用 `WORKDIR` 在 Dockerfile 中指定入口点。 相反，您应使用绝对路径。 有关详细信息，请参阅 [WORKDIR](#workdir)。\n\n如果将容器配置为使用 \\_\\_ 指令的 `ENTRYPOINT` 形式，则在操作的元数据文件中配置的 `args` 将不会在命令 shell 中运行。 如果操作的 `args` 包含环境变量，则不会替换该变量。 例如，使用以下 *exec* 格式将不会打印存储在 `$GITHUB_SHA` 中的值，而是会打印 `\"$GITHUB_SHA\"`。\n\n```dockerfile\nENTRYPOINT [\"echo $GITHUB_SHA\"]\n```\n\n如果需要变量替换，则可以使用 *shell* 形式或直接执行 shell。 例如，如果使用以下 exec 格式，可执行 shell 以打印存储在 \\_\\_ 环境变量中的值。\n\n```dockerfile\nENTRYPOINT [\"sh\", \"-c\", \"echo $GITHUB_SHA\"]\n```\n\n若要将操作的元数据文件中定义的 `args` 提供给使用 \\_\\_ 中的 exec 形式的 Docker 容器，建议创建一个名为 `ENTRYPOINT` 的 shell 脚本，该脚本可通过 `entrypoint.sh` 指令调用：\n\n#### 示例 Dockerfile\n\n```dockerfile\n# Container image that runs your code\nFROM debian:9.5-slim\n\n# Copies your code file from your action repository to the filesystem path `/` of the container\nCOPY entrypoint.sh /entrypoint.sh\n\n# Executes `entrypoint.sh` when the Docker container starts up\nENTRYPOINT [\"/entrypoint.sh\"]\n```\n\n#### 示例 entrypoint.sh 文件\n\n使用上面的示例 Dockerfile，GitHub 会将操作元数据文件中配置的 `args` 作为参数传递给 `entrypoint.sh`。 在 `#!/bin/sh` 文件的顶部添加 [](https://en.wikipedia.org/wiki/Shebang_\\(Unix\\))`entrypoint.sh`，以显式地使用系统的与 [POSIX](https://en.wikipedia.org/wiki/POSIX) 兼容的 shell。\n\n```shell\n#!/bin/sh\n\n# `$#` expands to the number of arguments and `$@` expands to the supplied `args`\nprintf '%d args:' \"$#\"\nprintf \" '%s'\" \"$@\"\nprintf '\\n'\n```\n\n您的代码必须是可执行的。 在工作流中使用 `entrypoint.sh` 文件之前，请确保该文件具有 `execute` 权限。 您可以使用此命令从终端修改权限：\n\n```shell\nchmod +x entrypoint.sh\n```\n\n当 `ENTRYPOINT` shell 脚本不可执行时，你将收到如下所示的错误：\n\n```shell\nError response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused \"exec: \\\"/entrypoint.sh\\\": permission denied\": unknown\n```\n\n### CMD（命令提示符）\n\n如果在操作的元数据文件中定义 `args`，`args` 将替代 `CMD` 中指定的 `Dockerfile` 指令。 有关详细信息，请参阅“[元数据语法参考](/zh/actions/reference/workflows-and-actions/metadata-syntax#runsargs)”。\n\n如果在 `CMD` 中使用 `Dockerfile`，请遵循以下准则：\n\n1. 在操作的自述文件中记录必要的参数，并在 `CMD` 指令的中忽略它们。\n2. 使用默认值，允许不指定任何 `args` 即可使用操作。\n3. 如果操作显示 `--help` 标记或类似项，请使用它让你的操作能够自行记录。\n\n## 支持的 Linux 功能\n\nGitHub Actions 支持 Docker 支持的默认 Linux 功能。 无法添加或删除功能。 有关 Docker 支持的默认 Linux 功能的详细信息，请参阅 Docker 文档中的“[Linux 内核功能](https://docs.docker.com/engine/security/#linux-kernel-capabilities)”。 若要详细了解 Linux 功能，请参阅 Linux 手册页中的“[Linux 功能概述](http://man7.org/linux/man-pages/man7/capabilities.7.html)”。"}