Home » Laravel » How To Get IP Address in Dockerized Laravel

How To Get IP Address in Dockerized Laravel

Getting a client IP address in Laravel is pretty simple. You don’t need to know which header contains the IP address, because there is the ip() method in the Illuminate\Http\Request class. However, if your Laravel application is running in a Docker container behaind a proxy, the method above will always return Docker internal IP address instead of the client IP.

In this short article, I am going to explain how to fix that and continue using the ip() method even in Dockerized Laravel application.

How To Get IP Address in Dockerized Laravel

There are Apache or Nginx and PHP-FPM in the container that handle requests. But Docker has some issues with real IP forwarding into a container. You can read more about it in the following issue. It may work, If client’s request is coming directly to the container without any proxy. However, if you have a global proxy configured on your server (for example, Nginx) that dispatches and forwards user’s requests to your application, you will get internal docker IP. Docker has a bug, when the local IP address is replaced to Docker internal IP and this bug is not fixed at the moment of writing. There are possible issues:

  • You will get the IP of the server where the proxy is located instead of client IP.
  • You will get the Docker internal IP if the proxy is located on localhost.
  • You will get the Docker internal IP for all requests from the localhost.

In these cases, Nginx and PHP-FPM can’t see the client IP address because the REMOTE_ADDR header contains an internal IP like 172.26.0.1 or proxy IP. Let’s create an endpoint in the routes/api.php file, which returns the client IP and a few headers to test it:

routes/api.phpRoute::get("/ip", function (\Illuminate\Http\Request $request) { return response()->json([ "ip" => $request->ip(), "remote_addr" => $_SERVER["REMOTE_ADDR"] ?? "", "x_forwarded_for" => $_SERVER["HTTP_X_FORWARDED_FOR"] ?? "", "x_forwarded_proto" => $_SERVER["HTTP_X_FORWARDED_PROTO"] ?? "", ]); });

As you can see, there REMOTE_ADDR contain docker internal address:

The proxy web server on the host knows the client IP, and can forward it into the container using the X-Forwarded-For and X-Forwarded-Proto headers. For example, here is a full configuration for test_domain.local, which forwards requests to http://localhost:8080.

/etc/nginx/conf.d/test_domain.confserver { listen 0.0.0.0:8081; server_name test_domain.local; location / { proxy_pass http://localhost:8080; proxy_set_header Host $http_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; } }

Here, http://localhost:8080 is the address and port of the application web server inside a docker container. At this moment, our test endpoint will return the following response:

By default, the headers above are ignored. Although, there are TrustedProxies middleware which can fetch correct IP from X-Forwarded-For and X-Forwarded-Proto headers. This middleware is already enabled for all requests. You only need to add your proxy IP to the trusted proxies list. This list is in the $proxies array in app/Http/Middleware/TrustProxies.php. Here are possible values:

  • Proxy IP. In our case it should be internal docker IP – 172.26.0.1;
  • * – reflects any proxy server that is located on the same server as your Laravel application;
  • ** – reflects any proxy.

For example:

app/Http/Middleware/TrustProxies.phpprotected $proxies = [ "172.26.0.1" ];

After that, you can recheck the IP address, and it will be displayed correctly this time.

Wrapping Up

In this short article, we’ve dove into how to get a client IP in Laravel when your project is running on Docker and placed behind a proxy. As you can see, everything is quite simple. Alternatively, you can use host network driver for your docker container with a web server to be able get real IP address even for localhost.

Leave a Comment

Exit mobile version