nginx-proxy: nginx.conf does not get updated with overlay network IPs

I created an overlay-network for my swarm and can ping and wget a hello-world webserver in the swarm from the reverseproxy container.

This is my /etc/hosts

10.0.1.7        mynetwork_hello_1

And this the relevant part of nginx.conf

upstream ~my.test.com {
                        # mynetwork_hello_1
                        server :80;
}

As you can see the IP is missing.

Looks like somewhere around here the IP does not get written correctly.

Any idea how to fix this or is this an issue with docker-gen?

Tested on: docker 1.9.1, docker-compose 1.5.1

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 17
  • Comments: 66 (12 by maintainers)

Commits related to this issue

Most upvoted comments

What’s the status on this issue?

#425 was closed and #337 was merged

@wader @Ant59 @meyer Just in case, it isn’t necessary to downgrade to version 1 compose file, just add network_mode: bridge to each service instead (which is the old default).

Hey,

Not sure this is the right place for this, but i think if you’re gonna do it through compose, you should re-declare the entrypoint. If you look at the Dockerfile, you can see it’s meant to receive arguments.

Since you’re trying to run nginx-proxy using separate containers, you have to give the nginx container a name and feed it to docker-gen so that it knows which container to send signals.

This part of your compose file cannot work:

- /etc/docker-gen/templates/nginx.tmpl:/etc/nginx/conf.d/default.conf

It is docker-gen, that is going to use nginx.tmpl and generate default.conf for nginx to use. What you’re doing here is simply mounting nginx.tmpl as default.conf as is and nginx will never understand it.

I would also advise to use compose v2, even though this thread is about the problems it may cause, it has already provided a solution that works. This way you won’t get any bad surprises when v1 becomes legacy.

Here’s what a a docker-compose.yml could look like:

version: "2"

services:
  nginx:
    image: nginx
    container_name: nginx_proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./volumes/conf.d:/etc/nginx/conf.d"
      - "./volumes/vhost.d:/etc/nginx/vhost.d"
      - "./volumes/certs:/etc/nginx/certs:ro"
      - "/usr/share/nginx/html"
    networks:
      - proxy-tier
  docker-gen:
    image: jwilder/docker-gen
    container_name: docker_gen
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock:ro"
      - "./data/templates:/etc/docker-gen/templates:ro"
    volumes_from:
      - nginx
    entrypoint: /usr/local/bin/docker-gen -notify-sighup nginx_proxy -watch -only-exposed -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf

networks:
  proxy-tier:
    external:
      name: nginx-proxy

This of course will not work as is. If you want a complete working example, have a look here

Like i said this is compose v2, with the revamped network support. So you’ll want to create a host-wide (or swarm-wide through overlay) network first for your nginx-proxy container that will be configured by docker-gen to connect with your other nginx that will serve your sites (Unless you want to expose a new unique port for every site)

$ docker network create -d bridge nginx-proxy

I’d recommend using @almereyda ‘s upstream block (earlier in this thread), and have your sites’ compose files look something like this:

version: "2"

services:
  nginx:
    image: nginx
    container_name: mysite-nginx
    volumes:
      - "./volumes/conf.d:/etc/nginx/conf.d:ro"
      - "./volumes/www:/opt/www/:ro"
    environment:
      - VIRTUAL_HOST=sub.domain.tld
      - VIRTUAL_PORT=80
      - VIRTUAL_NETWORK=nginx-proxy
    networks:
      - proxy-tier

networks:
  proxy-tier:
    external:
      name: nginx-proxy

Hope this helps.

I am now also using the following declaration to get working results:

{{ define "upstream" }}
        {{ if .Address }}
                {{/* If we got the containers from swarm and this container's port is published to host, use host IP:P$
                {{ if and .Container.Node.ID .Address.HostPort }}
                        # {{ .Container.Node.Name }}/{{ .Container.Name }}                                             
                        server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }};
                {{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
                {{ else if .Address.IP }}
                        # {{ .Container.Name }}
                        server {{ .Address.IP }}:{{ .Address.Port }};
                {{ else }}
                        # {{ .Container.Name }}
                        server {{ .Container.Name }}:{{ .Address.Port }};
                {{ end }}
        {{ else }}
                # {{ .Container.Name }}
                server {{ .Container.IP }} down;
        {{ end }}
{{ end }}

@mickaelperrin did you solve it? I am using nginx,nginx-gen and companion and I have no host…

FWIW, I got it to work using rckrdstrgrd/nginx-proxy in my config here: https://github.com/duck1123/jiksnu/blob/feature/cucumber/docker-compose.yml

I feel that the issue has been resolve. It just needs to be merged from @duck1123.

Cheers! Pascal

The README should be updated accordingly (it refers to this issue).

@Nepoxx looks like this has not beed published on docker hub yet

I’ve tested the changes from #425 and it works like a charm xD nginx-proxy

👍 same problem here with docker 1.10 and latest nginx-proxy

@pascalandy

Glad it could be useful!

As for your compose file, it’s actually much more simple now with the new docker networks. You can remove the

    ports:
      - "80:2368"

portion of your files altogether. You nginx-proxy container and sites will be on the same network, no need to expose ports, just listen on your ghost instances and define the VIRTUAL_PORT and you’ll be good to go.

As for the first part of your message, i didn’t get what you use docker run for and why it’s the same command twice.

Have a look at this gist for an extensive example for Nginx + PHP + MySQL. To add SSL, you’d just need to add

LETSENCRYPT_HOST=xxxxx.com
LETSENCRYPT_EMAIL=xxx@xxxx.com

I found a much better solution for the v2 Compose file breakage on container restart: in my derivative image with the v2 template tweaks, I also save a copy of the original /etc/nginx/conf.d/default.conf to /app and re-copy it back on container startup in the entrypoint.

Before this change, nginx would read the stale config file and bail when it couldn’t find an old container’s upstream host (which might not have come back up yet, or might not be coming back at all).

After the change, nginx is happy to read the original config file and gets signaled by docker-gen when other containers have come up and the new config is ready.

Here’s my Dockerfile:

FROM jwilder/nginx-proxy:latest

# Back up the original nginx conf so we can restore it on startup
RUN cp /etc/nginx/conf.d/default.conf /app/default.conf

# Add a new entrypoint that restores the default nginx conf on startup; this
# fixes breakage on container restart from the below tweaked template, since
# nginx can't find the old hosts
RUN mv /app/docker-entrypoint.sh /app/original-docker-entrypoint.sh
ADD docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod a+x /app/docker-entrypoint.sh

# Add tweaked template to support v2 Compose files
ADD nginx.tmpl /app/nginx.tmpl

And my docker-entrypoint.sh:

#!/bin/bash
cp /app/default.conf /etc/nginx/conf.d/default.conf
exec ./original-docker-entrypoint.sh "$@"

The nginx.tmpl includes the changes @almereyda provided above.

Yes, the previous comment.