Skip to main content

创建 Docker 容器操作

本指南向您展示构建 Docker 容器操作所需的最少步骤。

简介

在本指南中,您将了解创建和使用打包的 Docker 容器操作所需的基本组件。 本指南的重点是打包操作所需的组件,因此很少讲操作代码的功能。 操作将在日志文件中打印“Hello World”或“Hello [who-to-greet]”(如果您提供自定义名称)。

完成此项目后,您应了解如何构建自己的 Docker 容器操作和在工作流程测试该操作。

自托管运行器必须使用 Linux 操作系统并安装 Docker 才能运行 Docker 容器操作。 有关自托管运行器要求的详细信息,请参阅“关于自托管运行程序”。

Warning

创建工作流和操作时,应始终考虑代码是否可能执行潜在攻击者的不受信任的输入。 某些上下文应被视为不受信任的输入,因为攻击者可能会插入自己的恶意内容。 有关详细信息,请参阅“GitHub Actions 的安全强化”。

先决条件

创建 Dockerfile

在新的 hello-world-docker-action 目录中,创建一个新的 Dockerfile 文件。 如果你有问题,请确保你的文件名正确大写(使用大写字母 D 但不要大写 f)。 有关详细信息,请参阅“Dockerfile 对 GitHub Actions 的支持”。

Dockerfile

Dockerfile
# Container image that runs your code
FROM alpine:3.10

# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh

# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

创建操作元数据文件

在上面创建的 hello-world-docker-action 目录中创建一个新的 action.yml 文件。 有关详细信息,请参阅“GitHub Actions 的元数据语法”。

action.yml

YAML
# action.yml
name: 'Hello World'
description: 'Greet someone and record the time'
inputs:
  who-to-greet:  # id of input
    description: 'Who to greet'
    required: true
    default: 'World'
outputs:
  time: # id of output
    description: 'The time we greeted you'
runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.who-to-greet }}

此元数据定义一个 who-to-greet 输入和一个 time 输出参数。 若要将输入传递给 Docker 容器,应使用 inputs 声明输入并在 args 关键字中传递输入。 你包含在 args 中的所有内容都会传递给容器,但为了让用户更好地发现你的操作,建议使用输入。

GitHub 将从 Dockerfile 构建映像,然后使用此映像在新容器中运行命令。

编写操作代码

您可以选择任何基础 Docker 映像,并因此为您的操作选择任何语言。 以下 shell 脚本示例使用 who-to-greet 输入变量在日志文件中打印“Hello [who-to-greet]”。

接下来,该脚本会获取当前时间并将其设置为作业中稍后运行的操作可以使用的输出变量。 为了使 GitHub 能够识别输出变量,必须将它们写入 $GITHUB_OUTPUT 环境文件:echo "<output name>=<value>" >> $GITHUB_OUTPUT。 有关详细信息,请参阅“GitHub Actions 的工作流命令”。

  1. hello-world-docker-action 目录中创建一个新的 entrypoint.sh 文件。

  2. 将以下代码添加到 entrypoint.sh 文件。

    entrypoint.sh

    Shell
    #!/bin/sh -l
    
    echo "Hello $1"
    time=$(date)
    echo "time=$time" >> $GITHUB_OUTPUT
    
    

    如果 entrypoint.sh 执行没有任何错误,则操作的状态设置为 success。 您还可以在操作的代码中显式设置退出代码以提供操作的状态。 有关详细信息,请参阅“设置操作的退出代码”。

  3. 使 entrypoint.sh 文件成为可执行文件。 Git 提供了一种方法来显式更改文件的权限模式,以便每次有克隆/分支时都不会重置该文件。

    Shell
    git add entrypoint.sh
    git update-index --chmod=+x entrypoint.sh
    
  4. (可选)若要检查 git 索引中文件的权限模式,请运行以下命令。

    Shell
    git ls-files --stage entrypoint.sh
    

    类似于 100755 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 entrypoint.sh 的输出表示文件具有可执行权限。 在本例中,755 表示可执行权限。

创建自述文件

要让人们了解如何使用您的操作,您可以创建自述文件。 自述文件在您计划公开分享操作时最有用,但也是提醒您或您的团队如何使用该操作的绝佳方式。

