Docker container port not accessible in GitHub Actions but works locally

I’m facing a strange problem with my Docker setup. It works flawlessly when I run it locally, but when I try it in GitHub Actions, one of the containers becomes unreachable.

The error I see is:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=3000): Max retries exceeded with url: /rest/v1/users (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x8a2b19f4c920>: Failed to establish a new connection: [Errno 111] Connection refused'))

Here’s my docker-compose configuration for the troubled service:

  workflow-engine:
    image: registry.workflow.io/engine/main
    ports:
      - "3000:3000"
    environment:
      - WF_HOST=workflow-engine:3000
      - WF_PORT=3000
      - WF_PROTOCOL=http
      - RUNTIME_ENV=production
      - DATABASE_TYPE=postgres
      - DB_PREFIX=wf_
      - DB_POSTGRES_NAME=workflow_db
    volumes:
      - ./docker/engine/config:/app/.config
      - ./docker/engine/storage:/storage

I am trying to connect to this service from my Python Flask application using the requests library. The odd thing is that the other services in the same compose file work perfectly in GitHub Actions.

To troubleshoot, I reduced it to these curl commands:

curl --fail http://localhost:8080 || exit 1
curl --fail http://localhost:3000/rest/v1/info/ || exit 1

The first command works (different service), but the second fails with curl: (7) Failed to connect to localhost port 3000 after 0 ms: Connection refused. I even tried changing the port number thinking GitHub Actions might already be using it.

Any suggestions on why this behavior is different between local and CI setups?

Check if your container’s listening on all interfaces, not just localhost. Add EXPOSE 3000 to your Dockerfile and make sure your app binds to 0.0.0.0:3000 instead of 127.0.0.1:3000. GitHub Actions networking gets weird - stuff works locally but breaks in CI because of how Docker handles port binding.

Had this exact problem last year - it’s a timing issue. Your workflow-engine container starts but isn’t ready for connections when tests kick off. GitHub Actions runners behave differently than your local setup. Add a health check to your docker-compose config for the workflow-engine service, then wait for it before running curl commands. Use docker-compose up --wait or build a retry loop with exponential backoff into your test script. Also check the container logs for CI-specific startup errors. Missing environment variables or wonky file permissions often break services silently in GitHub Actions while everything works fine locally.

This screams container networking issue in your CI setup. Your workflow-engine service is probably binding to the wrong interface inside the container. Add command: sh -c "sleep 10 && your-start-command" to give it more startup time. Double-check your GitHub Actions workflow has the right service dependencies too. I hit this same thing - container started fine but the app wasn’t actually bound to the port yet. Also check if GitHub Actions is using a different Docker network mode that breaks localhost. Try switching from localhost:3000 to 127.0.0.1:3000 in your connection string - fixes these CI networking quirks sometimes.