Docker下执行Django迁移报错OperationalError无法解析db主机名
问题排查与解决方案
当前报错本质是web容器的内置DNS无法识别db这个主机名。正常同属一个docker-compose项目的服务,会被自动分配到同一个桥接网络,compose内置的DNS会直接把服务名映射成对应容器的内网IP,不需要额外写IP就能通信,出现解析失败基本是以下几个原因,按排查优先级处理:
- 确认执行命令的路径完全包含目标docker-compose.yml文件
很多人执行docker-compose exec命令时,和之前执行up启动时的路径不一致。compose会根据当前所在目录的项目名称生成独立的网络空间,路径不对的话,当前执行命令的环境根本识别不到之前启动的web、db服务,自然没法做DNS解析。你可以在当前目录先执行docker-compose ps,如果列表里没有显示web、db两个服务,说明路径不对,切回存放docker-compose.yml的项目根目录再执行迁移命令。 - 手动验证容器间网络连通性
即使路径正确,也可能出现默认网络配置异常,直接进web容器测试主机名解析能力:
执行命令:docker-compose exec web ping db
如果这一步直接报同名解析错误,说明两个服务没有挂载到同一个网络。这时候不要依赖compose自动生成的默认网络,直接显式给两个服务声明统一的自定义桥接网络,修改后的docker-compose.yml参考配置:
改完之后执行version: '3.8' services: web: build: . command: python /code/manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - 8000:8000 depends_on: - db networks: - app_backend db: image: postgres:11 networks: - app_backend networks: app_backend: driver: bridgedocker-compose down && docker-compose up -d --build重建所有服务,再重新做连通性测试。 - 检查db容器的实际运行状态
depends_on配置只保证db容器先于web容器启动,并不会判断postgres服务本身是否完成初始化、正常运行。如果db容器启动直接报错退出,会被自动从对应网络中移除,这时候web容器自然也解析不到它的地址。先执行docker-compose ps查看db的运行状态,如果显示为Exited,先执行docker-compose logs db排查postgres的启动报错(比如端口冲突、数据目录权限问题等),把db服务正常拉起后再执行迁移。 - 快速兜底验证方案
如果需要临时跳过解析问题验证迁移流程是否通顺,可以直接通过docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 你的db容器名称命令拿到db容器的实际内网IP,临时把settings.py里的HOST配置改成这个IP,跑通迁移流程后,再回头排查DNS解析的配置问题。
内容的提问来源于stack exchange,提问作者Menno ō
相关产品推荐
相关产品推荐

