I’m having trouble with a Docker Compose setup that works perfectly on my local machine but breaks when running in GitHub Actions. The problem seems to be with port exposure for one specific service.
Local vs CI Environment
On my local Mac, everything runs smoothly. But in the GitHub Actions runner, I get connection errors when trying to reach the service API.
Error Message
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8899): Max retries exceeded with url: /api/v1/users (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f3d28e3d810>: Failed to establish a new connection: [Errno 111] Connection refused'))
Docker Compose Configuration
workflow_service:
image: docker.n8n.io/n8nio/n8n
ports:
- "8899:5678"
environment:
- N8N_HOST=workflow_service:5678
- N8N_PORT=5678
- N8N_PROTOCOL=http
- NODE_ENV=production
- DB_TYPE=postgresdb
- DB_TABLE_PREFIX=workflow_
- DB_POSTGRESDB_DATABASE=workflows
volumes:
- ./docker/workflow/config:/home/node/.n8n
- ./docker/workflow/storage:/storage
Testing Commands
curl --fail http://localhost:3000 || exit 1
curl --fail http://localhost:8899/api/v1/docs/ || exit 1
The first curl works fine but the second one fails with curl: (7) Failed to connect to localhost port 8899 after 0 ms: Connection refused. I’m accessing this from a Python Flask app using the requests library. Any ideas what might cause this difference between local and CI environments?
I’ve hit this exact issue with Docker containers in GitHub Actions. It’s almost always a timing problem - the container starts but n8n hasn’t fully loaded yet.
GitHub runners are way slower than your local machine and have weird resource limits. You’re curling the API right after startup, but n8n probably needs more time to actually be ready.
Here’s what fixes it: add a health check or wait loop before your curl commands. Either do a simple retry with sleep intervals, or set up a proper health endpoint that waits for n8n to be fully operational.
Also try using 127.0.0.1 instead of localhost - GitHub Actions can be picky about port binding and this often works better in CI.
check ur github actions runner logs first - port binding sometimes fails silently in CI. also, n8n might be binding to 127.0.0.1 instead of 0.0.0.0 inside the container, which blocks external connections. try adding N8N_LISTEN_ADDRESS=0.0.0.0 to your environment vars.
This is a service discovery issue with GitHub Actions networking. Your Flask app is trying to connect to localhost:8899, but CI environments handle Docker networks differently than your local setup.
I hit the same thing when my app ran outside Docker but needed to reach containerized services. Port mapping works locally because Docker Desktop handles localhost binding differently than Linux CI runners.
Run your Flask app inside the same Docker Compose network instead of from the host. If you can’t do that, check the n8n startup logs in your GitHub Actions output to make sure your container binds to all interfaces. Services often bind only to 127.0.0.1 by default, which blocks external connections even with correct port mapping.