hello-world-docker-action 目录中,创建一个用于指定以下信息的 README.md 文件:

  • 操作用途的详细说明。
  • 必需的输入和输出参数。
  • 可选输入和输出参数。
  • 操作使用的密钥。
  • 操作使用的环境变量。
  • 如何在工作流中使用操作的示例。

README.md

Markdown
# Hello world docker action

This action prints "Hello World" or "Hello" + the name of a person to greet to the log.

## Inputs

## `who-to-greet`

**Required** The name of the person to greet. Default `"World"`.

## Outputs

## `time`

The time we greeted you.

## Example usage

uses: actions/hello-world-docker-action@v2
with:
  who-to-greet: 'Mona the Octocat'

提交、标记和推送操作到 GitHub

从终端中提交 action.ymlentrypoint.shDockerfileREADME.md 文件。

最佳做法是同时为操作版本添加版本标记。 有关对操作进行版本控制的详细信息,请参阅“关于自定义操作”。

Shell
git add action.yml entrypoint.sh Dockerfile README.md
git commit -m "My first action is ready"
git tag -a -m "My first action release" v1
git push --follow-tags

在工作流程中测试您的操作

现在,您已准备好在工作流程中测试您的操作。

  • 位于任何存储库内的工作流均可使用公共操作。

使用公共操作的示例

以下工作流代码使用公共 actions/hello-world-docker-action 存储库中已完成的 hello world 操作。 将以下工作流示例代码复制到 .github/workflows/main.yml 文件中,但将 actions/hello-world-docker-action 替换为存储库和操作名称。 还可以将 who-to-greet 输入替换为你的名称。 公共操作即使未发布到 GitHub Marketplace 也可使用。 有关详细信息,请参阅“在 GitHub Marketplace 中发布操作”。

.github/workflows/main.yml

YAML
on: [push]

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    name: A job to say hello
    steps:
      - name: Hello world action step
        id: hello
        uses: actions/hello-world-docker-action@v2
        with:
          who-to-greet: 'Mona the Octocat'
      # Use the output from the `hello` step
      - name: Get the output time
        run: echo "The time was ${{ steps.hello.outputs.time }}"

使用私有操作的示例

将以下示例工作流代码复制到操作存储库中的 .github/workflows/main.yml 文件中。 还可以将 who-to-greet 输入替换为你的名称。 此操作不能发布到 GitHub Marketplace,并且只能在此仓库中使用。

.github/workflows/main.yml

YAML
on: [push]

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    name: A job to say hello
    steps:
      # To use this repository's private action,
      # you must check out the repository
      - name: Checkout
        uses: actions/checkout@v4
      - name: Hello world action step
        uses: ./ # Uses an action in the root directory
        id: hello
        with:
          who-to-greet: 'Mona the Octocat'
      # Use the output from the `hello` step
      - name: Get the output time
        run: echo "The time was ${{ steps.hello.outputs.time }}"

从存储库中,单击“操作”选项卡,然后选择最新的工作流运行。 在“作业”下或可视化图中,单击“表示问候的作业” 。

单击“Hello world action step”,应该会看到“Hello Mona the Octocat”或日志中输出的用于 who-to-greet 输入的名称。 要查看时间戳,单击“获取输出时间”。

访问容器操作创建的文件

当容器操作运行时,它将使用容器上的 /github/workspace 目录自动映射运行器上的默认工作目录 (GITHUB_WORKSPACE)。 添加到容器上此目录的任何文件都可用于同一作业中的任何后续步骤。 例如,如果你有一个生成项目的容器操作,并且想要将生成输出作为项目上传,则可以使用以下步骤。

workflow.yml

YAML
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # Output build artifacts to /github/workspace on the container.
      - name: Containerized Build
        uses: ./.github/actions/my-container-action

      - name: Upload Build Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: workspace_artifacts
          path: ${{ github.workspace }}

有关将生成输出作为项目上传的详细信息,请参阅“从工作流存储和共享数据”。

GitHub.com

上的示例 Docker 容器操作

可以在 GitHub.com 上找到许多 Docker 容器操作示例。