Skip to content

[FAQ] HW3 with act: the postgres service is "healthy" but the API dies with "connection refused" on localhost:5432 #415

Description

@yazdanparasthesam

Course

ai-dev-tools-zoomcamp

Question

In Homework 3 (module 03) the assignment tells you to run your CI workflow
locally with act. My workflow starts a postgres:16 service container
with a pg_isready healthcheck, and act prints container health … is healthy. But when the job boots the Agent Relay API with
RELAY_DATABASE_URL=postgresql+psycopg://relay:relay@localhost:5432/relay,
it crashes:

text

psycopg.OperationalError: connection failed: connection to server at
"127.0.0.1", port 5432 failed: Connection refused
The identical workflow passes on GitHub Actions. Why does localhost work
there but not under act, and what hostname should I use?

Answer

Because GitHub and act place service containers in different networks:

GitHub Actions publishes service ports on the job runner's loopback, so
localhost:5432 is correct there.
act runs each service as a separate container on a user-defined docker
network shared with the job container. Nothing is published on the job's
loopback; the service is reachable by its service name (the key under
services:), resolved by docker's embedded DNS. Under act the host is
postgres, not localhost. The giveaway is the error text itself: it
retries ::1 and 127.0.0.1 — loopback — while the healthy service sits
one hop away on the act network.
Fix that is correct in BOTH worlds — parameterise the host with a per-runner
default (vars is legal in step env and, unlike env, in job-level if):

YAML


jobs:
  test:
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER: relay
          POSTGRES_PASSWORD: relay
          POSTGRES_DB: relay
        options: >-
          --health-cmd "pg_isready -U relay -d relay"
          --health-interval 3s --health-timeout 3s --health-retries 10
    steps:
      - name: boot api against postgres
        env:
          RELAY_DATABASE_URL: >-
            postgresql+psycopg://relay:relay@${{ vars.DB_HOST || 'localhost' }}:5432/relay
        run: |
          uv run uvicorn main:app --port 8005 &
          ...

Locally: act … --var DB_HOST=postgres. On GitHub vars.DB_HOST is unset, the
expression falls back to localhost, and the workflow is unchanged.

Sanity checks: docker network inspect <act-…-test-network> lists both
containers; getent hosts postgres resolves inside the job container; and a
service that is healthy in act's log yet "refused" from the job is always
this networking difference, never a bad healthcheck.

Checklist

  • I have searched existing FAQs and this question is not already answered
  • The answer provides accurate, helpful information
  • I have included any relevant code examples or links

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions