I've got a bunch of HTTP server images, but I need a single proxy
container that supports SNI to expose them to the world. This
container can link to a colleciton of HTTP-serving containers and
proxy them under arbitrary hostnames using user-supplied, per-host
certificates and keys.
env and sed are both in POSIX 2013 [1,2], and the:
eval A=\$$B
variable indirection is because POSIX [3] doesn't support Bash's
indirect expansion "A=${!B}". The 'tcp' -> 'http' replacement maps
Docker's tcp:://${IP}:${PORT} addresses to http://${IP}:${PORT} for
use in the Nginx config.
envsubst is in gettext [4] and not in POSIX [5], so it may be slightly
less portable. However, envsubst and gettext are in Gentoo's x86 and
amd64 stage1s, our Gentoo-based images will have it.
[1]: http://pubs.opengroup.org/onlinepubs/
9699919799/utilities/env.html
[2]: http://pubs.opengroup.org/onlinepubs/
9699919799/utilities/sed.html
[3]: http://pubs.opengroup.org/onlinepubs/
9699919799/utilities/V3_chap02.html#tag_18_06_02
[4]: http://www.gnu.org/software/gettext/
[5]: http://pubs.opengroup.org/onlinepubs/
9699919799/idx/utilities.html
|-- buildbot (adds a Buildbot master and slave)
|-- memcached (adds Memcached)
|-- nginx (adds Nginx)
+ | |-- nginx-proxy (SSL/TLS proxying via SNI)
| `-- kibana (adds Kibana)
|-- postgresql (adds PostgreSQL)
|-- redis (adds Redis)
elasticsearch
memcached
nginx
+ nginx-proxy
kibana
postgresql
redis
--- /dev/null
+# Copyright (C) 2014 W. Trevor King <wking@tremily.us>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+FROM ${NAMESPACE}/nginx:${TAG}
+MAINTAINER ${MAINTAINER}
+
+# Add a framework for easy virtual hosts
+RUN mkdir /etc/nginx/vhosts
+RUN chown nginx:nginx /etc/nginx/vhosts
+RUN sed -i 's|^\([[:space:]]*\)\(server {\)|\1include vhosts/*.conf;\n\n\1\2|' /etc/nginx/nginx.conf
+ADD vhost-template.conf /etc/nginx/vhosts/TEMPLATE
+RUN chown nginx:nginx /etc/nginx/vhosts/TEMPLATE
+ADD create-vhosts-from-environment.sh /usr/bin/create-vhosts-from-environment
+
+# Uncomment the default HTTPS server
+RUN sed -i 's/^\t#\([^ ]\)/\t\1/' /etc/nginx/nginx.conf
+RUN sed -i 's/listen 127.0.0.1:443;/listen 443 default_server;/' /etc/nginx/nginx.conf
+
+CMD create-vhosts-from-environment && rc default && tail -F /var/log/messages
+EXPOSE 443
--- /dev/null
+While the `nginx` container serves a single, unnamed host from
+`/var/www/localhost/htdocs`, this container uses [Nginx] to proxy a
+collection of virtual servers via hostname. It listens for both
+plaintext and [TLS][] connections, and uses [Server Name Indication
+(SNI)][SNI] to serve the appropriate [X.509][] certificate.
+
+Run this [Nginx][] image with:
+
+ $ docker run -d -name nginx-a -v /var/www/a.net/htdocs:/var/www/localhost/htdocs wking/nginx
+ $ docker run -d -name nginx-b -v /var/www/b.com/htdocs:/var/www/localhost/htdocs wking/nginx
+ $ docker run -d -name nginx-proxy-0 -link nginx-a:a -e A_NAME=a.com -link nginx-b:b -e B_NAME=b.net -v /etc/ssl/nginx-proxy-0:/etc/ssl/nginx -p 80:80 -p 443:443 wking/nginx-proxy
+
+[volume-mounting][volume-mount] your certificates and keys under the
+container's `/etc/ssl/nginx`. The `*_NAME` environment variables
+override Docker's [default][link-name] `/${LINKER}/${LINKEE}`. For
+example, without th `-e A_NAME=a.com` argument, `A_NAME` would be
+`/nginx-proxy-0/a`. You should avoid link aliases with `-` and `.` in
+them, because `A.NET_NAME` is not a valid shell variable.
+
+[HAProxy][] added native SSL support with [version 1.5-dev12
+(2012-09-10)][HAProxy-v1.5], but v1.5 isn't stable yet so I think
+Nginx is the best tool for this task.
+
+[Nginx]: http://nginx.org/
+[TLS]: http://en.wikipedia.org/wiki/Transport_layer_security
+[SNI]: http://en.wikipedia.org/wiki/Server_Name_Indication
+[X.509]: http://en.wikipedia.org/wiki/X.509
+[volume-mount]: http://docs.docker.io/en/latest/use/working_with_volumes/
+[link-name]: http://docs.docker.io/en/latest/use/working_with_links_names/
+[HAProxy]: http://haproxy.1wt.eu/
+[HAProxy-v1.5]: http://haproxy.1wt.eu/download/1.5/src/CHANGELOG
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2014 W. Trevor King <wking@tremily.us>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# usage: C1_PORT=tcp://192.168.0.1:12345/ C1_NAME=a.com \
+# C2_PORT=tcp://192.168.0.2:54321/ C2_NAME=b.net \
+# create-vhosts-from-environment
+
+for NAME_VARIABLE in $(env | sed -n 's/^\([^=]*_NAME\)=.*/\1/p'); do
+ URL_VARIABLE="${NAME_VARIABLE%_NAME}_PORT"
+ eval NAME="\$$NAME_VARIABLE"
+ eval URL="\$$URL_VARIABLE"
+ URL="http://${URL#tcp://}"
+ env -i \
+ NAME="${NAME}" \
+ URL="${URL}" \
+ envsubst '
+ ${NAME}
+ ${URL}
+ ' \
+ < /etc/nginx/vhosts/TEMPLATE > "/etc/nginx/vhosts/${NAME}.conf"
+done
--- /dev/null
+# Copyright (C) 2014 W. Trevor King <wking@tremily.us>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+server {
+ listen 80;
+ listen 443 ssl;
+ server_name ${NAME};
+
+ ssl on;
+ ssl_certificate /etc/ssl/nginx/${NAME}.pem;
+ ssl_certificate_key /etc/ssl/nginx/${NAME}.key;
+
+ access_log /var/log/nginx/${NAME}.ssl_access_log main;
+ error_log /var/log/nginx/${NAME}.ssl_error_log info;
+
+ root /var/www/${NAME}/htdocs;
+
+ location / {
+ proxy_pass ${URL};
+ proxy_set_header X-Forwarded-For $remote_addr;
+ }
+}