28

I have two docker containers with nginx. container1 is linked to container2. Docker then adds an entry to /etc/hosts which I entered into the nginx configuration like so:

server {
    location ~ ^/some_url/(.*)$ {
        proxy_pass http://container1/$1;
    }
}

I can ping container1 from container2, but nginx cannot resolve it:

*1 no resolver defined to resolve container1

How can I proxy_pass a request to another docker container?

Tim-Erwin
  • 1,061
  • 1
  • 10
  • 28
  • Can you share your hosts file? How did you link the two containers? (What name does the link have?) Also gotcha: In case you `rm`d one of the containers and restart it later, the IP will have changed (hosts are not updated) – wpp Jan 19 '15 at 17:53
  • I just tried configuration similar to yours and it worked fine for me with `nginx:1.7.9`. Can you start bash at *container2* and curl *container1* ? You are not using the same configurations both container1 and 2, are you? – Mykola Gurov Jan 20 '15 at 12:12
  • 1
    @MykolaGurov I can ping and curl and what not container1 from container2. My problem is, that nginx doesn't seem to be able to resolve it. I'm not using the same configurations, no (if you're referring to nginx config). – Tim-Erwin Jan 21 '15 at 22:32

3 Answers3

44

Use an upstream block instead of the container name directly

upstream backend {
    server container1;
}
server {
    location ~ ^/some_url/(.*)$ {
        proxy_pass http://backend/$1;
    }
}

This should allow normal name resolution to occur providing a way to easily use docker links with nginx.

Bruce Stringer
  • 456
  • 5
  • 4
  • 1
    Best answer when you aren't wanting to mess around with any external dependencies. – Xaero Degreaz Apr 21 '16 at 18:56
  • 6
    The problem I had with this solution is that `container1` must be up and running before you can start your nginx container, otherwise it won't start – Marc-Alexandre Bérubé May 12 '16 at 17:21
  • 1
    Write a script that waits until the backend is up. Something like this should work: `bash -c "while ! curl -s container1:8080 > /dev/null; do echo waiting for container1; sleep 3; done; start_nginx.sh"` where `start_nginx.sh` actually starts the nginx service. – threejeez Jun 29 '16 at 16:50
  • 1
    @Marc-AlexandreBérubé Shouldn't be an issue though - if you're using `--link` that's a requirement anyhow. – TJ Biddle Aug 10 '17 at 22:06
  • only really clean and safe solution. kudos! – Jarema Oct 07 '18 at 12:22
42

You could use embedded Docker DNS service, if enabled, check your container resolver:

cat /etc/resolv.conf

Should be:

nameserver 127.0.0.11

Use this IP as resolver:

server {
    location ~ ^/some_url/(.*)$ {
        resolver 127.0.0.11;
        proxy_pass http://container1/$1;
    } }
Thomas Decaux
  • 18,451
  • 2
  • 83
  • 95
9

You should take a look at this answer about using /etc/hosts as your resolver: Using /etc/hosts as resolver for url rewriting

Basically, your dns or resolver does not use /etc/hosts to resolve names during a lookup, but you can work around this by installing dnsmasq and using 127.0.0.1 as your resolver. You can add 127.0.0.1 as the resolver directly in your nginx config:

server {
    location ~ ^/some_url/(.*)$ {
        resolver 127.0.0.1;
        proxy_pass http://container1/$1;
    }
}
Community
  • 1
  • 1
Michael
  • 9,298
  • 1
  • 31
  • 49
  • That's something I actually already tried, but since dnsmasq did not start up without errors I gave up. Maybe too quickly. Will try again and let you know. – Tim-Erwin Jan 19 '15 at 22:25
  • I tried again, simply added dnsmasq to my entrypoint. If you're running your container inside a VM make sure to run dnsmasq as root, it won't work otherwise. – Tim-Erwin Jan 26 '15 at 13:48