如何解决在使用MySQL和Docker运行Golang时出现的连接被拒绝错误。

huangapple go评论83阅读模式
英文:

how to solve this error on Golang running with MySQL in Docker connection refused

问题

我已经搜索并使用了这种方法,但它仍然不起作用,连接无法建立。

我的Dockerfile:

# 从golang基础镜像开始
FROM golang:alpine as builder

# 安装git
# git是用于获取依赖项的必需品
RUN apk update && apk add --no-cache git

# 在容器内设置当前工作目录
WORKDIR /app

# 复制go mod和sum文件
COPY go.mod go.sum ./

# 下载所有依赖项。如果go.mod和go.sum文件没有更改,依赖项将被缓存
RUN go mod download

# 将源代码从当前目录复制到容器内的工作目录
COPY . .

# 构建Go应用程序
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# 从头开始启动一个新的阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# 从上一个阶段复制预构建的二进制文件。注意我们还复制了.env文件
COPY --from=builder /app/main .
COPY --from=builder /app/.env .

# 将端口8080暴露给外部世界
EXPOSE 2345

# 运行可执行文件的命令
CMD ["./main"]

我的Docker-compose.yml:

version: '3.9'
services:
  app:
    container_name: golang_api_container
    build: .
    ports:
      - 5000:2345
    restart: on-failure
    volumes:
      - api:/usr/src/app/
    depends_on:
      - golang-mysql
    networks:
      - fullstack

  golang-mysql:
    image: mysql:5.7
    container_name: db_mysql_container
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 12345
    ports:
      - 3306:3306
    volumes:
      - database_mysql:/var/lib/mysql
    networks:
      - fullstack

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    depends_on:
      - golang-mysql
    environment:
      - PMA_HOST=golang-mysql
      - PMA_ARBITRARY=1
    ports:
      - 3001:80
    restart: always
    networks:
      - fullstack

volumes:
  api:
  database_mysql:

networks:
  fullstack:
    driver: bridge

我的.db文件:

# Mysql Live
DB_HOST=db_mysql_container
DB_DRIVER=mysql
API_SECRET=sipil_api2022
DB_USER=root
DB_PASSWORD=12345
DB_NAME=macan
DB_PORT=3306

# Mysql Test
TEST_DB_HOST=db_mysql_container
TEST_DB_DRIVER=mysql
TEST_API_SECRET=sipil_api2022
TEST_DB_USER=root
TEST_DB_PASSWORD=12345
TEST_DB_NAME=macan_test
TEST_DB_PORT=3306

我的db-config.go文件:

func SetupDBConnection() *gorm.DB {
	errEnv := godotenv.Load()
	if errEnv != nil {
		panic("Failed to load env file")
	}

	dbUser := os.Getenv("DB_USER")
	dbPass := os.Getenv("DB_PASSWORD")
	dbHost := os.Getenv("DB_HOST")
	dbName := os.Getenv("DB_NAME")

	dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8&parseTime=True&loc=Local", dbUser, dbPass, dbHost, dbName)
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Println("Failed to create a connection to DB")
	} else {
		log.Println("Connection Established to DB")
	}
	return db
}

仍然出现错误。我已将DB_HOST调整为DB_HOST=db_mysql_container,因为它与mysql的docker容器名称匹配,但仍然无法连接,连接被拒绝。

如何解决在使用MySQL和Docker运行Golang时出现的连接被拒绝错误。

英文:

I've searched and used this method but it still doesn't work, the connection doesn't work
https://stackoverflow.com/questions/62436736/golang-mysql-docker-connection-refused

my Dockerfile

# Start from golang base image
FROM golang:alpine as builder

# ENV GO111MODULE=on

# Install git.
# Git is required for fetching the dependencies.
RUN apk update && apk add --no-cache git

# Set the current working directory inside the container 
WORKDIR /app

# Copy go mod and sum files 
COPY go.mod go.sum ./

