I have 2 websites that clients need to connect to on port 80. Each website runs in its own container. I want to run both containers on the same Docker host.
I understand that port 80 can only be exposed on the Host one time. What solutions exist that have minimal overhead/administration that will allow me to simply run both containers on the same host (while still allowing clients to reach each container on port 80) ?
Both website 1 and website 2 should appear to client the web browser on port 80 and have friendly URL's (ie: www.web1.com, www.web2.com)
Use an nginx reverse proxy:
- install Nginx on the host. On Debian/Ubuntu:
apt-get install nginx
. Note: I've assumed you don't have apache or some other web server on the host already...
- For each site, write an nginx site file in directory
/etc/nginx/sites-available
that redirects that site to a docker container's http that will run on some other prearranged port (for example, 2001, 2002, ...). Each site gets its own file, like the one below, but with different prearranged ports for each site. External users will access these at port 80 of the same IP address but with different web site names, and from these names nginx will handle the necessary internal connections invisibly.
- symlink the site files so they show up in directory
/etc/nginx/sites-enabled
and restart nginx
. Later, you can remove one of these links and restart nginx if you need to temporarily disable access to a site.
- start the containers on system restart by adding
docker run
commands to /etc/rc.local
, and redirecting the prearranged host port (localhost:2001) to container port 80 e.g. docker run -d -p localhost:2001:80 imageA
If a container is down you will get a gateway error from nginx. This could be customized to show a custom HTML page. For more robustness, it might be better to manage the containers in supervisord
or some other process manager that respawns dead processes.
Here is an example nginx site file for a redirection to port 2001:
upstream dockerA {
server localhost:2001;
}
server {
listen 192.168.1.8:80; // REPLACE WITH HOST NUMERIC IP ADDRESS
root /var/web/siteAstaticfiles;
index index.html;
server_name www.siteA.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://dockerA;
}
}
In this example, although a local disk directory for HTML files is set up for site A, it is not used. Instead all requests are sent to the upstream. I haven't tested whether the root
and index
lines can be safely omitted.
A more proper way to host multiple websites on a single host using docker, docker-compose and nginx-proxy:
https://blog.florianlopes.io/host-multiple-websites-on-single-host-docker/