You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因及解决办法

  1. 核心问题:容器网络隔离
    直接用docker run -it test2-app启动的应用容器,默认加入Docker的默认桥接网络;而通过docker-compose启动的postgres容器,处于docker-compose自动创建的专属自定义网络中。两个不同网络的容器无法通过服务名postgres进行DNS解析,导致连接超时。

  2. 正确启动方式
    放弃单独用docker run启动应用容器,直接通过docker-compose管理整个服务栈:

docker-compose up --build

这条命令会自动完成镜像构建、专属网络创建、关联服务启动,此时应用容器与postgres容器处于同一网络,可正常通过服务名postgres解析连接。

  1. 额外优化建议
  • 把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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:13:09