Docker-Compose部署Kong服务启动失败:PostgreSQL连接被拒绝
从你的日志和配置来看,Kong连接PostgreSQL失败主要有几个关键问题,我们一步步来修复:
1. 修正PostgreSQL的端口配置错误
你的PostgreSQL容器配置里,ports: - 5435:5435是错误的——PostgreSQL默认容器内监听的端口是5432,不是5435。虽然Kong和PostgreSQL在同一个Docker网络里,不需要端口映射也能通信,但如果要对外暴露端口,应该改成:
ports: - 5435:5432
不过对于Kong内部连接来说,只要PostgreSQL容器正常运行在kong-net网络,Kong通过kong-database主机名连接时,会直接访问容器的5432端口,所以这个端口映射错误不影响内部通信,但还是建议修正避免混淆。
2. 等待PostgreSQL完全就绪再启动Kong
depends_on只会等待PostgreSQL容器启动,不会等待数据库服务完全初始化完成。Kong启动时PostgreSQL可能还没准备好接受连接,导致连接拒绝。你可以用以下两种方法解决:
方法一:给Kong添加启动前等待脚本
修改Kong的command,先等待PostgreSQL就绪再启动Kong:
kong: image: kong:latest restart: always networks: - kong-net depends_on: - kong-database command: sh -c "until pg_isready -h kong-database -U kong; do sleep 1; done; kong start" ports: - 8000:8000 - 8443:8443 - 8009:8009 - 7947:7947 - 7947:7947/udp environment: - KONG_DATABASE=postgres - KONG_PG_HOST=kong-database - KONG_PG_PASSWORD=password - KONG_ADMIN_LISTEN=0.0.0.0:8009
如果Kong镜像里没有pg_isready工具,换成nc命令也可以:
command: sh -c "until nc -z kong-database 5432; do sleep 1; done; kong start"
方法二:给PostgreSQL添加健康检查
在PostgreSQL服务里添加健康检查,让Docker确认数据库就绪后再启动Kong:
kong-database: image: postgres:9.5 container_name: kong-database networks: - kong-net ports: - 5435:5432 environment: - POSTGRES_DB=kong - POSTGRES_USER=kong - POSTGRES_PASSWORD=password healthcheck: test: ["CMD-SHELL", "pg_isready -U kong -d kong"] interval: 5s timeout: 5s retries: 5
然后修改Kong的depends_on,依赖PostgreSQL的健康状态:
kong: # ... 其他配置 depends_on: kong-database: condition: service_healthy
3. 必须执行Kong数据库迁移
你提到移除了迁移配置,但Kong使用PostgreSQL时,必须先初始化数据库schema才能启动。你可以用以下两种方式完成迁移:
方式一:临时运行迁移容器
在启动docker-compose up之前,先执行迁移命令:
docker-compose run --rm kong kong migrations bootstrap
方式二:在docker-compose中添加迁移服务
添加一个一次性的迁移服务,自动完成初始化:
services: # ... kong-database和kong服务 kong-migrations: image: kong:latest networks: - kong-net depends_on: kong-database: condition: service_healthy command: kong migrations bootstrap environment: - KONG_DATABASE=postgres - KONG_PG_HOST=kong-database - KONG_PG_PASSWORD=password
这样启动时会先完成迁移,再启动Kong。
最终修正后的docker-compose.yml示例
version: '3.2' networks: kong-net: services: kong-database: image: postgres:9.5 container_name: kong-database networks: - kong-net ports: - 5435:5432 environment: - POSTGRES_DB=kong - POSTGRES_USER=kong - POSTGRES_PASSWORD=password healthcheck: test: ["CMD-SHELL", "pg_isready -U kong -d kong"] interval: 5s timeout: 5s retries: 5 kong-migrations: image: kong:latest networks: - kong-net depends_on: kong-database: condition: service_healthy command: kong migrations bootstrap environment: - KONG_DATABASE=postgres - KONG_PG_HOST=kong-database - KONG_PG_PASSWORD=password kong: image: kong:latest restart: always networks: - kong-net depends_on: kong-database: condition: service_healthy kong-migrations: condition: service_completed_successfully ports: - 8000:8000 - 8443:8443 - 8009:8009 - 7947:7947 - 7947:7947/udp environment: - KONG_DATABASE=postgres - KONG_PG_HOST=kong-database - KONG_PG_PASSWORD=password - KONG_ADMIN_LISTEN=0.0.0.0:8009
按照这个配置启动,应该就能解决连接拒绝的问题了——它会先等待PostgreSQL完全就绪,再执行数据库迁移,最后启动Kong服务。
内容的提问来源于stack exchange,提问作者Tara Prasad Gurung

