我目前正在尝试将我的一个Django API项目停靠。它使用postgres作为数据库。我使用Docker Cloud作为CI,以便我可以构建,lint和运行测试。
我开始使用以下DockerFile
# Start with a python 3.6 image
FROM python:3.6
ENV PYTHONUNBUFFERED 1
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD xxx
ENV DB_HOST db
RUN mkdir /code
ADD . /code/
WORKDIR /code
RUN pip install -r requirements.txt
RUN pylint **/*.py
# First tried running tests from here.
RUN python3 src/manage.py test
但是这个DockerFile总是失败,因为Django在运行单元测试时无法连接到任何数据库而justs因为没有postgres实例在此Dockerfile中运行而失败并出现以下错误
django.db.utils.OperationalError: could not translate host name "db"
to address: Name or service not known
然后我在Docker Cloud中发现了一个名为“自动测试”的东西,它允许你使用docker-compose.text.yml文件来描述一个堆栈,然后在每个构建中运行一些命令。这似乎是我运行测试所需要的,因为它可以让我构建我的Django图像,引用已经存在的postgres图像并运行测试。
我删除了
RUN python3 src/manage.py test
来自DockerFile的并创建了以下docker-compose.test.yml文件。
version: '3.2'
services:
db:
image: postgres:9.6.3
environment:
- POSTGRES_USER=$POSTGRES_USER
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
sut:
build: .
command: python src/manage.py test
environment:
- POSTGRES_USER=$POSTGRES_USER
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
- DB_HOST=db
depends_on:
- db
然后当我跑
docker-compose -f docker-compose.test.yml build
和
docker-compose -f docker-compose.test.yml run sut
在本地,测试全部运行并全部通过。
然后我将我的更改推送到Github并且Docker云构建它。构建本身成功,但自动测试使用docker-compose.test.yml文件失败,并出现以下错误:
django.db.utils.OperationalError: could not connect to server:
Connection refused
Is the server running on host "db" (172.18.0.2) and accepting
TCP/IP connections on port 5432?
因此,与我的本地计算机相比,似乎数据库服务没有启动或者启动Docker Cloud太慢了?
稍微谷歌后,我发现这个https://docs.docker.com/compose/startup-order/,其中表示容器并不真正等待彼此100%准备就绪。然后,如果确实需要,他们建议编写一个包装器脚本来等待postgres。
我按照他们的指示使用了wait-for-postgres.sh脚本。
多汁部分:
until psql -h "$host" -U "postgres" -c '\l'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
并替换了我的docker-compose.test.yml中的命令
command: python src/manage.py test
到
command: ["./wait-for-postgres.sh", "db", "python", "src/manage.py",
"test"]
然后我推送到Github,Docker Cloud开始建设。构建映像有效但现在Autotest只是等待postgres(我等了10分钟才手动关闭Docker Cloud中的构建过程)
今天我有一个Google-d,看起来大多数“Dockerize Django”教程都没有真正提到单元测试。
使用Docker运行Django单元测试是否完全错误?
我觉得它在本地运行得非常好,但是当Docker Cloud运行它时,它会失败!
答案 0 :(得分:0)
我似乎已经通过将文件中的docker-compose版本从3.2降级到2.1并使用healthcheck来修复它。
healthcheck选项在depends_on子句中给出了语法错误,因为您必须将数组传递给它。不知道为什么在3.2版本中不支持这个。
但这是我的新docker-compose.test.yml工作
version: '2.1'
services:
db:
image: postgres:9.6.3
environment:
- POSTGRES_USER=$POSTGRES_USER
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
healthcheck:
test: ["CMD-SHELL", "psql -h 'localhost' -U 'postgres' -c
'\\l'"]
interval: 30s
timeout: 30s
retries: 3
sut:
build: .
command: python3 src/manage.py test
environment:
- POSTGRES_USER=$POSTGRES_USER
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
- DB_HOST=db
depends_on:
// Does not work in 3.2
db:
condition: service_healthy