简介
在本指南中,您将了解创建和使用打包的 Docker 容器操作所需的基本组件。 本指南的重点是打包操作所需的组件,因此很少讲操作代码的功能。 操作将在日志文件中打印“Hello World”或“Hello [who-to-greet]”(如果您提供自定义名称)。
完成此项目后,您应了解如何构建自己的 Docker 容器操作和在工作流程测试该操作。
自托管运行器必须使用 Linux 操作系统并安装 Docker 才能运行 Docker 容器操作。 有关自托管运行器要求的详细信息,请参阅“关于自托管运行程序”。
Warning
创建工作流和操作时,应始终考虑代码是否可能执行潜在攻击者的不受信任的输入。 某些上下文应被视为不受信任的输入,因为攻击者可能会插入自己的恶意内容。 有关详细信息,请参阅“GitHub Actions 的安全强化”。
先决条件
- 必须在 GitHub 上创建存储库并将其克隆到工作站。 有关详细信息,请参阅“创建新仓库”和“克隆仓库”。
- 如果存储库使用 Git LFS,则存储库的存档中必须包含对象。 有关详细信息,请参阅“管理仓库存档中的 Git LFS 对象”。
- 您可能会发现它有助于你基本了解 GitHub Actions、环境变量和 Docker 容器文件系统。 有关详细信息,请参阅“在变量中存储信息”和“使用 GitHub 托管的运行器”。
创建 Dockerfile
在新的 hello-world-docker-action
目录中,创建一个新的 Dockerfile
文件。 如果你有问题,请确保你的文件名正确大写(使用大写字母 D
但不要大写 f
)。 有关详细信息,请参阅“Dockerfile 对 GitHub Actions 的支持”。
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"]
# 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
# 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 }}
# 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 的工作流命令”。
-
在
hello-world-docker-action
目录中创建一个新的entrypoint.sh
文件。 -
将以下代码添加到
entrypoint.sh
文件。entrypoint.sh
Shell #!/bin/sh -l echo "Hello $1" time=$(date) echo "time=$time" >> $GITHUB_OUTPUT
#!/bin/sh -l echo "Hello $1" time=$(date) echo "time=$time" >> $GITHUB_OUTPUT
如果
entrypoint.sh
执行没有任何错误,则操作的状态设置为success
。 您还可以在操作的代码中显式设置退出代码以提供操作的状态。 有关详细信息,请参阅“设置操作的退出代码”。 -
使
entrypoint.sh
文件成为可执行文件。 Git 提供了一种方法来显式更改文件的权限模式,以便每次有克隆/分支时都不会重置该文件。Shell git add entrypoint.sh git update-index --chmod=+x entrypoint.sh
git add entrypoint.sh git update-index --chmod=+x entrypoint.sh
-
(可选)若要检查 git 索引中文件的权限模式,请运行以下命令。
Shell git ls-files --stage entrypoint.sh
git ls-files --stage entrypoint.sh
类似于
100755 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 entrypoint.sh
的输出表示文件具有可执行权限。 在本例中,755
表示可执行权限。
创建自述文件
要让人们了解如何使用您的操作,您可以创建自述文件。 自述文件在您计划公开分享操作时最有用,但也是提醒您或您的团队如何使用该操作的绝佳方式。
在 hello-world-docker-action
目录中,创建一个用于指定以下信息的 README.md
文件:
- 操作用途的详细说明。
- 必需的输入和输出参数。
- 可选输入和输出参数。
- 操作使用的密钥。
- 操作使用的环境变量。
- 如何在工作流中使用操作的示例。
README.md
# 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'
# 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.yml
、entrypoint.sh
、Dockerfile
和 README.md
文件。
最佳做法是同时为操作版本添加版本标记。 有关对操作进行版本控制的详细信息,请参阅“关于自定义操作”。
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
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
在工作流程中测试您的操作
现在,您已准备好在工作流程中测试您的操作。
- 当操作位于专用存储库中时,你可以控制谁可以访问它。 有关详细信息,请参阅“管理存储库的 GitHub Actions 设置”。
- 位于任何存储库内的工作流均可使用公共操作。
使用公共操作的示例
以下工作流代码使用公共 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
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 }}"
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
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 }}"
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
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 }}
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 容器操作示例。