{"meta":{"title":"创建 Docker 容器操作","intro":"本教程将介绍如何生成 Docker 容器操作。","product":"GitHub Actions","breadcrumbs":[{"href":"/zh/actions","title":"GitHub Actions"},{"href":"/zh/actions/tutorials","title":"教程"},{"href":"/zh/actions/tutorials/use-containerized-services","title":"使用容器化服务"},{"href":"/zh/actions/tutorials/use-containerized-services/create-a-docker-container-action","title":"创建 Docker 容器操作"}],"documentType":"article"},"body":"# 创建 Docker 容器操作\n\n本教程将介绍如何生成 Docker 容器操作。\n\n## 简介\n\n在本指南中，您将了解创建和使用打包的 Docker 容器操作所需的基本组件。 本指南的重点是打包操作所需的组件，因此很少讲操作代码的功能。 操作将在日志文件中打印“Hello World”或“Hello \\[who-to-greet]”（如果你提供自定义名称）。\n\n完成此项目后，您应了解如何构建自己的 Docker 容器操作和在工作流程测试该操作。\n\n自托管运行器必须使用 Linux 操作系统并安装 Docker 才能运行 Docker 容器操作。 有关自托管运行程序要求的详细信息，请参阅“[自托管运行程序](/zh/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#requirements-for-self-hosted-runner-machines)”。\n\n> \\[!WARNING]\n> 创建工作流和操作时，应始终考虑代码是否可能执行潜在攻击者的不受信任的输入。 某些上下文应被视为不受信任的输入，因为攻击者可能会插入自己的恶意内容。 有关详细信息，请参阅“[安全使用指南](/zh/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections)”。\n\n## 先决条件\n\n* 必须在 GitHub 上创建存储库并将其克隆到工作站。 有关详细信息，请参阅 [创建新仓库](/zh/repositories/creating-and-managing-repositories/creating-a-new-repository) 和 [克隆仓库](/zh/repositories/creating-and-managing-repositories/cloning-a-repository)。\n* 如果存储库使用 Git LFS，则存储库的存档中必须包含对象。 有关详细信息，请参阅“[管理仓库存档中的 Git LFS 对象](/zh/enterprise-cloud@latest/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/managing-git-lfs-objects-in-archives-of-your-repository)”。\n* 您可能会发现它有助于你基本了解 GitHub Actions、环境变量和 Docker 容器文件系统。 有关详细信息，请参阅 [在变量中存储信息](/zh/actions/learn-github-actions/variables) 和 [GitHub 托管的运行程序](/zh/enterprise-cloud@latest/actions/using-github-hosted-runners/about-github-hosted-runners#docker-container-filesystem)。\n\n## 创建 Dockerfile\n\n在新的 `hello-world-docker-action` 目录中，创建一个新的 `Dockerfile` 文件。 如果遇到问题，请确保正确大写你的文件名（用大写字母 `D`，但不要大写 `f`）。 有关详细信息，请参阅“[Dockerfile 对 GitHub Actions 的支持](/zh/actions/creating-actions/dockerfile-support-for-github-actions)”。\n\n```\n          **Dockerfile**\n```\n\n```dockerfile copy\n# Container image that runs your code\nFROM alpine:3.10\n\n# Copies your code file from your action repository to the filesystem path `/` of the container\nCOPY entrypoint.sh /entrypoint.sh\n\n# Code file to execute when the docker container starts up (`entrypoint.sh`)\nENTRYPOINT [\"/entrypoint.sh\"]\n```\n\n## 创建操作元数据文件\n\n在上面创建的 `action.yml` 目录中创建一个新的 `hello-world-docker-action` 文件。 有关详细信息，请参阅“[元数据语法参考](/zh/actions/creating-actions/metadata-syntax-for-github-actions)”。\n\naction.yml\n\n```yaml copy\n# action.yml\nname: 'Hello World'\ndescription: 'Greet someone and record the time'\ninputs:\n  who-to-greet:  # id of input\n    description: 'Who to greet'\n    required: true\n    default: 'World'\noutputs:\n  time: # id of output\n    description: 'The time we greeted you'\nruns:\n  using: 'docker'\n  image: 'Dockerfile'\n  args:\n    - ${{ inputs.who-to-greet }}\n```\n\n此元数据定义一个 `who-to-greet` 输入和一个 `time` 输出参数。 若要将输入传递给 Docker 容器，应使用 `inputs` 声明输入并在 `args` 关键字中传递输入。 你包含在 `args` 中的所有内容都会传递给容器，但为了让用户更好地发现你的操作，建议使用输入。\n\nGitHub 将从 `Dockerfile` 构建映像，然后使用此映像在新容器中运行命令。\n\n## 编写操作代码\n\n您可以选择任何基础 Docker 映像，并因此为您的操作选择任何语言。 以下 shell 脚本示例使用 `who-to-greet` 输入变量在日志文件中打印“Hello \\[who-to-greet]”。\n\n接下来，该脚本会获取当前时间并将其设置为作业中稍后运行的操作可以使用的输出变量。 为了使 GitHub 能够识别输出变量，必须将它们写入 `$GITHUB_OUTPUT` 环境文件：`echo \"<output name>=<value>\" >> $GITHUB_OUTPUT`。 有关详细信息，请参阅“[GitHub Actions 的工作流命令](/zh/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter)”。\n\n1. 在 `entrypoint.sh` 目录中创建一个新的 `hello-world-docker-action` 文件。\n\n2. 将以下代码添加到 `entrypoint.sh` 文件。\n\n   entrypoint.sh\n\n   ```shell copy\n   #!/bin/sh -l\n\n   echo \"Hello $1\"\n   time=$(date)\n   echo \"time=$time\" >> $GITHUB_OUTPUT\n\n   ```\n\n   如果 `entrypoint.sh` 执行没有任何错误，则操作的状态设置为 `success`。 您还可以在操作的代码中显式设置退出代码以提供操作的状态。 有关详细信息，请参阅“[为操作设置退出代码](/zh/actions/creating-actions/setting-exit-codes-for-actions)”。\n\n3. 使 `entrypoint.sh` 文件成为可执行文件。 Git 提供了一种方法来显式更改文件的权限模式，以便每次有克隆/分支时都不会重置该文件。\n\n   ```shell copy\n   git add entrypoint.sh\n   git update-index --chmod=+x entrypoint.sh\n   ```\n\n4. （可选）若要检查 git 索引中文件的权限模式，请运行以下命令。\n\n   ```shell copy\n   git ls-files --stage entrypoint.sh\n   ```\n\n   类似于 `100755 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       entrypoint.sh` 的输出表示文件具有可执行权限。 在本例中，`755` 表示可执行权限。\n\n## 创建自述文件\n\n要让人们了解如何使用您的操作，您可以创建自述文件。 自述文件在您计划公开分享操作时最有用，但也是提醒您或您的团队如何使用该操作的绝佳方式。\n\n在 `hello-world-docker-action` 目录中，创建一个用于指定以下信息的 `README.md` 文件：\n\n* 操作用途的详细说明。\n* 必需的输入和输出参数。\n* 可选输入和输出参数。\n* 操作使用的密钥。\n* 操作使用的环境变量。\n* 在工作流中使用您的操作的示例。\n\n  ```\n          **README.md**\n  ```\n\n```markdown copy\n# Hello world docker action\n\nThis action prints \"Hello World\" or \"Hello\" + the name of a person to greet to the log.\n\n## Inputs\n\n## `who-to-greet`\n\n**Required** The name of the person to greet. Default `\"World\"`.\n\n## Outputs\n\n## `time`\n\nThe time we greeted you.\n\n## Example usage\n\nuses: actions/hello-world-docker-action@v2\nwith:\n  who-to-greet: 'Mona the Octocat'\n```\n\n## 提交、标记和推送操作\n\n从终端中提交 `action.yml`、`entrypoint.sh`、`Dockerfile` 和 `README.md` 文件。\n\n最佳做法是同时为操作版本添加版本标记。 有关对操作进行版本控制的详细信息，请参阅“[关于自定义操作](/zh/actions/creating-actions/about-custom-actions#using-release-management-for-actions)”。\n\n```shell copy\ngit add action.yml entrypoint.sh Dockerfile README.md\ngit commit -m \"My first action is ready\"\ngit tag -a -m \"My first action release\" v1\ngit push --follow-tags\n```\n\n## 在工作流程中测试您的操作\n\n现在，您已准备好在工作流程中测试您的操作。\n\n* 当操作位于专用仓库中时，你可以控制谁可以访问它。 有关详细信息，请参阅“[管理存储库的GitHub Actions设置](/zh/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#allowing-access-to-components-in-a-private-repository)”。\n* 当操作位于内部仓库中时，该操作只能在同一仓库的工作流中使用。\n* 位于任何存储库内的工作流均可使用公共操作。\n\n### 使用公共操作的示例\n\n下面的工作流代码使用公共 \\_\\_ 存储库中的已完成的 `actions/hello-world-docker-action` 操作。 将以下工作流示例代码复制到 `.github/workflows/main.yml` 文件中，但将 `actions/hello-world-docker-action` 替换为存储库和操作名称。 还可以将 `who-to-greet` 输入替换为你的名称。 公共操作即使未发布到 GitHub Marketplace 也可使用。 有关详细信息，请参阅“[在 GitHub Marketplace 中发布操作](/zh/actions/creating-actions/publishing-actions-in-github-marketplace#publishing-an-action)”。\n\n.github/workflows/main.yml\n\n```yaml copy\non: [push]\n\njobs:\n  hello_world_job:\n    runs-on: ubuntu-latest\n    name: A job to say hello\n    steps:\n      - name: Hello world action step\n        id: hello\n        uses: actions/hello-world-docker-action@v2\n        with:\n          who-to-greet: 'Mona the Octocat'\n      # Use the output from the `hello` step\n      - name: Get the output time\n        run: echo \"The time was ${{ steps.hello.outputs.time }}\"\n```\n\n### 使用私有操作的示例\n\n将以下示例工作流代码复制到操作存储库中的 `.github/workflows/main.yml` 文件中。 还可以将 `who-to-greet` 输入替换为你的名称。 此专用操作无法发布到 GitHub Marketplace，只能在此仓库中使用。\n\n.github/workflows/main.yml\n\n```yaml copy\non: [push]\n\njobs:\n  hello_world_job:\n    runs-on: ubuntu-latest\n    name: A job to say hello\n    steps:\n      # To use this repository's private action,\n      # you must check out the repository\n      - name: Checkout\n        uses: actions/checkout@v5\n      - name: Hello world action step\n        uses: ./ # Uses an action in the root directory\n        id: hello\n        with:\n          who-to-greet: 'Mona the Octocat'\n      # Use the output from the `hello` step\n      - name: Get the output time\n        run: echo \"The time was ${{ steps.hello.outputs.time }}\"\n```\n\n从存储库中，单击“操作”选项卡，然后选择最新的工作流运行。 在“作业”下或可视化图中，单击“表示问候的作业” 。\n\n单击“Hello world action step”，应该会看到“Hello Mona the Octocat”或日志中输出的用于 `who-to-greet` 输入的名称。 要查看时间戳，单击“获取输出时间”。\n\n## 访问容器操作创建的文件\n\n当容器操作运行时，它会自动将运行器上的默认工作目录 (`GITHUB_WORKSPACE`) 映射到容器上的 `/github/workspace` 目录。 添加到容器上此目录的任何文件都可用于同一作业中的任何后续步骤。 例如，如果你有一个构建项目的容器操作，并且想要将构建输出作为工件上传，则可以使用以下步骤。\n\n```\n          **workflow.yml**\n```\n\n```yaml copy\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v5\n\n      # Output build artifacts to /github/workspace on the container.\n      - name: Containerized Build\n        uses: ./.github/actions/my-container-action\n\n      - name: Upload Build Artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: workspace_artifacts\n          path: ${{ github.workspace }}\n```\n\n有关将生成输出作为制品上传的详细信息，请参阅“[使用工作流工件存储和共享数据](/zh/actions/using-workflows/storing-workflow-data-as-artifacts)”。\n\n## GitHub.com\n\n上的示例 Docker 容器操作\n\n可以在 GitHub.com\n上找到许多 Docker 容器操作示例。\n\n* [github/issue-metrics](https://github.com/github/issue-metrics)\n* [microsoft/infersharpaction](https://github.com/microsoft/infersharpaction)\n* [microsoft/ps-docs](https://github.com/microsoft/ps-docs)"}