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

Github Actions中PostgreSQL连接失败(dial error)问题求助

GitHub Actions中PostgreSQL连接失败及复合环境变量不生效问题

错误现象

CI流程中出现PostgreSQL连接错误,本地运行完全正常:

failed to connect to `host=/var/run/postgresql user= database=`: dial error (dial unix /var/run/postgresql/.s.PGSQL.5432: connect: no such file or directory)

CI配置文件(ci.yaml)

name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres:latest
        env:
          POSTGRES_USER: root
          POSTGRES_PASSWORD: password
          POSTGRES_DB: sso_dev
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v2

      - name: Setup Go
        uses: actions/setup-go@v2
        with:
          go-version: '1.21'

      - name: Install golang-migrate
        run: |
          curl -L https://github.com/golang-migrate/migrate/releases/download/v4.12.2/migrate.linux-amd64.tar.gz | tar xvz
          sudo mv migrate.linux-amd64 /usr/bin/migrate
          which migrate

      - name: Install dependencies
        run: go mod download

      - name: Create /config directory
        run: mkdir -p ./config

      - name: Create .env file
        run: echo "${{ secrets.ENV_CONFIG }}" > ./config/.env

      - name: Display .env file
        run: cat ./config/.env

      - name: Wait for PostgreSQL to be ready
        run: sleep 10

      - name: Check PostgreSQL connection
        run: pg_isready -h localhost -p 5432

      - name: Run tests
        run: make test-all-app

      - name: Notify results
        run: echo "Tests completed!"

ENV_CONFIG环境变量内容

GRPC_SERVER_PORT=44044
GRPC_SERVER_TIMEOUT=30s

DB_HOST=localhost
DB_PORT=5432
DB_NAME=sso_dev
DB_USER=root
DB_PASSWORD=password
DB_SSL_MODE=disable
DB_CONN_URL="postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME?sslmode=$DB_SSL_MODE"
DB_CONN_POOL_SIZE=10
DB_READ_TIMEOUT=5s
DB_WRITE_TIMEOUT=5s
DB_IDLE_TIMEOUT=60s
DB_DIAL_TIMEOUT=10s

Go数据库连接代码

package postgres

import (
    "context"
    "fmt"
    "github.com/jackc/pgx/v5/pgxpool"
    _ "github.com/jackc/pgx/v5/stdlib" // Import for side effects
    "github.com/rshelekhov/sso/internal/config"
    "github.com/rshelekhov/sso/internal/storage/postgres/sqlc"
    "net"
)

// NewStorage creates a new Postgres storage
func NewStorage(cfg *config.ServerSettings) (*pgxpool.Pool, error) {
    const method = "storage.postgres.NewStorage"

    poolCfg, err := pgxpool.ParseConfig(cfg.Postgres.ConnURL)
    if err != nil {
        return nil, fmt.Errorf("%s: failed to parse config: %w", method, err)
    }

    poolCfg.MaxConnLifetime = cfg.Postgres.IdleTimeout
    poolCfg.MaxConns = int32(cfg.Postgres.ConnPoolSize)

    dialer := &net.Dialer{KeepAlive: cfg.Postgres.DialTimeout}
    dialer.Timeout = cfg.Postgres.DialTimeout
    poolCfg.ConnConfig.DialFunc = dialer.DialContext

    pool, err := pgxpool.NewWithConfig(context.Background(), poolCfg)
    if err != nil {
        return nil, fmt.Errorf("%s: failed to create pgx connection pool: %w", method, err)
    }

    return pool, nil
}

临时解决方法

修改ENV_CONFIG,移除单独的数据库参数,直接写入完整的连接URL:

GRPC_SERVER_PORT=44044
GRPC_SERVER_TIMEOUT=30s

DB_CONN_URL="postgres://root:password@localhost:5432/sso_dev?sslmode=disable"
DB_CONN_POOL_SIZE=10
DB_READ_TIMEOUT=5s
DB_WRITE_TIMEOUT=5s
DB_IDLE_TIMEOUT=60s
DB_DIAL_TIMEOUT=10s

修改后CI流程恢复正常。

问题根源

复合环境变量未被Shell解析:
当使用echo "${{ secrets.ENV_CONFIG }}" > ./config/.env时,GitHub Actions只是将secrets中的字符串原封不动写入.env文件,没有经过Shell的变量替换流程。原ENV_CONFIG中的DB_CONN_URL里的$DB_USER、$DB_HOST等变量名不会被替换为实际值,导致应用读取到的是未解析的原始URL字符串。

pgx在解析这种无效URL时,无法识别正确的host、port等参数,会默认尝试通过Unix套接字连接PostgreSQL,这就是报错中出现Unix套接字文件不存在的原因。

本地环境正常是因为本地加载.env文件时,Shell会自动完成变量替换,而CI流程中缺少了这个解析步骤。

规范解决方法

  1. 直接写入完整连接URL:如临时解决方法所示,避免在secrets中使用变量引用。
  2. 在CI中用Shell解析变量:修改创建.env文件的步骤,使用envsubst完成变量替换:
echo '${{ secrets.ENV_CONFIG }}' | envsubst > ./config/.env

ubuntu-latest runner默认预装了envsubst(来自gettext包),可直接使用。
3. 在Go代码中拼接连接URL:从配置中读取DB_HOST、DB_USER等独立字段,在代码中构造完整的连接字符串,完全避免依赖Shell的变量解析,提高可靠性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:54:52