You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Docker中设置环境变量实现Web容器与MySQL容器通信

解决Docker容器中Web应用与MySQL的连接及启动依赖问题

一、用Docker自定义网络替代容器IP(规避IP变化问题)

容器IP会随重启/重建变化,直接用容器名作为DNS地址更可靠——Docker自定义网络会自动完成域名解析,无需手动跟踪IP。

  • 创建自定义Docker网络:

    docker network create app-network
    
  • 启动MySQL容器时加入该网络,设置必要环境变量并指定容器名:

    docker run -d \
      --name mysqldb \
      --network app-network \
      -e MYSQL_ROOT_PASSWORD=你的根密码 \
      -e MYSQL_DATABASE=你的数据库名 \
      mysql:latest
    

    这里容器名mysqldb就是Web应用要访问的地址,Docker会自动解析到对应容器IP。

二、修改Go应用代码:读取环境变量并验证数据库连接

你的Go应用需要读取环境变量获取MySQL地址,并且在启动前验证数据库是否就绪,避免Web应用启动时MySQL还未完成初始化。

1. 代码修改示例

import (
  "database/sql"
  "fmt"
  "log"
  "net/http"
  "os"
  "time"
  "flag"
  "net"

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

var linkList map[string]string
var db *sql.DB

func main() {
  // 读取环境变量,未设置时使用默认值
  mysqlHost := os.Getenv("mysqldb")
  if mysqlHost == "" {
    mysqlHost = "mysqldb" // fallback到MySQL容器名
  }
  mysqlPort := os.Getenv("MYSQL_PORT")
  if mysqlPort == "" {
    mysqlPort = "3306"
  }
  mysqlUser := os.Getenv("MYSQL_USER")
  if mysqlUser == "" {
    mysqlUser = "root"
  }
  mysqlPassword := os.Getenv("MYSQL_PASSWORD")
  if mysqlPassword == "" {
    log.Fatal("MYSQL_PASSWORD环境变量未设置")
  }
  mysqlDB := os.Getenv("MYSQL_DATABASE")
  if mysqlDB == "" {
    log.Fatal("MYSQL_DATABASE环境变量未设置")
  }

  // 构建MySQL连接DSN
  dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", mysqlUser, mysqlPassword, mysqlHost, mysqlPort, mysqlDB)

  // 循环重试连接,等待MySQL就绪
  var err error
  for i := 0; i < 10; i++ {
    db, err = sql.Open("mysql", dsn)
    if err == nil {
      err = db.Ping() // 实际验证连接
      if err == nil {
        break
      }
    }
    log.Printf("等待MySQL就绪,第%d次重试...", i+1)
    time.Sleep(2 * time.Second)
  }
  if err != nil {
    log.Fatalf("无法连接到MySQL: %v", err)
  }
  defer db.Close()
  log.Println("成功连接到MySQL数据库")

  // 原有HTTP服务逻辑
  linkList = map[string]string{}
  http.HandleFunc("/link", addLink)
  http.HandleFunc("/hpe/", getLink)
  http.HandleFunc("/", Home)

  ip := flag.String("i", "0.0.0.0", "")
  port := flag.String("p", "8080", "")
  flag.Parse()
  fmt.Printf("Listening on %s \n", net.JoinHostPort(*ip, *port))
  log.Fatal(http.ListenAndServe(net.JoinHostPort(*ip, *port), nil))
}

2. 前置准备

确保你的Go项目已引入MySQL驱动:

go get github.com/go-sql-driver/mysql

三、更新Dockerfile与容器启动命令

1. 优化Dockerfile

添加健康检查,验证Web服务是否正常运行:

FROM golang:1.19-bullseye AS build     
WORKDIR /app
COPY ./ ./
RUN go mod download  # 下载项目依赖
RUN go build -o main ./

FROM debian:bullseye
COPY --from=build /app/main /usr/local/bin/main
# 安装curl用于健康检查
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# 健康检查配置
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/ || exit 1
CMD ["/usr/local/bin/main"]

2. 构建并启动Web应用容器

启动时加入同一Docker网络,传递必要环境变量:

# 构建镜像
docker build -t tiny .

# 启动容器
docker run -d \
  --name web-app \
  --network app-network \
  -p 9008:8080 \
  -e mysqldb=mysqldb \
  -e MYSQL_PASSWORD=你的根密码 \
  -e MYSQL_DATABASE=你的数据库名 \
  tiny

四、更高效的方案:用Docker Compose管理容器

Docker Compose可以一键启动所有服务,自动处理网络、环境变量和启动顺序,避免手动敲命令的繁琐。

创建docker-compose.yml:

version: '3.8'

services:
  mysqldb:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 你的根密码
      MYSQL_DATABASE: 你的数据库名
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  web-app:
    build: .
    ports:
      - "9008:8080"
    environment:
      mysqldb: mysqldb
      MYSQL_PASSWORD: 你的根密码
      MYSQL_DATABASE: 你的数据库名
    networks:
      - app-network
    depends_on:
      mysqldb:
        condition: service_healthy # 等待MySQL健康检查通过后再启动
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/"]
      timeout: 3s
      retries: 3

networks:
  app-network:
    driver: bridge

启动/停止服务:

# 启动所有服务(后台运行)
docker-compose up -d

# 停止并删除容器
docker-compose down

五、优化Makefile(可选)

添加Docker Compose相关命令,统一管理操作:

build:
    go build -o bin/main main.go
    
run:
    go run main.go

# 构建Docker镜像
docker-build:
    docker build -t tiny .

# 用Docker Compose启动容器
runcontainer:
    docker-compose up -d

# 停止容器
stopcontainer:
    docker-compose down

compile:
    echo "Compiling for every OS and Platform"
    GOOS=linux GOARCH=arm go build -o bin/main-linux-arm main.go
    GOOS=linux GOARCH=arm64 go build -o bin/main-linux-arm64 main.go
    GOOS=freebsd GOARCH=386 go build -o bin/main-freebsd-386 main.go    

内容的提问来源于stack exchange,提问作者user19880359

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:35:49