Set up SSL/TLS for an Application in Docker
How to Install SSL/TLS for an Application Running in Docker
Overview
Terminating SSL at a reverse proxy (Nginx) in front of the container makes certificate management and application configuration easier. Nginx handles HTTPS and certificates and redirects requests to the application (serves plain HTTP internally) over an internal Docker network.
Client –HTTPS (443)–> Nginx (reverse proxy) –HTTP–> App container (e.g., 3000)
Prerequisites
- Your application must already be running inside a Docker container. In this example, the application uses port 3000 to receive requests.
- You need a domain name. Also, a DNS record that connects this domain name to your server’s public IP address.
- You need to allow ports 80 and 443 in your server firewall and any applicable cloud security group.
- An Ubuntu server with sudo access.
- Step 1: Bind the App to Localhost Only
Publish the container port on localhost so it can be accessed only through the proxy.
bash
docker run -d –name myapp –restart unless-stopped -p 127.0.0.1:3000:3000 myapp:latest
For Compose:
yaml
services:
myapp:
image: myapp:latest
restart: unless-stopped
ports:
– “127.0.0.1:3000:3000” - Step 2: Install Nginx and Certbot
bash
sudo apt-get update
sudo apt-get install -y nginx certbot python3-certbot-nginx - Step 3: Create the Nginx Site Configuration
Create /etc/nginx/sites-available/app.example.com:
nginx
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
}
}
Enable and test:
bash
sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx - Step 4: Issue the Certificate (Let’s Encrypt)
bash
sudo certbot –nginx -d app.example.com –redirect -m [email protected] –agree-tos -n
Certbot obtains the certificate, updates the Nginx config for HTTPS, and adds an HTTP-to-HTTPS redirect. - Step 5: Verify Auto-Renewal
bash
sudo systemctl status certbot.timer
sudo certbot renew –dry-run
Certificates are valid for 90 days and they will get renewed automatically. - Step 6: Validate
bash
curl -I https://app.example.com
Also test with an external tool such as SSL Labs. This helps to confirm the chain and protocol configuration.
Alternative A: Using a Commercial or Existing Certificate
Place the files on the server (e.g., /etc/ssl/app/fullchain.pem and privkey.pem, with the private key set to chmod 600), then use this in the Nginx server block:
nginx
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/ssl/app/fullchain.pem;
ssl_certificate_key /etc/ssl/app/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name app.example.com;
return 301 https://hostrequest_uri;
}
Ensure fullchain.pem contains the server certificate followed by the intermediate certificates.
Alternative B: Fully Containerized with Caddy (Automatic HTTPS)
Caddy obtains and renews certificates automatically with minimal configuration.
docker-compose.yml:
yaml
services:
myapp:
image: myapp:latest
restart: unless-stopped
caddy:
image: caddy:2
restart: unless-stopped
ports:
– “80:80”
– “443:443”
volumes:
– ./Caddyfile:/etc/caddy/Caddyfile
– caddy_data:/data
– caddy_config:/config
volumes:
caddy_data:
caddy_config:
Caddyfile:
app.example.com {
reverse_proxy myapp:3000
}
Run docker compose up -d. No need to publish ports for myapp. Caddy can access the application directly through the Docker Compose network.
Security control configuration
- Allow only TLS 1.2 and TLS 1.3. Also, disable older and unsafe protocols.
- Enable HSTS after confirming HTTPS works correctly. This tells browsers to use HTTPS for future connections.
- add_header Strict-Transport-Security “max-age=31536000; includeSubDomains” always;
- Never bake private keys into images. Don’t commit them to source control.
- Restrict firewall access to ports 80 (HTTP), 443 (HTTPS), and SSH only.
- Keep track of certificate expiry and renewal logs.
| Troubleshooting | ||
| Symptom | Likely Cause | Fix |
| Certbot challenge fails | DNS not pointing to server, or port 80 blocked | Verify the A record and firewall rules |
| 502 Bad Gateway | Container down or wrong port | Check docker ps and the proxy_pass target |
| Mixed content warnings | App generating HTTP links | Honor X-Forwarded-Proto in the app or framework |
| Browser shows incomplete chain | Missing intermediate certificate | Use the full chain file |
| Renewal fails | Port 80 closed or Nginx config error | Run certbot renew –dry-run and check /var/log/letsencrypt/ |
Conclusion
Velan’s remote infrastructure team can handle certificate issuance, reverse proxy setup, renewal monitoring, and TLS hardening remotely. We are an ISO certified firm for quality processes and data security. With our managed services, we deliver the best container management solutions for our customers across 12+ countries, including the UK and the US. Contact our team at [email protected]
Questions and Answers About Docker
A Docker image is a lightweight, read-only software package template. It contains everything needed to run an application.
A Docker image has
Application code
Libraries
Dependencies
Configuration
Velan Remote IT Support offers the top managed service provider for Docker services in AWS. We have expertise in working with Docker container management and deployment technologies. Schedule a free cloud consultation with our experts to get a customized quote for AWS Docker services.
As a leading MSP for container management support, Velan Remote IT Support helps businesses configure and manage a Docker proxy for secure and reliable communication between containers and external systems. Our IT experts assist with proxy settings, network connectivity, access controls, and troubleshooting to keep Docker-based applications running smoothly.
The issue can be solved by doing the following steps
Open Task Manager→ Performance → CPU.
Check whether virtualization is enabled.
If it is disabled, restart your computer and enable virtualization in the BIOS/UEFI settings.
Turn Windows features on in the Start menu.
For Linux, enable ‘Virtual Machine Platform’ and ‘Windows Subsystem’.
Open PowerShell as an administrator and run wsl –update.
Restart the computer.
Open Docker Desktop again and check whether the error is fixed.
Categories
- Applications 013