Nginx反向代理下Portainer Docker容器无法访问的问题求助
Hey George, sorry to hear you're having trouble getting Portainer working behind your Nginx reverse proxy! Let's walk through some common fixes for this issue since your helloworld setup is already working (great job getting that SSL config sorted out, by the way!).
Here are the key steps to troubleshoot and fix your problem:
First, confirm Portainer is running and accessible locally
Before blaming Nginx, make sure the Portainer container is up and responding directly on your server. Run this command to check the container status:docker psLook for your Portainer entry—you should see ports like
0.0.0.0:9000->9000/tcpmapped. Then test local access with:curl http://localhost:9000If this doesn't return Portainer's HTML content, your container might be misconfigured. Try restarting it with
docker restart portainerand check logs withdocker logs portainerfor errors.Fix the Nginx location block for Portainer
This is the most common culprit! Portainer expects to be accessed at the root path (/), but your current config is proxying to/portainerwithout adjusting for the path mismatch. Update your location block to this:location /portainer { proxy_pass http://localhost:9000/; # Don't forget the trailing slash! proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }Let me break this down:
- The trailing slash in
proxy_passtells Nginx to map/portainer/footohttp://localhost:9000/fooinstead ofhttp://localhost:9000/portainer/foo(which Portainer doesn't recognize, causing 404s). - The
proxy_set_headerlines ensure Portainer gets the correct client IP and knows the request came via HTTPS, fixing the "request sent via http while expected https" errors.
- The trailing slash in
If using Portainer's HTTPS port (9443)
If you're trying to proxy to Portainer's built-in HTTPS port, adjust theproxy_passto usehttps://and add a line to skip SSL verification (since Portainer uses a self-signed cert by default):location /portainer { proxy_pass https://localhost:9443/; proxy_ssl_verify off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }That said, it's simpler to proxy to Portainer's HTTP port (9000) and let Nginx handle the external HTTPS layer like you're doing with helloworld.
Alternative: Set a path prefix in Portainer
If you prefer not to add the trailing slash in Nginx, you can configure Portainer to use/portaineras its root path directly. Restart your Portainer container with this command (adjust volumes/ports as needed):docker run -d -p 9000:9000 -p 8000:8000 --name portainer --restart always \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce --path-prefix /portainerWith this setup, your original Nginx location block (without the trailing slash) should work fine.
Don't forget to reload Nginx!
After making any config changes, always validate the syntax first:nginx -tIf it returns "test is successful", reload the config to apply changes:
sudo systemctl reload nginx
Give these steps a try and let us know which one resolves your issue! If you're still stuck, share the output of docker ps and any relevant logs from /var/log/nginx/error.log or docker logs portainer—we can dig deeper from there.
备注:内容来源于stack exchange,提问作者George Wright

