Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With jwilder nginx-proxy, how to proxypass a subdirectory url to a specific container?

I use jwilder/nginx-proxy to make a reverse proxy. I try to redirect http://localhost:8000/api to a specific php service.

The directory structure:

.
+-- docker-compose.yml
+-- nginx
+-- nodejs
|   +-- index.js
|   +-- …
+-- php
|   +-- api

docker-compose.yml:

version: "3.1"

services:

  nginx-proxy:
    image: jwilder/nginx-proxy:alpine
    ports:
      - "8000:80"
    volumes:
      - ./php:/srv/www
      - /var/run/docker.sock:/tmp/docker.sock:ro

  nodejs:
    image: node:alpine
    environment: 
      - NODE_ENV=production
      - VIRTUAL_HOST=localhost
      - VIRTUAL_PORT=8080
    expose:
      - "8080"
    working_dir: /home/app
    restart: always
    volumes:
      - ./nodejs:/home/app
    command: ["node", "index.js"]

  php:
    image: php:apache
    environment:
      - VIRTUAL_HOST=localhost
    volumes:
      - ./php:/var/www/html

This works fine for the nodejs service.

Now, I would like to redirect calls to http://localhost:8000/api to the php service. I imagine that I have to add to the nginx conf something like:

server {
  location /api {
    proxy_pass http://php:80/api;
    proxy_set_header Host $host;
  }
}

This feature is not built into the lib. So, how can I achieve that?

like image 214
François Romain Avatar asked Oct 17 '22 09:10

François Romain


1 Answers

One approach is to give the php app its own virtual host:

  php:
    image: php:apache
    environment:
      - VIRTUAL_HOST=api.localhost
    volumes:
      - ./php:/var/www/html

Then, it will be accesible as this:

curl -H 'Host: api.localhost' http://localhost:8000/api

Setting the header can be achieved in practically any language. Or to avoid setting custom header, you can add that DNS to your /etc/hosts file:

127.0.0.1 api.localhost

So you can curl as this:

curl -H http://api.localhost:8000/api

This is how set custom headers, for example in node:

var request = require('request')

var formData = {}

request({
    headers: {
      'Host': 'api.localhost'
    },
    uri: 'http://localhost:8080',
    method: 'POST'
  }, function (err, res, body) {
      console.log("it works")
      console.log(res)
    }
)

But, I recommend you to go for the /etc/hosts approach, that should has an equivalent in production environment (a DNS server). So you don't need to touch node code.

like image 180
Robert Avatar answered Nov 15 '22 05:11

Robert