Localhost refused to connect using laravel sail (Docker)
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Localhost Refused to Connect Using Laravel Sail with Laravel Octane: A Deep Dive into Docker Networking Issues
As a senior developer working with modern PHP stacks, migrating applications from traditional setups to containerized environments like Docker and Laravel Sail is standard practice. However, introducing performance enhancements like Laravel Octane, which leverages high-performance servers like Swoole, can sometimes introduce subtle networking complexities within the Docker ecosystem.
Recently, I encountered an issue where my application, running via Laravel Sail, started refusing connections on localhost after installing Laravel Octane. This post will dissect why this happens and provide a robust solution for ensuring seamless connectivity between the host machine and the containerized application.
The Problem: Localhost Refusal After Octane Installation
The core issue stems from how the application server (Swoole, utilized by Octane) is configured to listen within the Docker container versus how the host machine attempts to access it via localhost. When you switch from a standard PHP development server to an Octane setup running on Swoole, the internal listening configuration changes, which often breaks simple localhost connections.
You noted that you were attempting to access http://localhost:8000 or http://0.0.0.0:8000, and these attempts failed. This suggests a networking layer problem rather than an application code error.
Analyzing the Docker Setup
Let's review the components you provided, as they hold the key to the fix.
Your docker-compose.yml file sets up several services (Laravel/Sail, MySQL, Redis, etc.) on a custom network named sail. This is excellent practice for service isolation.
# Snippet from your docker-compose.yml
services:
laravel.test:
# ... other settings
ports:
- '${APP_PORT:-80}:80' # Default port mapping (usually HTTP)
# ...
mysql:
# ...
The issue often arises when the application inside the container is configured to listen on an interface that Docker cannot directly map, or if the external port mapping conflicts with internal service discovery.
The critical change you made was in your supervisord.config:
[program:php]
command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
# ...
By explicitly setting --host=0.0.0.0, you instructed the Swoole server to bind to all available network interfaces inside the container, which is generally correct for Docker networking. However, external access still needs a proper bridge.
The Solution: Mastering Port Mapping and Host Access
The most reliable way to resolve "localhost refused" errors in a Docker environment is to ensure that the internal application port (the one Octane/Swoole is listening on) is correctly exposed to the host machine using the ports directive in docker-compose.yml.
If you are trying to access the web application, you should map the internal port used by your application to a port on your host machine.
Step 1: Adjusting Port Mapping
In many Laravel Sail setups, the main web server (which Octane runs) is configured internally to listen on a specific port (e.g., 8000). Ensure that this internal service is correctly mapped:
If you want to access your application via http://localhost:8000, verify that your laravel.test service in docker-compose.yml explicitly maps the container's exposed port to the host port. Since you are using environment variables like ${APP_PORT}, ensure these variables resolve correctly and map cleanly.
Step 2: Using 0.0.0.0 for External Access (The Best Practice)
While localhost often works on a single machine, using 0.0.0.0 when accessing services from the host machine is far more robust in containerized environments. It explicitly tells the service to listen on all network interfaces accessible by the container, making it reachable by external tools like your browser or curl.
If you are still facing issues after ensuring the port mapping is correct, try using the explicit IP address:
Instead of testing http://localhost:8000, try explicitly accessing the host machine's IP address if you suspect DNS/loopback resolution issues on Windows or specific Docker configurations.
Conclusion and Best Practices
Troubleshooting container networking requires understanding the interplay between the application code (Swoole configuration), the container environment (Dockerfile), and the orchestration layer (docker-compose). When working with Laravel, remember that Sail is designed to abstract much of this complexity for you. Always refer back to the official documentation on Laravel documentation regarding Docker setup and service interaction when facing connectivity issues.
By ensuring your application binds correctly (using 0.0.0.0 internally) and that your port mappings are explicit in docker-compose, you can eliminate these frustrating "localhost refused" errors and achieve a stable, high-performance deployment.