When the app runs inside the container, it's best to just take the public Nginx port and send the requests from the internal network to the app service.proxy_passIt's not enough: address.localhostFrom the inside of the Nginx container, the Nginx refers to itself, not the program; and if the source header is not transmitted correctly, the HTTPS, IP user or WebSocket links may be corrupted.
Quick answer:Connect Nginx and the app to a shared network, target upstream with the service name and port, just publish 80/443, andHostAnd then move the main scheme. Set the timeout, WebSocket and upload limitations as required by the program. Then test the connection from outside TLS and HTTP, and from within the upstream network.
Uninstall the network model before config.
The usual flow is: browser → DNS → firewall/CDN → Nginx → app service → internal dependency. Nginx should be on a network that sees the app; the database does not need to connect to a public network or proxy. If Nginx is installed on the host and the app is in Compose, the connection path is different and the app port should only be published on the loopback host. Do not mix the two in a config confusing config.
The name of the service instead of the IP container.
In the Compose network, services usually find each other by the name of the service. The IP container may change after recreate and should not be written to the Nginx fixed file. Nginx may also keep the name upstream when the configuration is resolved and then the same IP; then test the new deployment with a proper reload proxy or dynamic resolution pattern. Error 502 is an important indicator for this path immediately after recreate.
Minimal example for an HTTP backend
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app:8000;
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;
}
}
This model only works when the Compose service is calledappThe same network and port 8000 are listening. Replace the domain and port with the project. For Internet production, TLS and the correct redirect must also be added; do not consider HTTP as a ready-to-deploy version.The SSL Guide to Docker servicesIt examines the certificate and extension separately.
- What?HostDoes it matter?
Many applications use the domain to create absolute URLs, multisite or CSRF controls. Nginx does not necessarily give the same original host to the upstream by default; in the config you must specify the desired behavior. At the same time the program must control authorized hostnames so that the user's desired header does not become a malicious link or redirect.
Real IP and Proxy Chain
X-Forwarded-ForIt may be pre-valued on the client or CDN side; it should not be considered without a trust limit, the definite IP of the user. If you are behind a CDN or load balancer, Nginx and the app should only accept trusted proxies as the header source. Otherwise log, rate limit and IP-based access control can be removed. Test the real IP with a test request and log each right layer.
Scheme and redirect loop
If TLS terminates on Nginx but the app only sees internal HTTP, the app may consider the request insecure and permanently redirect it to HTTPS or create an incorrect URL.X-Forwarded-ProtoIt should send the browser scheme and the app only accept it from the proxy that supports it.$schemeIn Nginx, it is possible.httpIn this case, design the trust chain and the CDN to source linking policy separately.
WebSocket and long-distance connections
WebSocket needs to properly set up the Upgrade/Connection header and the appropriate HTTP version in hop proxy. For SSE and streaming, also coordinate buffering and timeout with app behavior. It is not necessary to copy a WebSocket general configuration for all routes; just target the relevant endpoint. Very long timeout without connection limitations can consume worker capacity; short timeout also interrupts the actual session.
Timeout and upload size
The 504 error is not always from Nginx; it may be from an app, database or dependency.proxy_connect_timeoutI'm not going to.proxy_read_timeoutAnd theproxy_send_timeoutThey have different goals. Don't use them to hide queries.client_max_body_sizeIt must be consistent with the need for upload and limitation of the application; changing it without controlling the file type and storage space creates a risk.
Static file and cache
If Nginx serves static files directly, mount only requires a precise reading and path. Cache header can be set higher for files with a version name, but HTML or custom response should not be followed by the same cache policy. Compression and cache should be tested with CDN and framework behavior; rapid optimization can show older versions of asset or other user content.
Health and setup order
Running a container app is not the same as being ready. Healthcheck requires low-cost endpoint, in-app controlled retry, and HTTP external check. If Nginx is started before the app, you may see a temporary error expected; but a permanent error requires checking DNS, network, listener, and log.Monitoring the server.It's going beyond the process.
Error process 502
- Match the service name and port to the actual app configuration.
- Make sure Nginx and the app are on the same network.
- From inside the proxy container, check the name and connection to the app port.
- Compare Nginx log and app over a period of time.
- After you recreate, check the previous cached IP in Nginx and secure reload.
- If the connection is made, check startup/health and timeout dependency.
Instead of opening an internet app port for quick fix, modify the internal path. Use the read tool to identify and test requests; changing the firewall or network without a return program can further disrupt the service.
Authentication before reload.
Before you apply the config, check the syntax and the upstream name in the same runtime environment. The reload should only be done after the test is successful and an actual request with the host/TLS is answered correctly. If you have multiple virtual hosts, make sure the default server does not send the unknown domain request to the sensitive program. Keep the previous version of the config for rollback.
A request test from start to finish.
For a low-risk path, record HTTP status, response time, hostname and final scheme from the outside. Then, in the Nginx log, find the same request and see what upstream status and upstream response time was. In the app log, also check the request ID or corresponding time.server_nameCheck the host header and trusted host settings. If only long requests fail, first measure the processing time of the app and dependency; changing the timeout is the last step of detection, not the first reaction.
The Proxy and Program Responsibility Boundary
The proxy can impose TLS, request size restrictions, and some rate policies; user authentication, access permissions, and data accuracy are also the responsibility of the program. If the proxy is removed and the app is directly published, edge controls become invalid.
Common Mistakes
- Writing.
localhostInstead of a service. - Use of fixed container IP
- Publishing the database to the host
- Unconditional trust in him
X-Forwarded-For - There was no WebSocket configuration for the required route.
- Upgrading the timeout to close the app
- Not reloading Nginx after upstream IP changes in configuration status
When do you need special assistance?
If you have multiple domains, CDN, WebSocket, TLS and multiple services behind a proxy, small errors in the header or network can disrupt login, payment, and IP restrictions.The application is Dockerized.It can document network design, reverse proxy, health and rollout in test staging and for production.
Common Questions
Should I publish the app port to the host?
If Nginx is on a shared network, usually not. If Nginx is on a host, publish limited to loopback may be required.
Why would I get 502 after the new deployment?
Check the listener, health or upstream resolution in Nginx; don't assume the IP container is fixed.
Did you?X-Forwarded-ForIs he always reliable?
No, only the header is received from the defined proxies and the default must be the actual IP base.
Is TLS required between Nginx and the app?
Depends on the network boundary and threat model; on a shared network a host may accept internal HTTP, but protection between hosts should be assessed separately.