Docker中PostgreSQL无法通过pgadmin、psql及Golang应用连接的问题
问题排查:Golang API Docker容器连接PostgreSQL失败及本地认证问题
遇到的两类问题
- 本地通过pgAdmin/psql连接PostgreSQL容器时,提示
password authentication failed for user postgres;尝试进入PostgreSQL容器时,出现the input device is not a TTY,移除-ti参数后无有效反馈。 - Golang应用连接数据库失败,日志显示
dial tcp 172.29.0.2:5432: connect: connection refused。
现有配置文件
docker-compose.yml
version: '3.8' services: go_db: container_name: go_db image: postgres:12 environment: POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres POSTGRES_DB: apploggerstorage ports: - 5432:5432 volumes: - pgdata:/var/lib/postgresql/data app_logger: container_name: app_logger image: lanceguinto/app_logger:1.0.0 build: . environment: DATABASE_URL: "host=go_db user=postgres password=postgres dbname=apploggerstorage sslmode=disable" ports: - 8000:8000 depends_on: - go_db volumes: pgdata:
(注:原配置遗漏顶层volumes声明,已补充)
Dockerfile
FROM golang:1.21.6 WORKDIR /app COPY . . RUN go get -d -v ./... RUN go build -o applogreader . EXPOSE 8000 CMD ["./applogreader"]
补充说明
- Golang应用代码存于外部粘贴板
- 参考某YouTube教程搭建
问题排查与解决方案
针对问题1:本地认证失败+容器进入异常
修复容器进入异常:
进入PostgreSQL容器的正确命令:docker exec -it go_db bashWindows环境若仍提示
input device is not a TTY,尝试:winpty docker exec -it go_db bash进入容器后,用内置psql验证账号有效性:
psql -U postgres -d apploggerstorage输入密码
postgres,若能成功进入,说明容器内账号配置正常,问题出在本地连接环节。排查本地认证失败:
- 检查本地是否有其他进程占用5432端口:
若有占用,可停止该进程,或修改docker-compose中PostgreSQL的端口映射为# Linux/macOS lsof -i :5432 # Windows netstat -ano | findstr :54325433:5432,本地连接时改用5433端口。 - 本地连接时,确保主机填
localhost、端口用映射后的值(默认5432)、用户名postgres、密码postgres、数据库apploggerstorage。 - 若之前启动过容器,
pgdata卷可能留存旧认证信息,删除卷重新构建:docker-compose down -v docker-compose up -d
- 检查本地是否有其他进程占用5432端口:
针对问题2:Golang应用连接被拒绝
解决容器启动顺序问题:
depends_on仅保证go_db容器先启动,但不确保PostgreSQL服务完全就绪,Golang应用启动时数据库可能仍在初始化。
两种解决方式:- 在Golang代码中添加连接重试逻辑:
import ( "log" "os" "time" "database/sql" _ "github.com/lib/pq" ) func initDB() *sql.DB { var db *sql.DB var err error maxRetries := 10 for i := 0; i < maxRetries; i++ { db, err = sql.Open("postgres", os.Getenv("DATABASE_URL")) if err == nil { err = db.Ping() if err == nil { break } } time.Sleep(1 * time.Second) } if err != nil { log.Fatalf("Failed to connect to database after %d retries: %v", maxRetries, err) } return db } - 在docker-compose中添加健康检查,确保PostgreSQL就绪后再启动Golang应用:
修改go_db服务配置:
修改go_db: # ... 原有配置 ... healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d apploggerstorage"] interval: 5s timeout: 5s retries: 5app_logger服务的depends_on:app_logger: # ... 原有配置 ... depends_on: go_db: condition: service_healthy
- 在Golang代码中添加连接重试逻辑:
验证容器间网络连通性:
进入Golang应用容器,尝试pinggo_db:docker exec -it app_logger ping go_db若能ping通,再尝试用psql连接数据库:
docker exec -it app_logger psql -U postgres -d apploggerstorage -h go_db若连接失败,查看PostgreSQL容器日志排查初始化问题:
docker logs go_db检查环境变量注入是否正确:
进入Golang容器查看DATABASE_URL是否正确:docker exec -it app_logger printenv DATABASE_URL确认内容为
host=go_db user=postgres password=postgres dbname=apploggerstorage sslmode=disable,若不符,检查docker-compose中环境变量的拼写。
内容的提问来源于stack exchange,提问作者zack_falcon
相关产品推荐
相关产品推荐

