Here’s a simple way to set up multiple Docker containers on a single host, with each container representing a unique domain, and each container protected with a LetsEncrypt SSL certificate. To achieve this we’ll meet the following requirments:
- Host Ubuntu droplet with Apache manages SSL for three containers
- Each container serves a separate application
- Host Ubuntu Apache uses reverse proxy to serve each application
Host droplet VHOST configuration
The configuration in these examples (abc.com) is the same for all the domains:
abc.com.conf
<VirtualHost *:80>
ServerName abc.com
ServerAlias www.abc.ca
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1.1:8080/
</VirtualHost>
abc.com-le-ssl.conf
Note, you need mod_ssl
and mod_proxy
enabled in Apache for this to work.
Note, also, that the SSL certificates are all stored and managed on the Ubuntu host, not on the containers.
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName abc.com
ServerAlias www.abc.com
SSLProxyEngine On
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/abc.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/abc.com/privkey.pem
</VirtualHost>
</IfModule>
Container VHOST configuration
The configuration in this example (container #1, abc.com) is the same for all the containers:
Note, it is not necessary to set up SSL certs or SSL VHOST on the container.
000-default.conf
<VirtualHost *:80>
ServerName localhost
DocumentRoot /var/www/code/public
<Directory /var/www/code/public>
Options FollowSymLinks Indexes
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}.access.log combined
</VirtualHost>
Container docker-compose.yml
configuration
The configuration in this example is the same for all the containers, with the exception of the forwarded port incrementing by one in each container. eg, 8080, 8081, 8082, etc:
services:
httpd:
image: "php:8.4.1-apache"
restart: 'no'
ports:
- "8080:80"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- .:/var/www
- ./config/sites-available:/etc/apache2/sites-available
- ./config/php:/usr/local/etc
build:
context: .
dockerfile: ./Dockerfile
networks:
default:
name: mysites
Conclusion
Obviously, this is a simplified setup in order to demonstrate the basic principles. This was quit easy to setup, once I figured it out. The host Ubuntu system was the cheapest droplet available on DigitalOcean, and it worked fine. The only software installed on it was apache2. The only ports open on the host firewall were 22, 80 and 443.