我想创建一个 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 容器通常只运行一个进程。 正如评论中指出的那样,图像不会以任何方式持续运行进程;如果
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 环境中,您需要做四件事:
在调用 Docker 之前运行 linter 和任何其他静态检查器
pylint --disable=R,C *.py
pytest -m 'not integration'
构建形象
docker compose build
启动容器堆栈,运行集成测试并清理
docker compose up -d
pytest -m integration
docker compose down -v
如果一切成功,则推送图像
docker compose push
请注意,我们已将 linting、单元测试和集成测试(取决于正在运行的服务)从 Dockerfile 中移出。 该服务作为图像的默认
CMD
在前台启动,作为容器中的唯一进程。