如何在 docker 容器内的后台运行并行服务器来测试它

问题描述 投票:0回答:1

我想创建一个 CI/CD 管道,一旦我将提交推送到 github,它将自动构建、测试和发布 docker 容器。

为此,我使用 Dockerfile 创建一个容器,如下所示:

FROM python:3.11.9-slim-bookworm
ADD . /
RUN apt-get update --fix-missing && apt-get install -y --fix-missing build-essential
RUN apt-get -y update && apt-get -y install curl
RUN make install 
RUN make lint
RUN make serve & sleep 5 
RUN ./service.sh
RUN make test 
EXPOSE 8000

本例中的 makeserve 正在运行一个 fastapi 应用程序。这是Makefile供参考:

install: 
    pip install -r requirements.txt 

lint: 
    pylint --disable=R,C *.py 

serve: 
    python app.py 

test: 
    python -m pytest -vv test_app.py 

clean_cache: 
    rm -rf __pycache__ .pytest_cache 

这里的service.sh是一个可执行文件,它等待fastapi服务器启动,因为它在启动后会休眠5秒。这是通过“&”符号完成的,因此服务器保持在后台运行。当我尝试在 Github Actions 中做同样的事情时,这对我很有用。

这是

service.sh
文件:

#!/bin/bash

for i in {1..10}; do
  if curl -s http://localhost:8000/; then
    echo "Service is up!"
    break
  fi
  echo "Waiting for service to start..."
  sleep 5
done

这段代码对于 github 操作来说已经足够好了。测试成功运行,服务器在后台继续运行。但是,当我尝试对 Docker 容器执行相同操作时,当我运行 make test 命令时,我收到连接池错误,表明服务器已停止。那么问题出在哪里呢?如何在 docker 容器的后台运行服务器?

我尝试使用与 Github 操作相同的解决方法,基于我在这里发布的帖子:如何在 GitHub Actions 中同时运行服务器

但这似乎不适用于 Dockerfile。

docker dockerfile cicd mlops
1个回答
0
投票

一个 Docker 容器通常只运行一个进程。 正如评论中指出的那样,图像不会以任何方式持续运行进程;如果

RUN
命令尝试启动后台进程,它将在该
RUN
命令结束时被终止。

我会尝试将 Dockerfile 限制为仅包含构建映像所需的内容。 如果您有 CI 系统,则更是如此:您可以让 CI 环境(而不是 Dockerfile)运行 linter,然后您可以在 Dockerfile 完成后对构建的映像运行集成测试。

如果你也去掉了这里的 Makefile 包装器,那么你的 Dockerfile 看起来就像一个非常常规的 Python Dockerfile:

FROM python:3.11.9-slim-bookworm
WORKDIR /app  # don't put files in the root directory
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends build-essential curl
# just one apt-get install line

# only install Python dependencies (from cache on rebuilds)
COPY requirements.txt ./
RUN pip install -r requirements.txt

# then install the rest of the application
COPY ./ ./  # prefer COPY to ADD

EXPOSE 8000
CMD ["./app.py"]

现在在您的 CI 环境中,您需要做四件事:

  1. 在调用 Docker 之前运行 linter 和任何其他静态检查器

    pylint --disable=R,C *.py 
    pytest -m 'not integration'
    
  2. 构建形象

    docker compose build
    
  3. 启动容器堆栈,运行集成测试并清理

    docker compose up -d
    pytest -m integration
    docker compose down -v
    
  4. 如果一切成功,则推送图像

    docker compose push
    

请注意,我们已将 linting、单元测试和集成测试(取决于正在运行的服务)从 Dockerfile 中移出。 该服务作为图像的默认

CMD
在前台启动,作为容器中的唯一进程。

© www.soinside.com 2019 - 2024. All rights reserved.