Docker Compose环境下Flask应用无法连接PostgreSQL服务的问题
问题
我尝试通过以下docker-compose.yml配置运行Flask、PostgreSQL和Nginx服务:
version: '3.6' services: postgres: image: postgres:10.5 container_name: postgres hostname: postgres user: postgres ports: - "5432:5432" networks: - db-tier environment: CUSTOM_CONFIG: /etc/postgres/postgresql.conf volumes: - ./postgres/sql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql - ./postgres/postgresql.conf:/etc/postgres/postgresql.conf command: postgres -c config_file=/etc/postgres/postgresql.conf restart: always app: image: python/app:0.0.1 container_name: app hostname: app build: context: . dockerfile: Dockerfile depends_on: - postgres networks: - app-tier - db-tier stdin_open: true nginx: image: nginx:1.22 container_name: nginx-reverse-proxy-flask ports: - "8080:80" depends_on: - app volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro networks: - app-tier networks: app-tier: driver: bridge db-tier: driver: bridge
Flask应用中app.config["SQLALCHEMY_DATABASE_URI"]配置为postgresql://denis:1234Five@postgres:5432/app。执行docker-compose up后出现如下错误:
app | psycopg2.OperationalError: could not connect to server: Connection refused app | Is the server running on host "postgres" (192.168.32.2) and accepting app | TCP/IP connections on port 5432?
已确认PostgreSQL服务的容器名称为postgres,请问是什么原因导致Flask应用无法连接到PostgreSQL服务?
分析与解决
- PostgreSQL未完全就绪就被Flask发起连接:
depends_on仅保证容器启动顺序,不会等待PostgreSQL完成初始化并就绪。解决方法:在Flask应用的数据库连接逻辑中添加重试机制;或者在Flask容器的启动脚本中使用wait-for-it、dockerize等工具,等待PostgreSQL的5432端口开放后再启动应用。 - PostgreSQL配置限制了TCP连接:你挂载了自定义的
postgresql.conf,需确认其中是否设置了listen_addresses = '*',否则PostgreSQL只会监听本地回环地址,容器外无法连接。同时检查pg_hba.conf(如果有自定义挂载),需允许db-tier网络段的主机连接,比如添加规则host all all 172.18.0.0/16 md5(具体网段可通过docker network inspect db-tier查看)。 - 数据库认证信息不匹配:当前Flask使用的连接URI是
denis:1234Five和数据库app,但PostgreSQL容器未配置初始化环境变量。Postgres官方镜像需要通过POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB三个环境变量指定初始用户、密码和数据库,否则默认用户是postgres、无密码,也不会自动创建app数据库。需要在postgres服务的environment中添加:POSTGRES_USER: denis POSTGRES_PASSWORD: 1234Five POSTGRES_DB: app - PostgreSQL容器内部端口未正常监听:进入postgres容器执行
netstat -tulpn,确认5432端口是否处于监听状态;或者执行ps aux | grep postgres检查数据库进程是否正常运行,排除容器启动失败的情况。
内容的提问来源于stack exchange,提问作者PatrickHellman
相关产品推荐
相关产品推荐

