Django+Docker-Compose指定db为数据库主机却连接localhost报错
问题
连接到位于"localhost"(127.0.0.1)、端口5432的服务器失败:连接被拒绝
明明在settings.py中直接指定了HOST为"db",为什么应用仍尝试连接localhost?
docker-compose.yml 配置
services: web-app: build: . ports: - "8000:8000" volumes: - ./myapp:/myapp command: > sh -c "python manage.py runserver 0:8000" db: image: postgres:13-alpine volumes: - ./myapp_data:/var/lib/postgresql/data/ environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - POSTGRES_DB=Test_overflow_db
settings.py 数据库配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'Test_overflow_db', 'USER': 'postgres', 'PASSWORD': 'postgres', 'HOST': 'db', 'PORT': 5432, } }
另外,之前碰到过类似错误:django.db.utils.OperationalError: connection to server at db ("172.20.0.2"), port 5432 failed: Connection refused,但做了一些操作后这个错误就没再出现了。
解决方案
- 确认配置文件是否生效:你挂载了本地
./myapp到容器内的/myapp,先检查容器里的settings.py是不是你修改的版本。进入容器执行cat /myapp/settings.py,看HOST字段是不是确实设为了db。有可能本地修改没同步,或者容器内有其他配置文件被优先加载。 - 排查环境变量覆盖:Django会优先读取环境变量里的数据库配置,比如
DATABASE_URL。如果这个变量设成了指向localhost的地址,会直接覆盖settings.py的配置。在容器里执行echo $DATABASE_URL,看看有没有这个变量,有的话要么删除要么改成正确的postgres://postgres:postgres@db:5432/Test_overflow_db。 - 检查容器网络归属:默认docker-compose会给所有服务创建一个共享网络,但如果手动指定了网络,要确保web-app和db在同一个网络里。执行
docker inspect web-app和docker inspect db,对比两者的NetworkSettings里的网络名称,不一致的话调整docker-compose.yml,把两个服务放到同一个网络中。 - 清除缓存或重启容器:如果之前用localhost启动过应用,可能有旧进程残留,或者Django的配置缓存没更新。直接重启web-app容器:
docker-compose restart web-app,或者在容器内运行python manage.py clearcache清除配置缓存。 - 等待数据库服务就绪:虽然现在错误是连localhost,但也有可能是web-app启动时db还没完全就绪,触发了某些 fallback 逻辑。可以在web-app的command里加入等待脚本,比如用
wait-for-it:
注意要先在Dockerfile里安装wait-for-it,或者用原生shell命令循环等待:command: > sh -c "wait-for-it db:5432 -- python manage.py runserver 0:8000"
这种方式需要容器里安装command: > sh -c "until pg_isready -h db -p 5432 -U postgres; do sleep 1; done; python manage.py runserver 0:8000"postgresql-client,可以在Dockerfile里添加RUN apk add --no-cache postgresql-client(因为用的是alpine镜像)。
内容的提问来源于stack exchange,提问作者SomeRandomDude111
相关产品推荐
相关产品推荐

