Deploying your own applications doesn't have to be complicated. Docker Compose makes it easy to manage containers, while Caddy automatically handles HTTPS using Let's Encrypt. Together, they provide a simple and reliable setup for hosting websites, APIs, and self hosted applications.
In this guide, you'll create a basic production ready setup that includes:
- Docker Compose for managing containers
- Caddy as a reverse proxy and web server
- Automatic HTTPS with Let's Encrypt
- A simple test page before deploying your own application
Prerequisites
Before getting started, make sure you have:
- Ubuntu 26.04 dedicated server
- A domain name pointing to your server
- Docker installed
- Docker Compose plugin installed
Verify the installation:
docker --version
docker compose version
Step 1: Create the project directory
Create a directory for your project.
mkdir -p ~/apps/myapp/site
cd ~/apps/myapp
Your project structure should look like this:
myapp/
├── compose.yml
├── Caddyfile
└── site/
└── index.html
Step 2: Create the Docker Compose file
Create a file named compose.yml.
nano compose.yml
Add following content:
services:
caddy:
image: caddy:2
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./site:/srv
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
The caddy_data volume stores your SSL certificates, so they remain available even after updating the container.
Step 3: Configure Caddy
Create a file named Caddyfile.
nano Caddyfile
Add following content:
example.com {
root * /srv
file_server
}
Replace example.com with your own domain name.
Step 4: Create a test page
Inside the site directory, create an index.html file.
nano index.html
Add following content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Caddy Test Page</title>
</head>
<body>
<h1>🎉 Caddy is Working!</h1>
<p>Your Ubuntu 26.04 server is serving this page securely with HTTPS.</p>
</body>
</html>
This page helps confirm that your DNS, Docker, Caddy, and SSL certificate are all working correctly.
Step 5: Start Caddy
Launch the container.
docker compose up -d
Check that it is running.
docker compose ps
If your domain is already pointing to the server, Caddy will automatically request and install an SSL certificate.
Visit:
https://example.com
You should see the test page.
Step 6: View logs
If you need to troubleshoot, check the container logs.
docker compose logs -f
Hosting your application
Once everything is working, you can replace the test page with your own application.
Update your compose.yml.
services:
app:
image: ghcr.io/yourusername/myapp:latest
restart: unless-stopped
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- app
volumes:
caddy_data:
caddy_config:
Update the Caddyfile.
example.com {
reverse_proxy app:3000
}
Replace 3000 with the port used by your application.
Apply the changes.
docker compose up -d
Your application will now be available through Caddy with automatic HTTPS.
Caddy and Docker Compose are a great combination for hosting modern applications on Ubuntu 26.04. Caddy automatically manages HTTPS, while Docker Compose keeps your deployment simple and easy to maintain.
You can use this same setup for Node.js, Next.js, Go, Laravel, Python, or any application running inside a Docker container by simply updating the reverse_proxy target in your Caddyfile.
Top comments (0)