Docker Compose部署Django时迁移出现django.db.utils.OperationalError
解决Docker Compose部署Django时无法解析Postgres主机名的问题
问题根源
你遇到的django.db.utils.OperationalError: could not translate host name "postgres" to address错误,核心原因是Docker镜像构建阶段无法访问Postgres服务容器:
- Dockerfile中的
RUN python3 manage.py makemigrate指令是在镜像构建时执行的,此时Postgres容器尚未启动,且构建环境不属于Docker Compose创建的noted-network网络,根本无法解析"postgres"这个服务名。 - 只有容器运行阶段,app容器才会加入compose网络,才能通过服务名访问Postgres。
解决方案
将数据迁移和静态文件收集的操作,从镜像构建阶段移到容器启动阶段执行,具体步骤如下:
1. 修改Dockerfile
移除构建阶段的makemigrate和collectstatic指令,改用启动命令执行这些操作:
修改后的Dockerfile:
FROM python:3.10 WORKDIR /noted COPY . . ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 RUN pip install -r requirements/production.txt \ && apt-get update \ && apt-get -y install wkhtmltopdf \ && apt-get -y autoclean EXPOSE 8000 WORKDIR /noted/noted # 移除构建阶段的迁移和静态文件收集命令 # RUN python3 manage.py makemigrate --settings=core.settings.production # RUN manage.py collectstatic --noinput --settings=core.settings.production # 启动容器时依次执行迁移、静态文件收集、启动Gunicorn CMD ["sh", "-c", "python3 manage.py makemigrate --settings=core.settings.production && python3 manage.py collectstatic --noinput --settings=core.settings.production && gunicorn --bind 0.0.0.0:8000 core.wsgi"]
2. (可选)使用Entrypoint脚本优化(推荐)
如果需要更清晰的启动流程,可创建一个entrypoint脚本:
创建entrypoint.sh文件(放在项目根目录):
#!/bin/sh # 执行自定义迁移命令 python3 manage.py makemigrate --settings=core.settings.production # 收集静态文件(跳过确认) python3 manage.py collectstatic --noinput --settings=core.settings.production # 启动Gunicorn服务(exec让进程成为容器PID 1,保证信号传递正常) exec gunicorn --bind 0.0.0.0:8000 core.wsgi
然后修改Dockerfile,添加脚本执行权限并设置为entrypoint:
FROM python:3.10 WORKDIR /noted COPY . . ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 RUN pip install -r requirements/production.txt \ && apt-get update \ && apt-get -y install wkhtmltopdf \ && apt-get -y autoclean \ && chmod +x /noted/entrypoint.sh # 给脚本加执行权限 EXPOSE 8000 WORKDIR /noted/noted ENTRYPOINT ["/noted/entrypoint.sh"]
3. 保留现有Docker Compose配置
你的docker-compose.yml中已经配置了depends_on并依赖Postgres的健康检查,这个配置是正确的,它会确保Postgres完全就绪后再启动app容器,避免启动时序问题。
验证修复
执行以下命令重新构建并启动服务:
docker compose down -v # 清理旧容器和数据卷(可选) docker compose up --build
此时app容器启动时会先执行数据迁移,再收集静态文件,最后启动Gunicorn,且能正常通过"postgres"服务名访问数据库。
内容的提问来源于stack exchange,提问作者user11631346
相关产品推荐
相关产品推荐

