WSL2环境下Docker运行Go应用报错read udp: i/o timeout求助
WSL2环境下Docker运行Go应用无法连接PostgreSQL,出现DNS解析超时错误
在Windows的WSL2环境中开发了一个连接PostgreSQL的Go应用,编写了Dockerfile和docker-compose.yml文件,构建出test2-app与postgres两个镜像。执行docker run -it test2-app命令时,出现如下错误:
2024/03/05 05:26:10 dial tcp: lookup postgres on 192.168.65.7:53: read udp 172.17.0.2:39295->192.168.75.8:43: i/o timeout
已重启Docker Desktop,但问题仍未解决。
相关代码
main.go文件
const ( host = "postgres" port = 5432 user = "postgres" password = "password" dbname = "test" ) func main() { connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) db, err := sql.Open("postgres", connStr) if err != nil { log.Fatal(err) } defer db.Close() err = db.Ping() if err != nil { log.Fatal(err) } fmt.Println("Successfully connected to PostgreSQL") }
Dockerfile
FROM golang:latest WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o main . CMD ["./main"]
docker-compose.yml文件
version: '2.2' services: app: build: context: . dockerfile: Dockerfile environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password - POSTGRES_DB=test depends_on: - db db: image: postgres restart: always ports: - "5432:5432" environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: test
问题原因及解决办法
核心问题:容器网络隔离
直接用docker run -it test2-app启动的应用容器,默认加入Docker的默认桥接网络;而通过docker-compose启动的postgres容器,处于docker-compose自动创建的专属自定义网络中。两个不同网络的容器无法通过服务名postgres进行DNS解析,导致连接超时。正确启动方式
放弃单独用docker run启动应用容器,直接通过docker-compose管理整个服务栈:
docker-compose up --build
这条命令会自动完成镜像构建、专属网络创建、关联服务启动,此时应用容器与postgres容器处于同一网络,可正常通过服务名postgres解析连接。
- 额外优化建议
- 把main.go中硬编码的数据库连接参数改为从环境变量读取,和docker-compose里的配置对应,提升灵活性:
修改main.go代码:import "os" const ( host = "postgres" port = 5432 ) func main() { user := os.Getenv("POSTGRES_USER") password := os.Getenv("POSTGRES_PASSWORD") dbname := os.Getenv("POSTGRES_DB") connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) // 后续原有逻辑不变 } depends_on仅保证服务启动顺序,不确保postgres完全就绪,建议在应用中添加连接重试逻辑,避免postgres未初始化完成时应用连接失败。
内容的提问来源于stack exchange,提问作者Kaifah Habibi
相关产品推荐
相关产品推荐

