The goal: Make the webservice hosted inside a docker container available through a specific domain that we own (let's say mycooldomain.com - keep in mind to replace this placeholder name with your actual domain in EVERY instance).
For this to work on a standard linux distro, apache and certbot need to be installed. Additionally, a need a specific set of apache modules need to be enabled for this to work.
sudo apt install apache2 certbot python3-certbot-apache
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
a2enmod headers
a2enmod rewrite
a2enmod ssl
Let's assume that our docker-compose looks something like this:
version: "3"
services:
webservice:
build: .
ports:
- "127.0.0.1:XXXX:80"
with XXXX being an arbitrary internal port that our docker container binds to.
When in doubt, use
netstat -tln
to see what ports are already in use.
To start off, create a file named mycooldomain.com.conf
in
/etc/apache2/sites-available
with the following content (replacing mycooldomain.com with your domain and XXXX with the port used by your docker container)
<VirtualHost *:80>
ServerName mycooldomain.com
# Redirect http requests to https
RewriteEngine On
RewriteCond %{SERVER_NAME} =mycooldomain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName mycooldomain.com
# Forward host header
ProxyPreserveHost On
ProxyRequests Off
# Proxy everything to backend
ProxyPass / http://127.0.0.1:XXXX/
ProxyPassReverse / http://127.0.0.1:XXXX/
# SSL config
</VirtualHost>
</IfModule>
<IfModule mod_mime.c>
# Manifest file
AddType application/manifest+json webmanifest
</IfModule>
<VirtualHost *:80>
ServerName mycooldomain.com
# Redirect http requests to https
RewriteEngine On
RewriteCond %{SERVER_NAME} =mycooldomain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName mycooldomain.com
ProxyPass /WEBSOCKET_ENDPOINT_OF_APP_HERE ws://127.0.0.1:XXXX/WEBSOCKET_ENDPOINT_OF_APP_HERE
ProxyPassReverse /WEBSOCKET_ENDPOINT_OF_APP_HERE ws://127.0.0.1:XXXX/WEBSOCKET_ENDPOINT_OF_APP_HERE
# Forward host header
ProxyPreserveHost On
ProxyRequests Off
# Proxy everything to backend
ProxyPass / http://127.0.0.1:XXXX/
ProxyPassReverse / http://127.0.0.1:XXXX/
# SSL config
</VirtualHost>
</IfModule>
<IfModule mod_mime.c>
# Manifest file
AddType application/manifest+json webmanifest
</IfModule>
<VirtualHost *:80>
ServerName mycooldomain.com
# Redirect http requests to https
RewriteEngine On
RewriteCond %{SERVER_NAME} =mycooldomain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName mycooldomain.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "ws://127.0.0.1:XXXX%{REQUEST_URI}" [P]
# Forward host header
ProxyPreserveHost On
ProxyRequests Off
# Proxy everything to backend
ProxyPass / http://127.0.0.1:XXXX/
ProxyPassReverse / http://127.0.0.1:XXXX/
# SSL config
</VirtualHost>
</IfModule>
<IfModule mod_mime.c>
# Manifest file
AddType application/manifest+json webmanifest
</IfModule>
To enable your config, run
a2ensite mycooldomain.com.conf
systemctl reload apache2
to create a symlink in /etc/apache2/sites-enabled
.
Next, head over to your domain registrar and set an A Record that points to the IP address of the host machine. If you are unsure how to do this, google "set A record YOUR-REGISTRAR-NAME".
In order to enable https for your domain, you can use certbot to create a ssl certificate.
Simply run
certbot
and enter the number next to mycooldomain.com. We do not need the http->https redirect, as our config already takes care of that.
After certbot finishes, thats it. Your webservide in the docker container is now reachable via mycooldomain.com.
Run
crontab -e
and choose your prefered editor (1 for nano).
At the botton, add
0 2 * * * certbot renew
This will check if your certificates need renewal every day at 2 am and renew them that if necessary.
To disable the daily emails telling you that no renewal was necessary, run:
certbot renew --quiet --post-hook "sudo service nginx reload"
In order to undo the actions described above, run the following commands:
a2dissite mycooldomain.com.conf
systemctl reload apache2
certbot delete --cert-name mycooldomain.com
and remove the file mycooldomain.com.conf
from
/etc/apache2/sites-available
.
To enable basic auth for a subdomain, add the following to the apache config (filling in your domain name):
<VirtualHost *:443>
...
<Location />
Deny from all
AuthUserFile "/etc/apache2/passwd_files/mycooldomain.com.htpasswd"
AuthName "Enter your credentials"
AuthType Basic
Satisfy Any
require valid-user
</Location>
...
</VirtualHost>
then, create the folder
mkdir -p /etc/apache2/passwd_files/
and create your credential file:
htpasswd -B -c /etc/apache2/passwd_files/mycooldomain.com.htpasswd root
and enter the password you want. (delete a user by deleting the line from the file)
Reload the apache once you are done.
a2dissite auf die conf
should bea2dissite mycooldomain.com.conf