GCP Cloud Build/Run部署Go+MySQL应用无法连接数据库
问题核心分析
报错dial tcp: lookup mysql on 169.254.169.254:53: no such host说明Go应用尝试解析主机名mysql失败——本地Docker Compose可用服务名作为主机名,但Cloud Run是独立托管容器环境,不存在mysql这个内部主机名,你的DB_HOST环境变量大概率被设为本地Compose里的服务名mysql,而非GCP上可访问的数据库地址。
排查修复步骤
修正DB_HOST配置
- 登录GCP Secret Manager,查看
DB_HOSTsecret内容,若为mysql则替换为:- Cloud SQL实例的公网/私有IP;
- Cloud Run专用连接格式:
/projects/[项目ID]/locations/[区域]/instances/[实例名](需开启Cloud SQL连接代理)。
- 部署后在Cloud Run控制台服务详情页,确认
DB_HOST已正确注入修改后的地址。
- 登录GCP Secret Manager,查看
验证数据库可访问性
- 若使用Cloud SQL:给Cloud Run服务的服务账号添加
Cloud SQL Client角色;公网访问需确保Cloud SQL授权网络包含Cloud Run出站IP,或启用私有服务访问。 - 若使用外部数据库:检查防火墙规则,允许Cloud Run IP段访问3306端口。
- 若使用Cloud SQL:给Cloud Run服务的服务账号添加
清理Cloud Build冗余步骤
cloudbuild.yaml最后一步docker-compose up完全多余,是在Cloud Build临时环境启动容器,与Cloud Run部署无关,直接删除该步骤。
优化Dockerfile适配生产环境
CompileDaemon是开发热重载工具,Cloud Run生产环境不需要,修改如下:- Dockerfile删除
RUN go install -mod=mod github.com/githubnemo/CompileDaemon; - entrypoint.sh改为直接编译运行(可去掉wait-for,若用Cloud SQL代理无需等待):
go build -o ecommerce main.go ./ecommerce
- Dockerfile删除
- 推荐用多阶段构建减小镜像体积:
# 构建阶段 FROM golang:1.22.2-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN apk add --no-cache protobuf-dev RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest RUN protoc --go_out=./ models/proto/cachemodels/*.proto RUN go build -o ecommerce main.go # 运行阶段 FROM alpine:latest WORKDIR /app COPY --from=builder /app/ecommerce . EXPOSE 8080 CMD ["./ecommerce"]
确认环境变量注入正确性
- 检查
cloudbuild.yaml中gcloud run deploy命令的环境变量引用,确保$$DB_HOST等转义正确,Secret Manager版本引用无误。
- 检查
你提供的配置文件
docker-compose.yaml
version: '3.8' services: mysql: image: mysql:latest environment: MYSQL_ROOT_USER: ${DB_ROOT_USER} MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: ${DB_DATABASE} MYSQL_USER: ${DB_USER} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_TCP_PORT: ${DB_PORT} ports: - "3306:3306" volumes: - db_data:/var/lib/mysql app: build: . ports: - "8080:8080" depends_on: - mysql environment: DB_HOST: ${DB_HOST} DB_DATABASE: ${DB_DATABASE} DB_USER: ${DB_ROOT_USER} DB_PASSWORD: ${DB_ROOT_PASSWORD} DB_PORT: ${DB_PORT} volumes: db_data:
cloudbuild.yaml
steps: - name: "gcr.io/cloud-builders/docker" args: [ "build", "-t", "gcr.io/benergy/go-ecommerce", ".", "-f", "Dockerfile" ] - name: "gcr.io/cloud-builders/docker" args: [ "push", "gcr.io/benergy/go-ecommerce" ] - name: 'gcr.io/cloud-builders/gcloud' entrypoint: 'sh' args: - '-c' - 'gcloud run deploy go-ecommerce --image gcr.io/benergy/go-ecommerce:latest \ --region us-central1 --set-env-vars DB_USER=$$DB_USER \ --set-env-vars DB_PASSWORD=$$DB_PASSWORD --set-env-vars DB_ROOT_USER=$$DB_ROOT_USER \ --set-env-vars DB_ROOT_PASSWORD=$$DB_ROOT_PASSWORD --set-env-vars DB_PORT=$$DB_PORT --set-env-vars DB_HOST=$$DB_HOST --set-env-vars DB_DATABASE=$$DB_DATABASE --cpu 1 --memory 1024Mi --port $$DB_PORT --allow-unauthenticated --platform managed ' secretEnv: [ 'DB_USER', 'DB_PASSWORD', 'DB_ROOT_USER', 'DB_ROOT_PASSWORD', 'DB_PORT', 'DB_HOST', 'DB_DATABASE' ] - name: 'gcr.io/cloud-builders/docker-compose' args: ['up', '--build', '--no-cache', '--detach'] availableSecrets: secretManager: - versionName: projects/859473192921/secrets/DB_USER/versions/latest env: 'DB_USER' - versionName: projects/859473192921/secrets/DB_PASSWORD/versions/latest env: 'DB_PASSWORD' - versionName: projects/859473192921/secrets/DB_ROOT_USER/versions/latest env: 'DB_ROOT_USER' - versionName: projects/859473192921/secrets/DB_ROOT_PASSWORD/versions/latest env: 'DB_ROOT_PASSWORD' - versionName: projects/859473192921/secrets/DB_PORT/versions/latest env: 'DB_PORT' - versionName: projects/859473192921/secrets/DB_HOST/versions/latest env: 'DB_HOST' - versionName: projects/859473192921/secrets/DB_DATABASE/versions/latest env: 'DB_DATABASE'
Dockerfile
FROM golang:1.22.2-alpine WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . COPY ./entrypoint.sh /entrypoint.sh RUN apk update && apk add --no-cache make protobuf-dev RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest RUN protoc --go_out=./ models/proto/cachemodels/*.proto # Install Compile Daemon for go. We'll use it to watch changes in go files RUN go install -mod=mod github.com/githubnemo/CompileDaemon # wait-for-it requires bash, which alpine doesn't ship with by default. Use wait-for instead ADD https://raw.githubusercontent.com/eficode/wait-for/v2.1.0/wait-for /usr/local/bin/wait-for RUN chmod +rx /usr/local/bin/wait-for /entrypoint.sh ENTRYPOINT [ "sh", "/entrypoint.sh" ]
entrypoint.sh
wait-for "${DB_HOST}:${DB_PORT}" -- "$@" # Watch your .go files and invoke go build if the files changed. CompileDaemon --build="go build -o ecommerce main.go" --command=./ecommerce
内容的提问来源于stack exchange,提问作者Hassan Shaitou
相关产品推荐
相关产品推荐

