Hosting Multiple Dockerized Websites on a Single Host
I've written about running multiple "dockerized" websites on a single host with the same port, but this required you to be able to assign multiple IPs to your host, which may not always be possible. The solution outlined below will allow you to deploy multiple websites on the same host by having the containers run on different public ports, but directing users to them through a reverse proxy. That way your users still don't need to type port numbers into the URI in order to get to your sites. This is a technique that I found on Jason Wilder's Blog. Its a simple solution which automatically registers and points to any website containers you spawn after the proxy container has initiated.
To get the frontend proxy running, you just need to run this command:
docker run -d \ -p 80:80 \ -v /var/run/docker.sock:/tmp/docker.sock \ -t jwilder/nginx-proxy
Then all you need to do is add the VIRTUAL_HOST environment variable to your container. This should be your site's domain.
docker run \ -e VIRTUAL_HOST=my.domain.com \ -p 80 \ ...
Now you should be able to view your website by plugging that
$VIRTUAL_HOST into your browser (so long as your computer resolves that domain name to where you are hosting the container). Navigating to the server by IP won't work! Linux users can achieve this in a dev environment by just updating their
Docker PHP Website Template
To simplify the creation of dockerized websites, I created a github template, which revolves primarily around two scripts which can be placed into any project, without any modifications necessary, in order to build and then run the container.
Below is my build script. It will move the Dockerfile above all of my project's files
#!/bin/bash if ! [ -n "$BASH_VERSION" ];then echo "this is not bash, calling self with bash...."; SCRIPT=$(readlink -f "$0") /bin/bash $SCRIPT exit; fi # Ensure that we are running in this scripts directory SCRIPT=$(readlink -f "$0") SCRIPTPATH=$(dirname "$SCRIPT") cd $SCRIPTPATH # Load settings (environment variables) source ../../settings/docker_settings.sh IMAGE_NAME="`echo $REGISTRY`/`echo $PROJECT_NAME`" # Copy the docker file up and run it in order to build the container. # We need to move the dockerfile up so that it can easily add everything to the container. cp -f Dockerfile ../../. cd ../../. # Ask the user if they want to use the docker cache read -p "Do you want to use a cached build (y/n)? " -n 1 -r echo "" # (optional) move to a new line if [[ $REPLY =~ ^[Yy]$ ]] then docker build --tag="$IMAGE_NAME" . else docker build --no-cache --tag="$IMAGE_NAME" . fi docker push $IMAGE_NAME echo "Run the container with the following command:" echo "bash run-container.sh"
#!/bin/bash # ensure running bash if ! [ -n "$BASH_VERSION" ];then echo "this is not bash, calling self with bash...."; SCRIPT=$(readlink -f "$0") /bin/bash $SCRIPT exit; fi # Setup for relative paths. SCRIPT=$(readlink -f "$0") SCRIPTPATH=$(dirname "$SCRIPT") cd $SCRIPTPATH # load the variables from the relative path # Feel free to change this relative path. source ../../settings/docker_settings.sh CONTAINER_IMAGE="`echo $REGISTRY`/`echo $PROJECT_NAME`" # Kill the container if it is already running. docker kill $PROJECT_NAME docker rm $PROJECT_NAME ####################### # ensure that we are running the frontend proxy # which allows us to run multiple web containers RESULT=`docker ps | grep jwilder | wc -l` if [ $RESULT -gt 0 ];then echo "found frontend proxy." else echo "Deploying frontend proxy" docker run -d \ -p 80:80 \ -v /var/run/docker.sock:/tmp/docker.sock \ -t jwilder/nginx-proxy fi ####################### # Now start the container. docker run -d \ -e VIRTUAL_HOST=$VIRTUAL_HOST \ -p 80 \ -p 443 \ --name="$PROJECT_NAME" \ $CONTAINER_IMAGE
An example settings file that would go along with the previous two scripts is as follows
VIRTUAL_HOST="images.programster.org" REGISTRY="docker-registry.programster.org:5000" PROJECT_NAME="dev-programster-images"