我有一个 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 来运行一切。
我已将您的 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 数据库时才会启动。