I found my way to this package from the nginx-proxy, which offers:
https://github.com/jwilder/nginx-proxy/blob/master/docker-compose-separate-containers.yml
could we have one for this package as well? it makes things so much easier. I've written one (see below) but am uncertain as to syntax. nginx-proxy's is written in Version 2 but I use v3 where the syntax has eliminated the volumes_from key. my alternative is not pretty but I can't think of another way of doing it: I declare the volumes globally and have to list them out in every dependency:
version: '3'
services:
nginx-proxy:
image: nginx
container_name: nginx-proxy
ports:
- "80:80"
volumes:
- nginx-conf:/etc/nginx/conf.d
- nginx-vhost:/etc/nginx/vhost.d
- nginx-html:/usr/share/nginx/html
- nginx-ssl:/etc/nginx/certs:ro
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: true
docker-gen:
image: jwilder/docker-gen
container_name: nginx-gen
command: -notify-sighup nginx -wait 5s:30s -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
volumes:
- nginx-conf
- nginx-vhost
- nginx-html
- nginx-ssl
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl
links:
- nginx-proxy
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-ssl
volumes:
- nginx-conf
- nginx-vhost
- nginx-html
- nginx-ssl
volumes:
- /path/to/certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
NGINX_DOCKER_GEN_CONTAINER: nginx-gen
ACME_CA_URI: https://acme-staging.api.letsencrypt.org/directory
links:
- nginx-proxy
volumes:
nginx-conf:
nginx-vhost:
nginx-html:
nginx-ssl:
Hi ekkis,
You docker-compose file have several errors :
Here is the working docker-compose file I'm currently using, if it can be of any use :
version: '3'
services:
nginx:
image: nginx:1.12
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:ro
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
restart: on-failure
dockergen:
image: jwilder/docker-gen:0.7.3
container_name: nginx-proxy-gen
depends_on:
- nginx
command: -notify-sighup nginx-proxy -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
restart: on-failure
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:latest
container_name: nginx-proxy-le
depends_on:
- nginx
- dockergen
environment:
- NGINX_DOCKER_GEN_CONTAINER=nginx-proxy-gen
volumes:
- conf:/etc/nginx/conf.d
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- certs:/etc/nginx/certs
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: on-failure
volumes:
conf:
vhost:
html:
certs:
# Do not forget to 'docker network create nginx-proxy' before launch
# and to add '--network nginx-proxy' to proxyed containers.
networks:
default:
external:
name: nginx-proxy
Declaring the volume globally and listing them in every container that need them is indeed the way you're supposed to do it if you want to use docker compose v3 file.
thanks, yes, I had already fixed the nginx-proxy reference in PR https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/pull/203
as for the syntax of labels and environment variables, the config comes up clean, and regarding the use of volumes, it works as I have it. I'm using it.
links are useful to make sure one container comes up before another. the letsencrypt should come up first because it needs to generate keys, docker-gen next because it creates the nginx config.
as for networks, yes, I've been thinking about that. of course, docker-compose will create a new network and automatically attach all the containers to it and I think the default behaviour is fine. if you disagree please expound as to why
If it works for you I'll give another try with volume declared this way, that's way cleaner than having to repeat the path every time.
I got the container dependencies in reverse order from yours, because the way I see it a running nginx container with a generated nginx config is required for letsencrypt to perform the domain based challenge validation.
Regarding network, I manage all my services with systemd service file and docker-compose files, even if they only run a single container (because I find it easier an cleaner to edit a yaml file than a multi line or very long command in a systemd service file). So I actually don't use "--network nginx-proxy" with docker run but rather add the external network nginx-proxy as default network on the docker-compose file for containers that need to be proxyed.
If I don't add an external default network for those other services managed by a docker-compose file, docker-composer will create one automatically upon launch and it will pretty quickly end up being a mess of auto created network. Plus using an external network ensure that docker-compose won't remove it or try to.
yes, you're right about the need for nginx to be running in order for challenge validation to occur. I originally had it set up that way but changed it because without an nginx.conf (which is created by nginx-gen) nginx can't route anything, and for nginx-gen to run it needs the nginx.tmpl, which is provided by nginx-letsencrypt, thus that needs to run first
your point about the network is well made. it's not something I had thought through. I currently start a bunch of services that need to be proxied in the same docker-compose file that kicks off the proxy. a container can join multiple networks (I believe) so for the sake of this package we can have one network name, and my containers can have their own network name but join the proxy network
if that sounds about right I will modify the PR accordingly and get back to you
@buchdag, could you share the relevant bits of your docker-compose here so I don't have to read the docs and figure out all the pieces?
with regards the network being "external", the docs indicate:
external
If set to true, specifies that this network has been created outside of Compose. docker-compose up will not attempt to create it, and will raise an error if it doesn鈥檛 exist.
so how do you create the network?
oh wait... so you create a non-external network in one docker-compose i.e. you define a driver for it, and all other docker-compose files declare it as external? and if so, that means you need to run the docker-compose that creates the network first?
@ekkis
creation (subnet is optional, but usefull if you want to fine tune your iptables):
network create -d bridge --subnet 172.28.0.0/16 --opt com.docker.network.bridge.name=nginx-proxy nginx-proxy
On my side, i create it on all usefull hosts from saltstack deployment (so without docker-compose), here is the saltstack state if it could be usefull:
nginx-proxy-network:
cmd.run:
- names:
- docker network create -d bridge --subnet 172.28.0.0/16 --opt com.docker.network.bridge.name=nginx-proxy nginx-proxy
- unless: docker network list | grep nginx-proxy
In the docker-compose.yml:
whatever-servicename:
[...]
networks:
- proxy-tier
networks:
proxy-tier:
external:
name: nginx-proxy
oh, I have to create it by hand: docker network create nginx-proxy. so that's a step I will have to include in the instructions for using the docker-compose file (if there's a way to automate it please let me know)
@lounagen, we crossed messages, however, thanks for your post because you solved another problem I had, namely that when I need to tell a process inside a container to accept connections from a certain subnet, I had to rely on knowing what Docker would use as its subnet. I didn't know about networks and your example shows me that I can specify the subnet so that solves the problem. thanks a bunch!
why name the network? if I do docker network create nginx-proxy then the network will be called nginx-proxy no?
@ekkis, if you only do docker network create nginx-proxy, you can list your bridge/network as nginx-proxy from docker network list, but on your 'real' interfaces, you will end up with a random br-<random hexa string> bridge interface name (at least under linux).
May be you don't care in your use-case, but i do, as i fine tune the iptables with this interface name and i don't bother to autofetch this bridge name to fill my iptables :-)
when you name your 'docker network' with the arg --opt com.docker.network.bridge.name=foobar, you'll end up with a well known name ('foobar' in this sample).
By the way, that's not directly related to this issue, but that's the reason i need to name my docker network for this bunch of 'not publicly exposed on Internet for every remote IP':
if someone here wanted to fine tune its iptables and ask him/herself why iptables don't filter the docker ports exposed on the host (if you'd like to restrict the ip_range allowed to connect publicly on your 443 port or whatever one from outside), i struggled on it some moths ago and found this useful post (https://fralef.me/docker-and-iptables.html).
@lounagen
I did not know the bit about "real" interface naming with --opt com.docker.network.bridge.name, that's super useful, thank you.
that is super useful indeed. I've added it to the PR
@lounagen, @JrCs suggested that rather than incorporating the docker-compose into this project, since there are many ways of kicking this off, that I create a separate project and he would link to it. I did here: https://github.com/ekkis/nginx-proxy-LE-docker-compose -- and I wondered if you might do the same with SaltStack?
@ekkis , sorry for the answer's delay.
I think the saltstack sample to create a docker network sounds obvious when you use saltstack already.
So i've just added this saltstack sample into a README file for external references if you want to add it as a sample from your project.
I referenced both your project and this @JrCs ' project:
https://github.com/lounagen/nginx-proxy-saltstack-network-creation
thanks for that. I've added a link to your project on my page
@buchdag The sniplet in https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/issues/200#issuecomment-297858150 is really cool, do you have it under version control anywhere or something?
I don't seem to understand why using nginx and docker-gen is not the default that is documented everywhere. It claims in the readme its more secure.
It's not the default because whilst being more secure it is harder to configure. I prefer that people try and understand the nginx-proxy + le companion setup first rather than jumping to the three containers setup rigth away and hitting configuration issues.
Also the fact that the three containers setup is more secure doesn't mean that the two containers setup is unsafe. It's probably fine for most people, hence being presented as the default.
For example compose files under vcs, have a look at https://github.com/buchdag/letsencrypt-nginx-proxy-companion-compose
Most helpful comment
Hi ekkis,
You docker-compose file have several errors :
Here is the working docker-compose file I'm currently using, if it can be of any use :
Declaring the volume globally and listing them in every container that need them is indeed the way you're supposed to do it if you want to use docker compose v3 file.