Hosting Multiple Dockerized Websites on a Single Host
Video Demonstration
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 /etc/hosts
file.
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.
Build Script
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"
Run Script
#!/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
Settings
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"
First published: 16th August 2018