Golang连接被拒绝问题排查与解决

Golang连接被拒绝问题排查与解决 我遇到了一个连接问题,连接被拒绝,问题出现在从一个Docker文件中的Go应用程序连接到另一个Docker文件中的MySQL时。

version: ‘3’ services: fullstack-mysql: container_name: db_mysql build: context: ./MySQL ports:

  • 3306:3306 volumes:
  • database_mysql:/var/lib/mysql networks:
  • fullstack

app: container_name: golang_app env_file:

  • ./Go/.env build: context: ./Go ports:
  • 9000:9000 restart: on-failure volumes:
  • api:/usr/src/app/ depends_on:
  • fullstack-mysql networks:
  • fullstack

phpmyadmin: image: phpmyadmin/phpmyadmin container_name: phpmyadmin_container env_file:

  • ./MySQL/.env depends_on:
  • fullstack-mysql environment:
  • PMA_HOST=fullstack-mysql #注意这里的“mysql”。必须是你用作mysql服务的名称。
  • PMA_USER=root
  • PMA_PORT=3306
  • PMA_PASSWORD=root ports:
  • 9090:80 restart: always networks:
  • fullstack

volumes: api: database_mysql:

networks: fullstack: driver: bridge

./Go/Dockerfile

FROM golang:alpine AS builder ENV GO111MODULE=on ENV MYSQL_PASSWORD=$(MYSQL_PASSWORD) ENV MYSQL_USER=$(MYSQL_USER) ENV MYSQL_DATABASE=$(MYSQL_DATABASE) ENV MYSQL_PORT=$(MYSQL_PORT) ENV MYSQL_DRIVER=$(MYSQL_DRIVER) RUN mkdir /app ADD . /app/ WORKDIR /app COPY ./structs.go . COPY ./handlers.go . COPY ./server.go . COPY ./favicon.ico . COPY ./assets /assets RUN go mod init stuff.com RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(ls -1 *.go) EXPOSE 9000 CMD [“go”, “run”, “.”]

./MySQL/Dockerfile

FROM mysql:8.0 ENV MYSQL_PASSWORD=$(MYSQL_PASSWORD) ENV MYSQL_USER=$(MYSQL_USER) ENV MYSQL_DATABASE=$(MYSQL_DATABASE) ENV MYSQL_PORT=$(MYSQL_PORT) ENV MYSQL_DRIVER=$(MYSQL_DRIVER) COPY test.sql /docker-entrypoint-initdb.d/test.sql EXPOSE 3306

./Go/main.go

func db() error {
//connStr:=config.mysqlUser+“:”+config.mysqlPassword+“[@tcp](/user/tcp)(db:”+config.mysqlHost+“:”+config.mysqlPort+“)/”+config.mysqlDB //Ping Error: dial tcp: lookup db:127.0.0.1:3306: no such host

connStr:=config.mysqlUser+“:”+config.mysqlPassword+“[@tcp](/user/tcp)(db:”+config.mysqlPort+“)/”+config.mysqlDB //Ping Error: dial tcp 23.195.69.108:3306: connect: connection refused

log.Println(connStr)
db, err := sql.Open(config.mysqlDriver, connStr)
if err != nil {
log.Println(whereami.WhereAmI(), err.Error())
} else {
log.Println(fmt.Sprintf(“%s”, db), whereami.WhereAmI())
}
defer db.Close()

err = db.Ping()
if err != nil {
log.Println("Ping Error: " + err.Error())
} else {
dbx.conn = db
}

log.Println(fmt.Sprintf(“%s”, dbx.conn), whereami.WhereAmI())
log.Println(fmt.Sprintf(“%T”, dbx.conn), whereami.WhereAmI())
return err
}

log.Println(connStr)->docker:docker@tcp(db:3306)/test_db

./Go/.env

MYSQL_ROOT_PASSWORD=root MYSQL_PASSWORD=docker MYSQL_USER=docker MYSQL_DATABASE=test_db MYSQL_HOST=fullstack-mysql MYSQL_PORT=3306 MYSQL_DRIVER=mysql

COOKIE_NAME=panda COOKIE_VALUE=123456987 COOKIE_MAX_AGE=0 COOKIE_PATH=/ COOKIE_HTTP_ONLY=true DOMAIN=127.0.0.1 PORT=:9000 API_PATH=/api/ API_VERSION=v1 APP_KEY=secret-sauce PROTOCOL=http://

.Mysql/.env

MYSQL_ROOT_PASSWORD=root MYSQL_PASSWORD=docker MYSQL_USER=docker MYSQL_DATABASE=test_db MYSQL_HOST=127.0.0.1 MYSQL_PORT=3306 MYSQL_DRIVER=mysql


