localhost:9000
Port 9000 is the most fought-over port in development. Four completely unrelated tools all default to it: PHP-FPM (the PHP process manager), SonarQube (code quality analysis), Portainer (Docker management UI), and Xdebug (PHP debugger). If you use any two of these, you've already hit a conflict. This page helps you figure out what's on your 9000 and how to untangle the mess.
What's Actually Using Your Port 9000?
# macOS / Linux
lsof -i :9000
# Windows
netstat -ano | findstr ":9000"
# Docker containers
docker ps --filter "publish=9000"
The process name tells you which service grabbed it: php-fpm, java (SonarQube), portainer, etc.
PHP-FPM
PHP-FPM (FastCGI Process Manager) is the standard way to run PHP in production with Nginx. While Apache uses mod_php (PHP runs inside Apache), Nginx delegates PHP processing to FPM, which listens on port 9000 (or a Unix socket). You won't see a web page at localhost:9000 — FPM speaks FastCGI protocol, not HTTP.
# Check if PHP-FPM is running
systemctl status php-fpm # Linux
brew services list # macOS (look for php)
# PHP-FPM config: /etc/php/8.3/fpm/pool.d/www.conf
# Default setting:
listen = 127.0.0.1:9000
# Change to Unix socket (recommended, avoids port conflicts):
listen = /run/php/php-fpm.sock
# Nginx config to connect to FPM:
# TCP port:
fastcgi_pass 127.0.0.1:9000;
# Unix socket (preferred):
fastcgi_pass unix:/run/php/php-fpm.sock;
Pro tip: Switch FPM from TCP port 9000 to a Unix socket. It's faster (no TCP overhead), avoids port conflicts entirely, and is what most production setups use. Edit www.conf, change listen to a socket path, update your Nginx config to match, and restart both.
SonarQube
SonarQube is a code quality and security analysis platform. After installation, its web interface lives at localhost:9000. Default credentials: admin / admin (it forces you to change on first login).
# Docker (quickest way to try it)
docker run -d --name sonarqube \
-p 9000:9000 \
sonarqube:latest
# Then open http://localhost:9000
# Change port — edit sonar.properties:
sonar.web.port=9001
# Docker with different port:
docker run -p 9001:9000 sonarqube:latest
SonarQube analyzes your code for bugs, vulnerabilities, code smells, and test coverage. You run a scanner against your codebase (SonarScanner CLI, Maven plugin, or Gradle plugin), and it sends results to the SonarQube server for viewing.
Portainer
Portainer provides a web-based GUI for managing Docker containers, images, volumes, and networks. It used to default to 9000, but newer versions (2.x+) use port 9443 (HTTPS). If you're seeing Portainer on 9000, you have an older version or a custom configuration.
# Modern Portainer (v2+)
docker run -d --name portainer \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
# Access at https://localhost:9443
# Legacy Portainer (v1) used port 9000:
docker run -p 9000:9000 portainer/portainer
Xdebug
Xdebug is a PHP debugging extension that lets you set breakpoints and step through code in your IDE. It previously defaulted to port 9000, but Xdebug 3 changed the default to 9003 specifically to avoid the PHP-FPM conflict. If you're using Xdebug 3+, you're on port 9003. If you're on Xdebug 2, you're fighting FPM for port 9000.
; php.ini settings for Xdebug 3
[xdebug]
xdebug.mode = debug
xdebug.client_port = 9003 ; This is the NEW default
xdebug.client_host = 127.0.0.1
xdebug.start_with_request = trigger
; Xdebug 2 (old)
xdebug.remote_port = 9000 ; The OLD default that conflicts with FPM
Resolving Conflicts
The cleanest solution: move PHP-FPM to a Unix socket (no port needed), keep SonarQube on 9000, Portainer on 9443, and Xdebug on 9003. No conflicts.
| Service | Recommended Port | How to Change |
|---|---|---|
| PHP-FPM | Unix socket | listen = /run/php/php-fpm.sock |
| SonarQube | 9000 | Keep default (or sonar.web.port=9001) |
| Portainer | 9443 | Already the new default |
| Xdebug | 9003 | Already the new default (v3) |