Docker容器内Go应用连接RabbitMQ失败求助
Docker环境下Go应用无法连接RabbitMQ的解决方案
问题背景
我编写了一个测试RabbitMQ的Go应用,同时使用Docker Compose管理Go应用和RabbitMQ服务。RabbitMQ能正常启动并访问管理面板,但Go应用始终报错:024/01/22 13:16:33 Failed to connect to RabbitMQ: dial tcp 127.0.0.1:5672: connect: connection refused
相关代码与配置
Go应用代码
package main import ( "log" "time" "github.com/streadway/amqp" ) func failOnError(err error, msg string) { if err != nil { log.Printf("%s: %s", msg, err) } } func main() { var conn *amqp.Connection var err error for i := 0; i < 5; i++ { conn, err = amqp.Dial("amqp://dev:test@rabbitmq:5672/") if err != nil { continue } log.Println(err) time.Sleep(5 * time.Second) } if err != nil { log.Printf("Failed to connect to RabbitMQ: %v", err) } ch, err := conn.Channel() failOnError(err, "Failed to open a channel") defer ch.Close() q, err := ch.QueueDeclare( "hello", // name false, // durable false, // delete when unused false, // exclusive false, // no-wait nil, // arguments ) failOnError(err, "Failed to declare a queue") body := "Hello World!" err = ch.Publish( "", // exchange q.Name, // routing key false, // mandatory false, // immediate amqp.Publishing{ ContentType: "text/plain", Body: []byte(body), }) log.Printf(" [x] Sent %s", body) failOnError(err, "Failed to publish a message") msgs, err := ch.Consume( q.Name, // queue "", // consumer true, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) failOnError(err, "Failed to register a consumer") forever := make(chan bool) go func() { for d := range msgs { log.Printf("Received a message: %s", d.Body) } }() log.Printf(" [*] Waiting for messages. To exit press CTRL+C") <-forever }
Dockerfile
FROM golang:latest LABEL maintainer="Anatoliy" WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o main . EXPOSE 8080 CMD ["./main"]
docker-compose.yml
version: '3.9' services: app: build: . ports: - "8080:8080" depends_on: rabbitmq: condition: service_healthy rabbitmq: image: "rabbitmq:3-management" hostname: "rabbit" environment: RABBITMQ_DEFAULT_USER: dev RABBITMQ_DEFAULT_PASS: test ports: - "5672:5672" - "15672:15672" healthcheck: test: ["CMD", "rabbitmqctl", "status"] interval: 30s timeout: 10s retries: 5
问题原因
在Docker Compose默认网络中,容器通过服务名称或容器主机名进行DNS解析。你的代码中指定了rabbitmq作为连接主机,但报错显示连接127.0.0.1,说明存在以下问题:
- RabbitMQ服务的主机名与代码中的连接主机不匹配(当前RabbitMQ主机名是
rabbit,代码用的是rabbitmq) - 重试逻辑存在缺陷,可能导致连接成功后仍执行错误分支
- 可能存在镜像缓存,容器运行的是旧版代码
修复方案
1. 统一RabbitMQ的服务名与主机名
修改docker-compose.yml中RabbitMQ的hostname为rabbitmq,确保与服务名一致,这样代码中的连接字符串amqp://dev:test@rabbitmq:5672/可以正确解析:
rabbitmq: image: "rabbitmq:3-management" hostname: "rabbitmq" # 修改为与服务名一致 environment: RABBITMQ_DEFAULT_USER: dev RABBITMQ_DEFAULT_PASS: test ports: - "5672:5672" - "15672:15672" healthcheck: test: ["CMD", "rabbitmqctl", "status"] interval: 30s timeout: 10s retries: 5
2. 优化重试逻辑
原代码中重试成功后仍会打印err(此时为nil),且延迟放在循环内导致不必要等待,修改为:
for i := 0; i < 5; i++ { conn, err = amqp.Dial("amqp://dev:test@rabbitmq:5672/") if err == nil { log.Println("Connected to RabbitMQ successfully") break } log.Printf("Connection attempt %d failed: %v", i+1, err) time.Sleep(2 * time.Second) }
3. 强制重新构建镜像
避免缓存导致容器运行旧代码:
docker-compose build --no-cache app docker-compose down && docker-compose up -d
4. 验证网络连通性
进入Go应用容器,测试与RabbitMQ的网络连通性:
docker exec -it <app-container-name> /bin/bash ping rabbitmq
如果能ping通,说明网络配置正常。
验证
启动服务后查看Go应用日志:
docker-compose logs app
若看到Connected to RabbitMQ successfully和[x] Sent Hello World!,则说明连接成功。
内容的提问来源于stack exchange,提问作者Anatoliy Krapotkin
相关产品推荐
相关产品推荐

