【问题标题】:Extract unit test results from multi-stage Docker build (.NET Core 2.0)从多阶段 Docker 构建(.NET Core 2.0)中提取单元测试结果
【发布时间】:2018-03-24 03:58:11
【问题描述】:

我正在构建一个 .NET Core 2.0 Web API 并且我正在创建一个 Docker 映像。我对 Docker 很陌生,如果之前已经回答过这个问题,我深表歉意。

我有以下用于创建映像的 Docker 文件。特别是,我在构建过程中运行单元测试,结果输出到./test/test_results.xml(我猜是在构建过程中创建的临时容器中)。我的问题是,构建完成后如何访问这些测试结果?

FROM microsoft/aspnetcore-build:2.0 AS build-env

WORKDIR /app

# Copy main csproj file for DataService
COPY src/DataService.csproj ./src/
RUN dotnet restore ./src/DataService.csproj

# Copy test csproj file for DataService
COPY test/DataService.Tests.csproj ./test/
RUN dotnet restore ./test/DataService.Tests.csproj

# Copy everything else (excluding elements in dockerignore)
COPY . ./

# Run the unit tests
RUN dotnet test --results-directory ./ --logger "trx;LogFileName=test_results.xml" ./test/DataService.Tests.csproj

# Publish the app to the out directory
RUN dotnet publish ./src/DataService.csproj -c Release -o out

# Build the runtime image
FROM microsoft/aspnetcore:2.0
WORKDIR /app
EXPOSE 5001
COPY --from=build-env /app/src/out .

# Copy test results to the final image as well??
# COPY --from=build-env /app/test/test_results.xml .

ENTRYPOINT ["dotnet", "DataService.dll"]

我采取的一种方法是在# COPY --from=build-env /app/test/test_results.xml . 行中发表评论。这会将test_results.xml 放入我的最终图像中。然后,我可以使用以下 powershell 脚本提取这些结果并从最终图像中删除 test_results.xml

$id=$(docker create dataservice)
docker cp ${id}:app/test_results.xml ./test/test_results.xml
docker start $id
docker exec $id rm -rf /app/test_results.xml
docker commit $id dataservice
docker rm -vf $id

但这看起来很丑陋,我想知道是否有更清洁的方法。

我希望有一种方法可以在 docker build 期间挂载卷,但官方 Docker 似乎不支持这种方法。

我现在正在考虑创建一个单独的图像,仅用于单元测试。

不确定是否有推荐的方法来实现我想要的。

【问题讨论】:

  • 您找到解决方案了吗?我遇到了完全相同的问题。
  • @Mike 不,抱歉,还没有。我刚刚采用了我提到的将测试结果临时添加到最终图像并提取它们的方法。对 Docker 来说很新,所以我只是想检查一下是否有其他方法或推荐的方法。

标签: unit-testing dockerfile asp.net-core-2.0


【解决方案1】:

这是一个老问题,但我最终在这里寻找同样的东西,所以我会把我的 tuppence 价值留给后代!

现在你可以使用DOCKER_BUILDKIT=1 让 docker 使用 buildkit 来构建你的镜像,它更快并且缓存更好,并且有一个--output 选项可以为你解决这个问题。我在下面有一个基于 golang 的示例,但这对于几乎任何东西都应该同样适用。

# syntax=docker/dockerfile:1.2
FROM golang:1.17 as deps
WORKDIR /src

COPY go.mod go.sum ./
RUN go mod download

COPY command ./command
COPY internal ./internal

# Tests

FROM deps as test
RUN --mount=type=cache,target=/root/.cache go test -v ./... 2>&1 | tee unit.out

FROM scratch as test-output
COPY --from=test /src/unit.out /unit.out

# Build

FROM deps as build
RUN your build steps

这个 dockerfile 有很多阶段:

  1. 跨需求规范复制并安装依赖项(用于缓存)
  2. 运行您的测试(重复使用 deps 阶段以避免重复自己)
  3. 将您的测试结果复制到临时图像中
  4. deps 构建您的映像/二进制文件/您通常会做的任何事情

现在如果你在某处设置DOCKER_BUILDKIT=1 并运行:

docker build

然后 docker 构建您的代码/图像,但不运行测试!因为您的build 阶段根本没有链接到test 阶段,所以它完全绕过了两个测试阶段。但是,您现在可以使用--target 选项来选择test-output 构建阶段和--output 选项来告诉它在本地磁盘上的哪个位置复制结果:

docker build --target test-output --output results .

Docker 然后将构建依赖项(如果您先这样做,则重新使用映像构建中的缓存),运行您的测试并将您的暂存映像的内容(即您的测试报告)复制到 results 目录.任务完成。 :)

编辑:

一篇文章在 .NET 应用程序中使用了这种方法,并更好地解释了整个事情! https://kevsoft.net/2021/08/09/exporting-unit-test-results-from-a-multi-stage-docker-build.html

【讨论】:

    【解决方案2】:

    感谢您的问题 - 我需要解决同样的问题。

    我根据构建结果添加了一个单独的容器阶段。测试及其输出都在那里处理,因此它们永远不会到达最终容器。因此 build-env 用于构建,然后中间测试容器基于该 build-env 映像,最终基于运行时容器,并复制了 build-env 的结果。

    # ---- Test ----
    # run tests and capture results for later use. This use the results of the build stage
    FROM build AS test
    #Use label so we can later obtain this container from the multi-stage build
    LABEL test=true
    WORKDIR /
    #Store test results in a file that we will later extract 
    RUN dotnet test --results-directory ../../TestResults/ --logger "trx;LogFileName=test_results.xml" "./src/ProjectNameTests/ProjectNameTests.csproj"
    

    我添加了一个 shell 脚本作为下一步,然后将图像标记为 project-test。

    #!bin/bash
    id=`docker images --filter "label=test=true"  -q`
    docker tag $id projectname-test:latest
    

    在那之后,我基本上会做你所做的,即使用 docker cp 并将文件取出。不同之处在于我的测试结果从未出现在最终图像中,因此我不会触摸最终图像。

    总的来说,我认为处理测试的正确方法可能是创建一个测试映像(基于构建映像)并使用已安装的卷运行它以获得测试结果,并让它在该容器启动时运行单元测试。拥有适当的图像/容器还可以让您运行集成测试等。这篇文章较旧但细节类似https://blogs.infosupport.com/build-deploy-test-aspnetcore-docker-linux-tfs2015/

    【讨论】:

    猜你喜欢
    • 2020-04-07
    • 2020-10-22
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    相关资源
    最近更新 更多