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)
Surprisingly or not, neither Docker nor Podman support exposing multiple containers on the same host's port right out of the box. Example: docker-compose failing scenario with "Service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash."
The above line will instruct Docker that the container's service can be connected to via port 8080. You can also expose multiple ports: By default, the EXPOSE keyword specifies that the port listens on TCP protocol.
It's ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application. You can connect multiple containers using user-defined networks and shared volumes.
Use an nginx reverse proxy:
apt-get install nginx
. Note: I've assumed you don't have apache or some other web server on the host already.../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. /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.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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With