【发布时间】:2020-10-25 21:25:39
【问题描述】:
假设我们正在使用 GitHub Actions 来构建和发布我们应用的容器映像。我将在这里选择 ASP.NET Core 作为应用程序的技术堆栈,尽管这并不重要。
我想讨论两种不同的方法:
1. “在外部构建”:在 GitHub Actions 运行器中构建/编译应用程序,将输出复制到容器映像中
例如,我们的 GitHub Actions 工作流文件可能如下所示...
name: build-outside
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
- name: .NET Publish
run: dotnet publish --configuration Release --nologo -p:CI=true -o $GITHUB_WORKSPACE/buildOutput src
- name: Build and push Docker image
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
repository: ${{ format('{0}/build-outside-test', secrets.DOCKERHUB_USERNAME) }}
tags: latest
...还有一个像这样的简单 Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:latest
WORKDIR /app
COPY buildOutput /app
ENTRYPOINT ["dotnet", "MyTestApp.dll"]
2。 “Build inside”:在一个容器中构建,将输出复制到另一个容器映像
在这种情况下,工作流文件更短...
name: build-inside
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Build and push Docker image
uses: docker/build-push-action@v1
with:
dockerfile: Dockerfile_build_inside
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
repository: ${{ format('{0}/build-inside-test', secrets.DOCKERHUB_USERNAME) }}
tags: latest
...而 Dockerfile 更长,因为现在我们正在这里构建应用程序本身和最终的容器映像:
FROM mcr.microsoft.com/dotnet/core/sdk:latest AS build
WORKDIR /src
COPY src /src
RUN dotnet publish --configuration Release --nologo -p:CI=true -o ./buildOutput
FROM mcr.microsoft.com/dotnet/core/aspnet:latest AS runtime
WORKDIR /app
COPY --from=build /src/buildOutput ./
ENTRYPOINT ["dotnet", "MyTestApp.dll"]
旁白:如果你不熟悉multi-stage builds, 注意第二个 Dockerfile 中的两个
FROM语句。是 在第一个临时容器中构建,然后仅复制 将输出构建到最终的(运行时优化的)容器映像中。
请注意,第二种方法在 ASP.NET Core 官方文档中明确表示为 recommended。
权衡
我confirmed 认为这两种方法都可以工作并生成工作容器映像。值得注意的是,build checks 在拉取请求上使用这两种方法都可以“正常工作”™:
现在离开这个具体的例子,这是我目前对每种方法的总体优势的看法:
- 在外部构建:
- 构建可以利用Marketplace Actions
- 如果构建复杂且包含多个步骤,则使用 GitHub Actions 原语(即一系列作业/任务)进行设置可能会有所帮助。这样一来,我们就可以让 GH 来优化构建、根据需要分配额外的资源、并行运行作业等。
- 更容易检查构建失败(UI 将准确显示哪个步骤失败)
- 在构建过程中无需下载第二个容器镜像,因此也许节省了一点网络带宽
- 内部构建:
- 精确、确定性的构建输出
- 完全控制构建环境;独立于构建运行器
- 容器构建也可以在本地开发机器上运行,产生完全相同的输出
问题
-
我是否准确地描述了这两种方法的优点?
-
在容器内部和外部构建的其他方面,特别是在 GitHub Actions 中,哪些方面值得一提?
【问题讨论】:
标签: docker asp.net-core github github-actions