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流程中缺少了这个解析步骤。
规范解决方法
- 直接写入完整连接URL:如临时解决方法所示,避免在secrets中使用变量引用。
- 在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
相关产品推荐
相关产品推荐

