Information, Technology, Security, and other stuff.
I was mucking around with configuring nginx containers and binding containers to dedicated IP addresses just so I could expose the same web ports, but then I found this amazing Nginx proxy container made by Jason Wilder, and my life has been so much easier ever since.
The easiest way to show how it works is with a docker-compose file:
version: '2' services: nginx-proxy: container_name: nginx-proxy image: jwilder/nginx-proxy ports: - "80:80" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro
This is all it takes to make a basic reverse proxy. The key thing to note here is the volume passed through: this container will watch all of your other containers through the docker socket to automagically configure the proxy for you.
So, if we want to reverse proxy some services, all we need to do is put a
VIRTUAL_HOST environment variable onto each host:
version: "3" services: nginx-proxy: container_name: nginx-proxy image: jwilder/nginx-proxy ports: - "80:80" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro ghost: container_name: ghost image: ghost volumes: - ghost_data:/var/lib/ghost environment: - VIRTUAL_HOST=ghost.example.com - VIRTUAL_PORT=2368 restart: always wordpress: container_name: wordpress image: bitnami/wordpress:latest volumes: - wordpress_data:/bitnami/wordpress - apache_data:/bitnami/apache - php_data:/bitnami/php environment: - WORDPRESS_USERNAME=example - WORDPRESS_PASSWORD=changeme - WORDPRESS_EMAILemail@example.com - WORDPRESS_FIRST_NAME=Foo - WORDPRESS_LAST_NAME=Bar - WORDPRESS_BLOG_NAME=Foo Blog - WORDPRESS_DATABASE_PASSWORD=changeme - WORDPRESS_DATABASE_USER=wpuser - WORDPRESS_DATABASE_NAME=wp - VIRTUAL_HOST: wordpress.example.com depends_on: - mariadb restart: always mariadb: container_name: mariadb image: bitnami/mariadb:latest environment: - ALLOW_EMPTY_PASSWORD=no - MARIADB_ROOT_PASSWORD=changeme - MARIADB_DATABASE=wp - MARIADB_USER=wpuser - MARIADB_PASSWORD=changeme volumes: - mariadb_data:/bitnami/mariadb restart: always volumes: mariadb_data: driver: local wordpress_data: driver: local apache_data: driver: local php_data: driver: local ghost_data: driver: local
This example has Wordpress (bitnami-provided) and a Ghost blog running side-by-side. Wordpress, by default, listens on port
80 so we can just pass in the
VIRTUAL_HOST variable by itself. Ghost, by default, listens on port
2368 so we also have to pass in the
VIRTUAL_PORT variable for the proxy to use.
This is all that's needed though. No more messing around with reverse proxy configuration, nor do you need to expose any ports externally from the containers, you only need to open ports
443 from the proxy itself.
If you want to enable TLS/SSL to the services, then a little more config is required, but that can all be found in the documentation.
There are security issues that do need to be taken into consideration though. The simplicity of the proxy pulling information from the docker socket can lead to a compromised proxy to extract information from the other containers, as well as creating new containers on the host. The example above has the read-only (
ro) flag set for the volume, but this only mitigates some risk.
Ultimately to be safe you should only use this in test environments, or on machines that you don't really care about getting pwned, but nevertheless it saves a lot of build and configuration time.