# Download all dependencies. Dependencies will be cached if the go.mod and the go.sum files are not changed 
RUN go mod download 

# Copy the source from the current directory to the working Directory inside the container 
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Start a new stage from scratch
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the Pre-built binary file from the previous stage. Observe we also copied the .env file
COPY --from=builder /app/main .
COPY --from=builder /app/.env .       

# Expose port 8080 to the outside world
EXPOSE 2345

#Command to run the executable
CMD ["./main"]

Docker-compose.yml

version: '3.9'
services:
  app:
    container_name: golang_api_container
    build: .
    ports: 
      - 5000:2345 
    restart: on-failure
    volumes:
      - api:/usr/src/app/
    depends_on:
      - golang-mysql          
    networks:
      - fullstack


  golang-mysql:
    image: mysql:5.7
    container_name: db_mysql_container
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 12345
    ports: 
      - 3306:3306 
    volumes:
      - database_mysql:/var/lib/mysql
    networks:
      - fullstack
  
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin_container
    depends_on:
      - golang-mysql
    environment:
      - PMA_HOST=golang-mysql # Note the "golang-mysql". Must be the name of the what you used as the mysql service.
      # - PMA_USER=root
      # - PMA_PORT=${DB_PORT}
      # - PMA_PASSWORD=
      - PMA_ARBITRARY=1
    ports:
      - 3001:80
    restart: always
    networks:
      - fullstack


volumes:
  api:
  database_mysql:                  

# Networks to be created to facilitate communication between containers
networks:
  fullstack:
    driver: bridge

.env file

# Mysql Live
DB_HOST=db_mysql_container                      
# DB_HOST=127.0.0.1                           # when running the app without docker 
DB_DRIVER=mysql 
API_SECRET=sipil_api2022                          # Used for creating a JWT. Can be anything 
DB_USER=root
DB_PASSWORD=12345
DB_NAME=macan
DB_PORT=3306
# DB_PASSWORD_ROOT=root


# Mysql Test
TEST_DB_HOST=db_mysql_container                        
# TEST_DB_HOST=127.0.0.1                       # when running the app without docker 
TEST_DB_DRIVER=mysql
TEST_API_SECRET=sipil_api2022
TEST_DB_USER=root
TEST_DB_PASSWORD=12345
TEST_DB_NAME=macan_test
TEST_DB_PORT=3306
# DB_PASSWORD_ROOT=root

my db-config.go

func SetupDBConnection() *gorm.DB { 
	errEnv := godotenv.Load() 
	if errEnv != nil {
		panic("Failed to load env file")
	}

	dbUser := os.Getenv("DB_USER")     
	dbPass := os.Getenv("DB_PASSWORD") 
	dbHost := os.Getenv("DB_HOST")     
	dbName := os.Getenv("DB_NAME")     

	dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?charset=utf8&parseTime=True&loc=Local", dbUser, dbPass, dbHost, dbName) 
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})                                                             
	if err != nil {
		log.Println("Failed to create a connection to DB")
	} else {
		log.Println("Connection Established to DB")
	}
	return db
}

Still error

如何解决在使用MySQL和Docker运行Golang时出现的连接被拒绝错误。

I've adjusted the DB_HOST to DB_HOST=db_mysql_container, because it matches the name on the docker container for mysql, but it still doesn't connect and the connection is refused.

答案1

得分: 1

当您部署一个堆栈/组合时,应该使用服务名称而不是容器名称进行通信。

因此,您的DB_HOST应该只是golang-mysql。此外,在生产环境中,您不希望将端口3306:3306映射到主机上。

英文:

When you are deploying a stack/compose, then you should communicate over the services name and not the container name

So your DB_HOST should be just golang-mysql. Also in production, you don't want to map the port 3306:3306 to the host.

huangapple
  • 本文由 发表于 2022年3月19日 13:24:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/71535598.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定