Closed Netherdrake closed 7 years ago
I use Let's Encrypt for just about everything these days. I don't think you want that in your app container though. You want that at the proxy or load balancer level. My favorite these days is this one...
https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion
(which works with jwilder/nginx-proxy
)
https://github.com/jwilder/nginx-proxy
Do you happen to run it with docker-compose, with automatic certificate generation?
Edit: I found one in examples: https://github.com/fatk/docker-letsencrypt-nginx-proxy-companion-examples/blob/master/docker-compose/v2/simple-site/docker-compose.yml
I don't usually use docker-compose for that because the Let's Encrypt container requires a somewhat longer than normal startup time and the app container would start before the LE container is ready.
So...
# start Nginx proxy
docker run -d -p 80:80 -p 443:443 \
--name nginx-proxy \
--restart always \
-v /opt/certs:/etc/nginx/certs:ro \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy:latest
# start Let's Encrypt helper
docker run -d \
--restart always \
-v /opt/certs:/etc/nginx/certs:rw \
--volumes-from nginx-proxy \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion:latest
Then make sure to hop into the logs for the LE container and watch for it to be done setting up. Once it's ready, you can start your app container with the two required env vars.
docker run -d \
-e VIRTUAL_HOST="example.com" \
-e VIRTUAL_PORT="3000" \ # default port for meteor-launchpad
-e LETSENCRYPT_EMAIL="me@example.com" \
-e LETSENCRYPT_HOST="example.com" \
-e ROOT_URL="https://example.com" \
-e MONGO_URL="mongodb://..." \
me/myapp:latest
You can then hop back into the logs for the LE container and you should see it generate the certs. Assuming your domain name is already pointed at your server, it should work within a few seconds. Renewals will then happen automatically.
You could obviously put all of that into a docker-compose.yml file, but you'd have to make sure that things come up in the right order and that the app container doesn't start before the LE container is ready.
Note that in my example above, your certs will be persisted to /opt/certs
on your host, so you can update the containers and the certs will still be there when the containers come back up.
But if you really wanted to use docker-compose...
nginx-proxy:
image: jwilder/nginx-proxy:latest
ports:
- 80:80
- 443:443
restart: always
volumes:
- /opt/certs:/etc/nginx/certs:ro
- /etc/nginx/vhost.d
- /var/run/docker.sock:/tmp/docker.sock:ro
- /usr/share/nginx/html
lets-encrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:latest
restart: always
volumes:
- /opt/certs:/etc/nginx/certs
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes_from:
- nginx-proxy
app:
image: me/myapp:latest
restart: always
environment:
- VIRTUAL_HOST=example.com
- VIRTUAL_PORT=3000
- LETSENCRYPT_EMAIL=me@example.com
- LETSENCRYPT_HOST=example.com
- ROOT_URL=https://example.com
- MONGO_URL=mongodb://...
Then just start them one at a time.
# start nginx
docker-compose up -d nginx-proxy
# start LE helper
docker-compose up -d lets-encrypt
# watch logs and wait to be ready...
docker-compose logs -f lets-encrypt
# start app
docker-compose up -d app
Is there a way to make meteor-launchpad host on port 80 rather than 3000?
docker run -p 80:3000 ...
But if you're running nginx proxy in front of it, that's irrelevant anyway. You run nginx on 80 and set the backend port that nginx should talk to with VIRTUAL_PORT
as I did above.
I am trying to make it work with haproxy
rather than nginx, and if I expose the port with 80:3000
it doesn't work for some reason.
You can't have two containers exposing the same port on the same server.
I know, thats not the problem.
If I try sample app (https://github.com/docker/dockercloud-hello-world) it works fine.
If I try my meteor web app, and expose 80:3000
, haproxy simply returns 503, no servers available
.
I'd like to use letsencrypt-nginx-proxy-companion:latest
, however Im deploying on dockercloud, and it doesn't work there. So Im trying to get this to work instead.
I don't know. Sounds like a config issue or your app possibly isn't responding to requests. It's not anything to do with this image though. I and many others use it every day to do the same exact thing you're trying to do.
Either way, you shouldn't need to expose port 80 on the app container to make haproxy work. Just point haproxy at 3000.
Or use any of the stuff I wrote out above. It works as-is. You can literally copy/paste it and add your own app container details.
Im sure it is not meteor-launchpad
issue.
So far, it looks like haproxy won't listen on public 80 port, so I'd perhaps need to do something like:
expose:
- '80'
Which is why I asked if meteor-launchpad
can make meteor run on port 80.
I tried setting haproxy TCP_PORTS
to 3000, and MODE
to http
, but that doesn't seem to work either.
I have literally no clue of what I'm doing, sorry if Im bugging you with questions much.
Ok, I've given up on haproxy, and decided to try nginx-proxy
, however I'm running into the same error:
503 Service Temporarily Unavailable
nginx/1.11.3
My docker config:
lets-encrypt:
image: 'jrcs/letsencrypt-nginx-proxy-companion:latest'
restart: always
tags:
- steemsports
volumes:
- '/opt/certs:/etc/nginx/certs'
- '/var/run/docker.sock:/var/run/docker.sock:ro'
volumes_from:
- nginx-proxy
nginx-proxy:
image: 'jwilder/nginx-proxy:latest'
ports:
- '80:80'
- '443:443'
restart: always
tags:
- steemsports
volumes:
- '/opt/certs:/etc/nginx/certs:ro'
- /etc/nginx/vhost.d
- '/var/run/docker.sock:/tmp/docker.sock:ro'
- /usr/share/nginx/html
web:
autoredeploy: true
environment:
- LETSENCRYPT_EMAIL=hidden
- LETSENCRYPT_HOST=preview.steemsports.com
- 'MONGO_URL=hidden'
- 'ROOT_URL=https://preview.steemsports.com/'
- VIRTUAL_HOST=preview.steemsports.com
- VIRTUAL_PORT=3000
image: 'furion/steemsports-web:latest'
restart: always
tags:
- steemsports
I've started nginx-proxy
first, then LE, then web app.
LE output:
[lets-encrypt-1]2016-11-28T20:03:00.242650199Z parse error: Invalid numeric literal at line 1, column 3
[lets-encrypt-1]2016-11-28T20:03:00.243910702Z Warning: '/etc/nginx/certs' does not appear to be a mounted volume.
[lets-encrypt-1]2016-11-28T20:03:00.253161011Z parse error: Invalid numeric literal at line 1, column 3
[lets-encrypt-1]2016-11-28T20:03:00.254331448Z Warning: '/etc/nginx/vhost.d' does not appear to be a mounted volume.
[lets-encrypt-1]2016-11-28T20:03:00.267364301Z parse error: Invalid numeric literal at line 1, column 3
[lets-encrypt-1]2016-11-28T20:03:00.267775667Z Warning: '/usr/share/nginx/html' does not appear to be a mounted volume.
[lets-encrypt-1]2016-11-28T20:03:00.284010902Z Sleep for 3600s
[lets-encrypt-1]2016-11-28T20:03:00.347398574Z 2016/11/28 20:03:00 Generated '/app/letsencrypt_service_data' from 2 containers
[lets-encrypt-1]2016-11-28T20:03:00.347445391Z 2016/11/28 20:03:00 Running '/app/update_certs'
[lets-encrypt-1]2016-11-28T20:03:00.353107948Z 2016/11/28 20:03:00 Watching docker events
[lets-encrypt-1]2016-11-28T20:03:00.366586383Z Reloading nginx proxy...
[lets-encrypt-1]2016-11-28T20:03:00.421315594Z 2016/11/28 20:03:00 Contents of /app/letsencrypt_service_data did not change. Skipping notification '/app/update_certs'
[lets-encrypt-1]2016-11-28T20:03:00.575676108Z Q2016/11/28 20:03:00 Generated '/etc/nginx/conf.d/default.conf' from 2 containers
[lets-encrypt-1]2016-11-28T20:03:00.590912288Z ;2016/11/28 20:03:00 [notice] 51#51: signal process started
[lets-encrypt-1]2016-11-28T20:03:00.592228552Z Creating/renewal preview.steemsports.com certificates... (preview.steemsports.com)
[lets-encrypt-1]2016-11-28T20:03:01.335406961Z 2016-11-28 20:03:01,332:INFO:simp_le:1383: Certificates already exist and renewal is not necessary, exiting with status code 1.
[lets-encrypt-1]2016-11-28T20:03:01.377512561Z Sleep for 3600s
[lets-encrypt-1]2016-11-28T20:07:28.048390032Z 2016/11/28 20:07:28 Received event die for container 9f275a0d0514
[lets-encrypt-1]2016-11-28T20:07:28.561427575Z 2016/11/28 20:07:28 Received event stop for container 9f275a0d0514
[lets-encrypt-1]2016-11-28T20:07:32.913395287Z 2016/11/28 20:07:32 Received event start for container 00c12b93e375
[lets-encrypt-1]2016-11-28T20:07:47.913567562Z 2016/11/28 20:07:47 Debounce minTimer fired
[lets-encrypt-1]2016-11-28T20:07:47.982855471Z 2016/11/28 20:07:47 Generated '/app/letsencrypt_service_data' from 2 containers
[lets-encrypt-1]2016-11-28T20:07:47.982903482Z 2016/11/28 20:07:47 Running '/app/update_certs'
[lets-encrypt-1]2016-11-28T20:07:47.998515899Z Creating/renewal preview.steemsports.com certificates... (preview.steemsports.com)
[lets-encrypt-1]2016-11-28T20:07:48.719681502Z 2016-11-28 20:07:48,717:INFO:simp_le:1383: Certificates already exist and renewal is not necessary, exiting with status code 1.
[lets-encrypt-1]2016-11-28T20:07:48.762292259Z Sleep for 3600s
Sounds like a problem with your app - which I don't have access to.
Ugh, I have spent a few hours chasing my tail - all for nothing. I assume there was nothing wrong with haproxy config either.
The issue was an incorrect Cloudflare setting. Changing SSL from Flexible
to Full (strict)
fixed the issue.
Everything 'just works' now.
Isn't that always how it is? :)
Glad to hear it's working.
Just for kicks of it, I got it to work on haproxy as well (on port 3000). The trick is to set FORCE_SSL
and VIRTUAL_HOST
vars.
haproxy:
image: 'interaction/haproxy:master'
links:
- letsencrypt
- web
ports:
- '80:80'
- '443:443'
roles:
- global
tags:
- steemsports-web
volumes_from:
- letsencrypt
letsencrypt:
environment:
- DOMAINS=preview2.steemsports.com
- EMAIL=HIDDEN
expose:
- '80'
image: 'interaction/letsencrypt:master'
tags:
- steemsports-web
web:
autoredeploy: true
environment:
- FORCE_SSL=yes
- 'VIRTUAL_HOST=https://*'
- 'MONGO_URL=HIDDEN'
- 'ROOT_URL=https://preview2.steemsports.com/'
expose:
- '3000'
image: 'furion/steemsports-web:latest'
restart: always
tags:
- steemsports-web
I have run into this same issue. I'm curious why a misconfiguration in cloudflare would cause the container to not think the directories are mounted. I use cloudflare but only for dns. I don't route any ssl/traffic through them. I can log into the container and navigate to the directories that it says aren't mounted. Any insight on this?
Are there any plans to add Lets Encrypt SSL support as an option to deployment.
I think this would be a killer feature.
If not, do you happen to know any good ways to setup nginx or other reverse proxy in combination with meteor-launchpad?