Docker部署Golang后端+PostgreSQL+Redis连接问题求助
问题背景
我有一个包含Golang后端、PostgreSQL数据库和Redis的项目,用于初始化PostgreSQL的SQL如下:
ALTER USER postgres WITH password '123'; CREATE TABLE users ( username VARCHAR (200) PRIMARY KEY, pass VARCHAR (50) );
第一阶段:单Dockerfile多阶段构建问题
编写的Dockerfile如下:
# syntax=docker/dockerfile:1 FROM postgres:latest AS go2 ENV POSTGRES_USER postgres ENV POSTGRES_PASSWORD '' ENV POSTGRES_DB postgres EXPOSE 5432 ADD table.sql /docker-entrypoint-initdb.d/ FROM redis:latest AS go3 FROM golang:latest AS go WORKDIR /app COPY . . RUN go build -o bin ENTRYPOINT [ "/app/bin" ] EXPOSE 8000
执行构建命令:
docker build . -t mycontainer
运行容器命令:
docker run -t mycontainer --network=bridge
出现错误:
[error] failed to initialize database, got error failed to connect to
host=172.17.0.2 user=postgres database=postgres: dial error (dial tcp 172.17.0.2:5432: connect: connection refused)
尝试用docker run -t mycontainer --network=host运行,问题依旧。
第二阶段:Docker Compose更新后的问题
创建了docker-compose.yaml文件:
services: db: image: 'postgres:15.7' restart: always network_mode: bridge volumes: - './db/table.sql:/docker-entrypoint-initdb.d/init.sql' ports: - '5433:5432' environment: POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: 123 redis: image: 'redis:7.0.12' network_mode: bridge ports: - '6380:6379' backend: build: ./backend network_mode: bridge ports: - '8000:8089' depends_on: - db
现在PostgreSQL和Redis运行正常,但后端容器报错:
[error] failed to initialize database, got error failed to connect to
host=127.0.0.1 user=postgres database=postgres: dial error (dial tcp 127.0.0.1:5433: connect: connection refused)
解决方案
1. 单Dockerfile多阶段构建的问题根源
多阶段构建中只有最后一个阶段(golang:latest)会被打包为最终镜像,postgres和redis阶段的内容不会被包含在最终容器内。也就是说你运行的容器只启动了Golang后端,PostgreSQL和Redis根本没在这个容器里运行,自然无法连接。
单容器运行多个服务不符合Docker最佳实践,应该用Docker Compose管理多个独立容器。
2. Docker Compose的连接问题修复
核心问题
- 后端配置中用
127.0.0.1:5433连接数据库:在Docker网络中,127.0.0.1指的是后端容器自身,而非PostgreSQL容器;且容器间通信应使用容器内部端口5432,而非宿主机映射的5433。 depends_on仅保证容器启动顺序,不确保PostgreSQL服务完全就绪(比如数据库初始化完成)。
修复步骤
步骤1:修改后端数据库连接地址
在Golang项目的数据库配置中,将连接地址改为db:5432:
db是Docker Compose中PostgreSQL服务的名称,Docker会自动解析为对应容器的IP。- 使用容器内部端口
5432进行通信。
示例连接字符串:
dsn := "postgres://postgres:123@db:5432/postgres?sslmode=disable"
步骤2:优化Docker Compose网络配置
移除所有服务的network_mode: bridge,Docker Compose默认会创建专属桥接网络,更适合服务间通信。修改后的配置:
services: db: image: 'postgres:15.7' restart: always volumes: - './db/table.sql:/docker-entrypoint-initdb.d/init.sql' ports: - '5433:5432' environment: POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: 123 redis: image: 'redis:7.0.12' ports: - '6380:6379' backend: build: ./backend ports: - '8000:8089' depends_on: - db
步骤3:添加PostgreSQL就绪检查(可选)
为避免后端在PostgreSQL未完全就绪时连接失败,可为db服务添加健康检查:
services: db: # 保留原有配置 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"] interval: 5s timeout: 5s retries: 5 backend: # 保留原有配置 depends_on: db: condition: service_healthy
3. 验证操作
- 停止并清理现有容器:
docker-compose down
- 重新构建并启动服务:
docker-compose up --build
- 查看后端日志,确认数据库连接成功。
内容的提问来源于stack exchange,提问作者Vali