更多关于Golang连接被拒绝问题排查与解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang连接被拒绝问题排查与解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


连接被拒绝通常是由于网络配置或连接字符串错误导致的。从你的配置来看,主要问题在于Go应用程序连接MySQL时使用了错误的连接地址。

在你的main.go文件中,连接字符串构建有问题:

// 当前错误的连接字符串
connStr:=config.mysqlUser+":"+config.mysqlPassword+"@tcp(db:"+config.mysqlPort+")/"+config.mysqlDB

应该使用在docker-compose中定义的MySQL服务名称fullstack-mysql,而不是db

// 正确的连接字符串
connStr := config.mysqlUser + ":" + config.mysqlPassword + "@tcp(fullstack-mysql:" + config.mysqlPort + ")/" + config.mysqlDB

另外,你的Go Dockerfile中环境变量设置有问题,应该从.env文件读取配置。修改./Go/Dockerfile

FROM golang:alpine AS builder
ENV GO111MODULE=on
RUN mkdir /app
ADD . /app/
WORKDIR /app
COPY . .
RUN go mod init stuff.com
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main .
EXPOSE 9000
CMD ["./main"]

在Go代码中,确保正确读取环境变量:

package main

import (
    "database/sql"
    "fmt"
    "log"
    "os"
    
    _ "github.com/go-sql-driver/mysql"
)

type Config struct {
    mysqlUser     string
    mysqlPassword string
    mysqlHost     string
    mysqlPort     string
    mysqlDB       string
    mysqlDriver   string
}

var config Config

func init() {
    config = Config{
        mysqlUser:     getEnv("MYSQL_USER", "docker"),
        mysqlPassword: getEnv("MYSQL_PASSWORD", "docker"),
        mysqlHost:     getEnv("MYSQL_HOST", "fullstack-mysql"),
        mysqlPort:     getEnv("MYSQL_PORT", "3306"),
        mysqlDB:       getEnv("MYSQL_DATABASE", "test_db"),
        mysqlDriver:   getEnv("MYSQL_DRIVER", "mysql"),
    }
}

func getEnv(key, defaultValue string) string {
    if value, exists := os.LookupEnv(key); exists {
        return value
    }
    return defaultValue
}

func db() error {
    // 正确的连接字符串
    connStr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s",
        config.mysqlUser,
        config.mysqlPassword,
        config.mysqlHost,  // 应该是 "fullstack-mysql"
        config.mysqlPort,
        config.mysqlDB)
    
    log.Println("Connection string:", connStr)
    
    db, err := sql.Open(config.mysqlDriver, connStr)
    if err != nil {
        log.Println("Open error:", err.Error())
        return err
    }
    defer db.Close()
    
    // 设置连接池参数
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(25)
    db.SetConnMaxLifetime(5 * time.Minute)
    
    err = db.Ping()
    if err != nil {
        log.Println("Ping Error:", err.Error())
        return err
    }
    
    log.Println("Successfully connected to MySQL")
    return nil
}

func main() {
    // 等待MySQL服务启动
    time.Sleep(5 * time.Second)
    
    if err := db(); err != nil {
        log.Fatal("Database connection failed:", err)
    }
    
    // 你的应用逻辑
}

还需要在docker-compose.yml中确保网络配置正确,app服务应该等待MySQL完全启动:

version: '3'
services:
  fullstack-mysql:
    container_name: db_mysql
    build:
      context: ./MySQL
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: test_db
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
    volumes:
      - database_mysql:/var/lib/mysql
    networks:
      - fullstack
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  app:
    container_name: golang_app
    build:
      context: ./Go
    ports:
      - "9000:9000"
    restart: on-failure
    volumes:
      - api:/usr/src/app/
    depends_on:
      fullstack-mysql:
        condition: service_healthy
    networks:
      - fullstack
    environment:
      MYSQL_HOST: fullstack-mysql
      MYSQL_PORT: 3306
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      MYSQL_DATABASE: test_db

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    depends_on:
      - fullstack-mysql
    environment:
      PMA_HOST: fullstack-mysql
      PMA_USER: root
      PMA_PORT: 3306
      PMA_PASSWORD: root
    ports:
      - "9090:80"
    restart: always
    networks:
      - fullstack

volumes:
  api:
  database_mysql:

networks:
  fullstack:
    driver: bridge

关键点是:

  1. 使用正确的服务名称fullstack-mysql而不是db
  2. 添加健康检查确保MySQL完全启动后再连接
  3. 在app服务中明确设置环境变量
  4. 使用正确的连接字符串格式:user:password@tcp(host:port)/database
回到顶部