Docker容器中Flask应用连接同VM内PostgreSQL容器失败排查
Docker容器间PostgreSQL连接失败的解决办法
问题情况
同一虚拟机上有两个现成的Docker容器:<postgres>(PostgreSQL数据库)和<system>,它们都在名为<network>的Docker网络里,而且不能修改这俩容器的配置。现在你开发的Flask应用容器连不上<postgres>,报错:
psycopg2.OperationalError: could not parse network address "<postgres>.<network>": Name or service not known
本地电脑能正常连接PostgreSQL的代码:
conn = psycopg2.connect( database="db", user='user1', password='user1_passwd' host='<VM_ip>', port='<db_port>', sslmode='require', sslcert='./user1.crt', sslkey='./user1.key')
Flask容器里尝试的连接代码(失败):
conn = psycopg2.connect( database="db", user='user1', password='user1_passwd' host='<postgres>.<network>', port='<db_port>', sslmode='require', sslcert='./user1.crt', sslkey='./user1.key')
当前Flask容器的docker-compose.yml配置:
version: '3' services: app: container_name: app restart: always build: ./app ports: - "5000:5000" command: gunicorn -w 1 -b 0.0.0.0:8000 wsgi:server
问题根源
你的Flask容器没加入到<postgres>所在的<network>网络中,Docker容器之间要通过名称解析通信,必须处于同一个网络,不然内置DNS服务找不到对应的容器。
解决步骤
修改docker-compose.yml,将Flask容器加入目标网络
添加networks配置,指定加入已存在的<network>网络:version: '3' services: app: container_name: app restart: always build: ./app ports: - "5000:5000" command: gunicorn -w 1 -b 0.0.0.0:8000 wsgi:server networks: - target_network networks: target_network: external: true name: <network> # 替换成实际的网络名称<network>简化数据库连接的host参数
加入同一网络后,直接用<postgres>容器名作为host即可,不需要添加网络后缀:conn = psycopg2.connect( database="db", user='user1', password='user1_passwd' host='<postgres>', port='<db_port>', sslmode='require', sslcert='./user1.crt', sslkey='./user1.key')重新部署Flask容器
执行以下命令重启容器:docker-compose down docker-compose up -d --build
补充说明
- 用VM IP连接失败,是因为容器内默认无法直接访问宿主机的VM IP(虽然有配置方法,但不如加入同一网络方便可靠)。
- 直接用容器IP连接失败,是因为Docker容器重启后IP会发生变化,同一网络内使用容器名解析才是稳定的方案,固定IP不适合长期使用。
内容的提问来源于stack exchange,提问作者Mike Lvov
相关产品推荐
相关产品推荐

