我应该在docker构建过程中运行测试吗?

6
我有一个像这样的Dockerfile:
FROM python:3.9

WORKDIR /app

RUN apt-get update && apt-get upgrade -y

RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python -

ENV PATH /root/.local/bin:$PATH

COPY pyproject.toml poetry.lock Makefile ./

COPY src ./src

COPY tests ./tests

RUN poetry install && poetry run pytest && make clean

CMD ["bash"]

正如您所看到的,测试将在构建期间运行。这可能会略微减慢构建速度,但将确保我的代码在Docker容器中运行。

如果我的本地机器上的测试通过,并不意味着它们也会在Docker容器中通过。

假设我在代码中添加了一个使用chromedriver或ffmpeg二进制文件的功能,该二进制文件存在于我的系统中,因此测试将在我的系统中通过。

但是,假设我忘记在Dockerfile中安装这些依赖项,则Docker构建将失败(因为测试正在构建期间运行)

我正在尝试做什么的标准方法是什么?

我的Dockerfile好吗?还是我应该采取其他措施?


2
镜像是逐层构建的,在 Dockerfile 中,每个指令都会在最终镜像中创建一个层。据我所知,每次执行测试都会使缓存失效,因此后续层不会从缓存中加载,因此您将无法充分利用加速后续构建的缓存概念。 - Amit Meena
谢谢您的见解。我是 Docker 的新手,之前并不知道这一点。 - aahnik
1
没有问题,请参阅以下链接以了解 Dockerfile 最佳实践:(!) https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ (2) 关于 Python:https://pythonspeed.com/articles/docker-caching-model/ - Amit Meena
问题在于Docker不适用于运行测试。我认为测试应该是您的流水线的一部分。您需要一个与容器环境完全相同的测试环境,在其中运行代码以供生产使用(使用相同的镜像)。在部署后对镜像运行测试是可以的,但我不会将它们包含在dockerfile中。将测试应用于该环境,并在测试通过时标记构建。然后,您就知道构建X.X.X已通过测试。当您拥有此机制时,只需在流水线的“测试阶段”中使用即可。 - Ric Jafe
2个回答

7
如果您使用多个阶段,您可以运行docker build而避免运行测试,如果您想在之后运行测试,则运行docker build --target test将在之前构建的内容上运行测试。这种方法在Docker官方文档中有详细解释。
通过这种方式,我们不仅避免了由于Docker缓存机制而造成的重复构建,还可以避免测试代码被打包到镜像中。
在进行CI/CD时,此实现的一个可能的用例是在本地开发和CI中运行这两个命令,并且不在CD中运行测试命令,因为将部署的代码已经过测试。

6

让pytest在镜像构建时运行对我来说没有意义。 然而,你可以在镜像完成后运行测试。 在你的流水线中应该有类似以下这些步骤:

  1. 本地测试你的Python包
  2. 使用poetry生成wheel文件
  3. 使用你的Python包构建Docker镜像
  4. 运行你的Docker镜像以测试是否正常工作(例如运行pytest)
  5. 将已测试的镜像发布到容器注册表

2
我该如何完成第四步呢?我的意思是在定义Dockerfile时,我应该将tests目录复制到镜像中吗?然后运行 docker run pyproject poetry run pytest - aahnik
1
这是一个选项,但你需要进行单元测试。在第4点中,你需要进行完整性测试,也许应该调用公共方法来确保执行正确。 - Daniel Argüelles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接