容器golang与容器mysql连接问题

问题描述 投票:0回答:1

我有一个 Go 的小项目,基本上有一个连接。

Dockerfile

FROM golang:1.22.3 AS build-stage
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /go-start ./cmd/server/main.go

FROM scratch
WORKDIR /
COPY --from=build-stage /go-start /go-start
COPY --from=build-stage /app/.env .env
EXPOSE 8080
ENTRYPOINT ["/go-start"]

然后我有一个 docker-compose.yml ,其中包含我的 Dockerfile 和 MySQL 映像

services:
  zumenu-backoffice-api:
    container_name: zumenu-backoffice-api
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 8080:8080
    env_file:
      - ./.env
    depends_on:
      - mysql
    networks:
      - zumenu-network

  mysql:
    image: mysql:5.7
    container_name: mysql-zumenu-backoffice
    platform: linux/amd64
    volumes:
      - ./build/mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    ports:
      - 3312:3306
    networks:
      - zumenu-network

networks:
  zumenu-network:
    driver: bridge

以及我的 Go 代码来建立连接


package configs

import (
    "errors"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

func LoadConDB() (*sqlx.DB, error) {
    db, err := sqlx.Connect("mysql", "root:root@(localhost:3312)/zumenu_db")
// or mysql:3306 or mysql-zumenu-backoffice:3306 don't work

    if err != nil {
        return nil, errors.New("failed to connect to the database")
    }
    return db, nil
}

package main

import (
    "fmt"

    "github.com/andremartinsds/api-backoffice-zumenu/configs"
)

func main() {
    _, err = configs.LoadConDB()

    if err != nil {
        panic(err)
    }
    fmt.Println("ok!!!")

}

当我启动 MySQL 容器并在没有 Docker 的情况下在本地运行 Go 应用程序时,它可以工作。但是当一切都用 Docker 运行时,它就不起作用了。

我希望用 Docker 来运行一切。

docker go docker-compose
1个回答
0
投票

我已将您的 Go 代码合并到一个文件中:

package main

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

func main() {
    user := os.Getenv("DB_USER")
    password := os.Getenv("DB_PASSWORD")

    connection := fmt.Sprintf("%s:%s@(mysql:3306)/zumenu_db", user, password)

    fmt.Println("Connecting to database: ", connection)
    db, err := sqlx.Connect("mysql", connection)
    if err != nil {
        log.Fatal(err)
    }

    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Database connection successful")
}

使用

DB_USER
中的
DB_PASSWORD
.env
来构造连接字符串。请注意,连接字符串使用 MySQL 服务的名称 (
mysql
),而不是
localhost
。这对于在容器之间建立连接非常重要,因为 Go 进程的
localhost
与 MySQL 进程的
localhost
不同。

我还更新了

docker-compose.yml
,进行了健康检查,以确保在启动 Go 代码之前数据库已准备好连接。

services:
  zumenu-backoffice-api:
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 8080:8080
    env_file:
      - ./.env
    depends_on:
      mysql:
        condition: service_healthy

  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    ports:
      - 3312:3306
    healthcheck:
      test: ["CMD", "mysqladmin", "-u${DB_USER}", "-p${DB_PASSWORD}", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5

只有当

mysql
服务被标记为“健康”时,后台 API 才会启动,并且只有当
mysqladmin
能够使用
.env
中提供的用户名和密码 ping 数据库时才会启动。

© www.soinside.com 2019 - 2024. All rights reserved.