3

I want to run Nginx in a docker container, it listens to port 80 and I want it to proxy_pass to port 8080 when the url starts with word api, and I have some web app listening port 8080. This has been working for me without docker, but with docker, I couldn't get it to work.

My nginx.conf is like:

    location /{
        # serve static page
    }
    location /api {
        proxy_pass http://0.0.0.0:8080;
    }

I run my nginx container with docker run -d -p 80:80 -p 8080: 8080 nginx

My problem is now I can no longer run my web app because it can't listen to port 8080 since that container is already listening to it.

Arch1tect
  • 4,128
  • 10
  • 48
  • 69
  • Using docker you should in general not run multiple processes within a single container. Try to run your web app in a separate container and let nginx proxy requests to it. – Sebastian Jan 01 '18 at 12:06
  • @Sebastian I'm not. The nginx container only contains nginx, but I don't know how to pass requests from nginx container to my web app container. – Arch1tect Jan 01 '18 at 18:35
  • If you are using different containers there won`t be port conflicts (as you indicated in your question) – Sebastian Jan 01 '18 at 19:06

3 Answers3

6

docker run -d --net host nginx

Try it! Nginx container will share the host network with IP and all ports

亚里士朱德
  • 510
  • 5
  • 15
1

First, you need to create a network to place both containers:

docker network create nginx_network

Then, you should specify Docker's DNS server in nginx configuration:

location /api {
    #Docker DNS
    resolver 127.0.0.11;

    #my_api - name of container with your API, see below
    proxy_pass http://my_api:8080;
}

Finally, run your containers:

docker run --network="nginx_network" -d --name my_api your_api_container
docker run --network="nginx_network" -d -p 80:80 nginx

Note:

  1. --name parameter's value for API's container must match domain name in Nginx config
  2. it's enough to specify only 80 port for your nginx container
  3. first run your API's container and then Nginx's container (see below)
  4. both containers must be in the same network

This should work.

In case if you run nginx container first, then nginx will try to resolve domain name my_api on startup and fail, because container with this name doesn't exist yet. In this case there is a following workaround (not sure if it is good solution). Modify nginx config:

location /api {
    #Docker DNS
    resolver 127.0.0.11;

    #hack to prevent nginx to resolve domain on start up
    set $docker_host "my_api";

    #my_api - name of container with your API, see below
    proxy_pass http://$docker_host:8080;
}
Marat Safin
  • 1,793
  • 20
  • 28
0

You can (or rather should) only have one process per docker container which means you will have nginx running in one container and your application on another. The old way is to create links between containers like this:

$ docker run --name my-app -d myself/myapp
$ docker run --name proxy --link my-app:my-app -d nginx

This will add a line in /etc/hosts in the nginx container so it will be able to call the other container by it's name.

And then in nginx.conf file:

location /api {
    proxy_pass http://my-app:8080;
}

However according to official Docker docs this method is deprecated and you should only use it's "absolutely needed". Instead you should use the docker networking. Theoretically if both containers are in the same network and the local DNS server is working (embedded in docker) they should be able to see each other without the --link parameter. Unfortunately it didn't work for me for some reason. Nginx didn't have the correct DNS configured in /etc/resolv.conf, but read the article and play around it, I'm sure it will work.

Mat
  • 2,378
  • 3
  • 26
  • 35