Skip to content

Commit

Permalink
Allow to use the official nginx image and docker-gen in separate cont…
Browse files Browse the repository at this point in the history
…ainers
  • Loading branch information
JrCs committed Feb 17, 2016
1 parent 5c6d639 commit 0d6d105
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 13 deletions.
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,47 @@ Then start any containers you want to proxied with a env var `VIRTUAL_HOST=subdo

The containers being proxied must [expose](https://docs.docker.com/reference/run/#expose-incoming-ports) the port to be proxied, either by using the `EXPOSE` directive in their `Dockerfile` or by using the `--expose` flag to `docker run` or `docker create`. See [nginx-proxy](https://github.com/jwilder/nginx-proxy) for more informations. To generate automatically Let's Encrypt certificates see next section.

#### Separate Containers (recommended method)
nginx proxy can also be run as two separate containers using the [jwilder/docker-gen](https://github.com/jwilder/docker-gen)
image and the official [nginx](https://hub.docker.com/_/nginx/) image.

You may want to do this to prevent having the docker socket bound to a publicly exposed container service.

To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) on your host system and set the `NGIX_DOCKER_GEN_CONTAINER`environment variable to the name or id of the docker-gen container.

* First start nginx (official image) with volumes:
```bash
$ docker run -d -p 80:80 -p 443:443 \
--name nginx \
-v /etc/nginx/conf.d \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /path/to/certs:/etc/nginx/certs:ro \
nginx
```

* Second start the docker-gen container with the shared volumes and the template file:
```bash
$ docker run -d \
--name nginx-gen \
--volumes-from nginx \
-v /path/to/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/docker-gen \
-notify-sighup nginx -watch -only-exposed -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
```

* Then start this container (NGIX_DOCKER_GEN_CONTAINER variable must contain the docker-gen container name or id):
```bash
$ docker run -d \
-e NGINX_DOCKER_GEN_CONTAINER=nginx-gen \
--volumes-from nginx \
-v /path/to/certs:/etc/nginx/certs:rw \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion
```
Then start any containers to be proxied as described previously.

#### Let's Encrypt

To use the Let's Encrypt service to automatically create a valid certificate for virtual host(s).
Expand All @@ -57,7 +98,7 @@ The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL
For example

```bash
$ docker run -d -p 80:80 \
$ docker run -d \
-e VIRTUAL_HOST="foo.bar.com,bar.com" \
-e LETSENCRYPT_HOST="foo.bar.com,bar.com" \
-e LETSENCRYPT_EMAIL="foo@bar.com" ...
Expand All @@ -83,3 +124,6 @@ $ docker run -d \
```

* `DEBUG` - Set it to `true` to enable debugging of the entrypoint script, which could help you pin point any configuration issues.

* `NGINX_PROXY_CONTAINER`- I for some reason you can't use the docker --volumes-from option, you can specify the name or id of the nginx-proxy container with this variable.

8 changes: 5 additions & 3 deletions app/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ function get_nginx_proxy_cid {
for cid in $volumes_from; do
cid=${cid%:*} # Remove leading :ro or :rw set by remote docker-compose (thx anoopr)
if [[ $(docker_api "/containers/$cid/json" | jq -r '.Config.Env[]' | egrep -c '^NGINX_VERSION=') = "1" ]];then
export NGINX_PROXY_CID=$cid
export NGINX_PROXY_CONTAINER=$cid
break
fi
done
if [[ -z "${NGINX_PROXY_CID:-}" ]]; then
if [[ -z "${NGINX_PROXY_CONTAINER:-}" ]]; then
echo "Error: can't get nginx-proxy container id !" >&2
echo "Check that you use the --volumes-from option to mount volumes from the nginx-proxy." >&2
exit 1
Expand Down Expand Up @@ -70,7 +70,9 @@ source /app/functions.lib

if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
check_docker_socket
get_nginx_proxy_cid
if [[ -z "${NGINX_DOCKER_GEN_CONTAINER:-}" ]]; then
[[ -z "${NGINX_PROXY_CONTAINER:-}" ]] && get_nginx_proxy_cid
fi
check_writable_directory '/etc/nginx/certs'
check_writable_directory '/etc/nginx/vhost.d'
check_writable_directory '/usr/share/nginx/html'
Expand Down
26 changes: 21 additions & 5 deletions app/functions.lib
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ remove_all_location_configurations() {
eval "$old_shopt_options" # Restore shopt options
}

## Docker
## Docker API
function docker_api {
local scheme
local curl_opts=(-s)
Expand All @@ -38,6 +38,10 @@ function docker_api {
if [[ -n "${3:-}" ]]; then
curl_opts+=(-d "$3")
fi
if [[ -z "$DOCKER_HOST" ]];then
echo "Error DOCKER_HOST variable not set" >&2
return 1
fi
if [[ $DOCKER_HOST == unix://* ]]; then
curl_opts+=(--unix-socket ${DOCKER_HOST#unix://})
scheme='http:'
Expand All @@ -58,11 +62,23 @@ function docker_exec {
fi
}

function docker_kill {
local id="${1?missing id}"
local signal="${2?missing signal}"
docker_api "/containers/$id/kill?signal=$signal" "POST"
}

## Nginx
reload_nginx() {
if [[ -n "${NGINX_PROXY_CID:-}" ]]; then
echo "Reloading nginx proxy..."
docker_exec "$NGINX_PROXY_CID" \
'[ "sh", "-c", "/usr/local/bin/docker-gen -only-exposed /app/nginx.tmpl /etc/nginx/conf.d/default.conf; /usr/sbin/nginx -s reload" ]'
if [[ -n "${NGINX_DOCKER_GEN_CONTAINER:-}" ]]; then
# Using docker-gen separate container
echo "Reloading nginx proxy (using separate container ${NGINX_DOCKER_GEN_CONTAINER})..."
docker_kill "$NGINX_DOCKER_GEN_CONTAINER" SIGHUP
else
if [[ -n "${NGINX_PROXY_CONTAINER:-}" ]]; then
echo "Reloading nginx proxy..."
docker_exec "$NGINX_PROXY_CONTAINER" \
'[ "sh", "-c", "/usr/local/bin/docker-gen -only-exposed /app/nginx.tmpl /etc/nginx/conf.d/default.conf; /usr/sbin/nginx -s reload" ]'
fi
fi
}
3 changes: 0 additions & 3 deletions app/letsencrypt_service
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,6 @@ pid=
trap '[[ $pid ]] && kill $pid; exec $0' EXIT
trap 'trap - EXIT' INT TERM

echo 'Waiting 15s before updating certs...'
sleep 15s

update_certs

# Wait some amount of time
Expand Down
2 changes: 1 addition & 1 deletion app/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ trap 'term_handler' INT QUIT KILL TERM
/app/letsencrypt_service &
letsencrypt_service_pid=$!

docker-gen -watch -only-exposed -notify '/app/update_certs' /app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data &
docker-gen -watch -only-exposed -notify '/app/update_certs' -wait 15s:60s /app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data &
docker_gen_pid=$!

# wait "indefinitely"
Expand Down

0 comments on commit 0d6d105

Please sign in to comment.