使用Docker Build构建镜像后无法连接PostgreSQL数据库
嘿,我一眼就看出问题出在哪了——这是Docker网络的锅!
为啥会报错?
你用docker-compose up能正常跑,是因为Compose会自动给所有服务创建一个专属的私有网络,web、db这些服务都在这个网络里,所以Django能通过db这个服务名直接找到数据库容器的IP。但你单独用docker run启动镜像时,容器默认跑到了Docker的默认bridge网络里,这个网络里根本没有叫db的家伙,自然解析失败,就抛出那个OperationalError了。
至于你改postgresql.conf的listen_addresses,完全没必要,问题根本不在PostgreSQL的监听设置上,是容器之间没在一个网络里,连都连不上!
怎么解决?给你三个办法,按需选:
办法1:让容器加入Compose的专属网络(最直接)
先查一下Compose创建的网络叫啥名:
docker network ls一般是你的项目文件夹名加
_default,比如你项目在mystore文件夹里,网络名就是mystore_default。启动镜像的时候,指定连接到这个网络:
docker run -p 4000:8000 --network=你的网络名称 mystore记得先确保
db容器在运行哦,用docker-compose up -d db就能后台启动数据库。
办法2:临时用宿主机IP连接(仅测试用)
如果你只是想快速测试一下,不想折腾网络,可以把DATABASE配置里的HOST改成MacOS宿主机的专属Docker地址host.docker.internal:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'postgres', 'USER': 'user', 'PASSWORD': 'password', 'HOST': 'host.docker.internal', 'PORT': '5432', } }
然后重新构建镜像:
docker build -t mystore .
不过这个办法只适合临时测试,生产环境别用,太依赖宿主机了,不够灵活。
办法3:用Compose管理单容器(最推荐)
其实完全没必要单独docker run,直接在docker-compose.yml里加个测试用的服务就行:
version: '2' services: # 保留原来的所有服务(db、redis、celery这些)... test-web: image: mystore command: uwsgi /app/saleor/wsgi/uwsgi.ini ports: - '4000:8000' depends_on: - db - redis - search
然后运行:
docker-compose up test-web
这样容器会自动加入Compose的私有网络,完美解析db主机,还能顺便依赖其他服务,一举两得!
最后再提个小提醒
- 先确认
db容器真的正常启动了,用docker-compose logs db看看日志,确保PostgreSQL已经准备好接受连接了。 - 如果是用Docker Cloud部署到VPS,同样要保证应用容器和
db容器在同一个Docker网络里,或者通过环境变量传递数据库的IP地址来配置连接。
内容的提问来源于stack exchange,提问作者Henry Lynx

