A reverse proxy server is a server that typically sits in front of other web servers in order to provide additional functionality.
The issue
Docker containers are assigned random IPs and ports which makes addressing them much more complicated from a client perspective. By default, the IPs and ports are private to the host and cannot be accessed externally unless they are bound to the host.
Binding the container to the hosts port can prevent multiple containers from running on the same host.
For example, only one container can bind to port 80 at a time. This also complicates rolling out new versions of
the container without downtime since the old container must be stopped before the new one is started.
A reverse proxy can help with these issues as well as improve availability by facilitating zero-downtime deployments.
Installation nginx-proxy
There’s a nice solution: open_in_new nginx-proxy .
To start the reverse proxy:
docker container run -d \
-p 80:80 \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
nginxproxy/nginx-proxy
Or using docker-compose.yml:
version: '2'
services:
reverse-proxy:
container_name: reverse-proxy
image: nginxproxy/nginx-proxy
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
default:
name: reverse-proxy
Attaching new containers
To make our containers work with the reverse proxy, we need to do two things:
- Expose a port.
- Set a
VIRTUAL_HOSTvariable.
Example of some container configuration:
version: '2'
services:
app:
container_name: dorokhov.codes
image: dorokhov.codes
expose:
- "80"
environment:
VIRTUAL_HOST: dorokhov.codes
networks:
default:
name: dorokhov.codes
And we have to add our reverse proxy container to the dorokhov.codes network:
docker network connect dorokhov.codes reverse-proxy
Custom Nginx reverse proxy image
For a single upstream (not dynamic Docker discovery), you can build a small image that injects host and upstream via environment variables at startup.
Dockerfile:
FROM nginx:1.7
COPY default.conf /etc/nginx/conf.d/default.conf
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
default.conf:
server {
listen 80;
server_name {{NGINX_HOST}};
location / {
proxy_pass {{NGINX_PROXY}};
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host {{NGINX_HOST}};
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
entrypoint.sh:
#!/bin/bash
set -e
sed -i "s|{{NGINX_HOST}}|$NGINX_HOST|;s|{{NGINX_PROXY}}|$NGINX_PROXY|" /etc/nginx/conf.d/default.conf
cat /etc/nginx/conf.d/default.conf
exec "$@"
docker-compose.yml example:
proxy:
image: proxy:1.0
links:
- identidock
ports:
- "80:80"
environment:
- NGINX_HOST=142.93.71.92
- NGINX_PROXY=http://identidock:5000
Andrew Dorokhov