Dockerfile for Static Website with Caddy Webserver: Modern, Secure, and Simple Deployment
This guide will walk you through creating a robust Dockerfile using Caddy as the web server, exploring best practices, configuration techniques, and practical implementation strategies for containerizing static websites.
Why Caddy? Understanding Its Unique Advantages
Caddy stands out among web servers for several compelling reasons:
- Automatic HTTPS: Caddy automatically provisions and renews SSL/TLS certificates using Let's Encrypt, eliminating complex manual configuration.
- Simplicity: Its configuration is more readable and concise compared to traditional web servers like Nginx or Apache.
- Modern Protocol Support: Built-in support for HTTP/2 and HTTP/3 out of the box.
- Security by Default: Implements best security practices natively.
Designing the Dockerfile for a Caddy-Powered Static Website
Let's create a comprehensive Dockerfile that demonstrates Caddy's strengths in static website deployment:
# Use official Caddy image as base
FROM caddy:2.7-alpine
# Set working directory
WORKDIR /app
# Copy website files
COPY ./website/ /app/
# Optional: Custom Caddyfile for advanced configuration
COPY Caddyfile /etc/caddy/Caddyfile
# Expose ports for HTTP and HTTPS
EXPOSE 80 443
# Default Caddy command
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
Dockerfile Breakdown
Base Image Selection
- We use the official
caddy:2.7-alpine
image, which provides a minimal Alpine Linux-based Caddy installation. - Alpine ensures a lightweight, security-focused container with minimal overhead.
Working Directory
/app
is set as the working directory for website files.- Provides a clear, organized location for static content.
File Copying
- Copies entire website directory into the container.
- Allows flexible placement of static assets.
Sample Caddyfile Configuration
{
# Global options
email your-email@example.com # For Let's Encrypt registration
}
example.com {
# Serve static files
root * /app
# Enable compression
encode gzip
# Security headers
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-XSS-Protection "1; mode=block"
X-Frame-Options "DENY"
Content-Security-Policy "default-src 'self'"
}
# File server configuration
file_server
}
Configuration Insights
- Automatic HTTPS: Caddy handles SSL certificate management automatically.
- Performance Optimization: Gzip compression enabled.
- Security Headers: Implements robust security configurations.
- Simple Routing: Straightforward static file serving.
Multi-Stage Build for Enhanced Flexibility
For more complex static sites with build processes, implement a multi-stage build:
# Build Stage
FROM node:alpine AS builder
WORKDIR /build
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Final Stage
FROM caddy:2.7-alpine
WORKDIR /app
COPY --from=builder /build/dist /app
COPY Caddyfile /etc/caddy/Caddyfile
EXPOSE 80 443
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
Advanced Deployment Strategies
Docker Compose Integration
version: '3.8'
services:
website:
build: .
ports:
- "80:80"
- "443:443"
volumes:
- ./website:/app
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Security Considerations
- Non-Root Execution: Run Caddy as a non-privileged user.
- Minimal Image: Use Alpine-based images.
- Regular Updates: Keep base images and Caddy updated.
Secure Dockerfile Modification
FROM caddy:2.7-alpine
# Create non-root user
RUN addgroup -S webuser && adduser -S webuser -G webuser
# Set proper permissions
COPY --chown=webuser:webuser ./website /app
# Switch to non-root user
USER webuser
EXPOSE 80 443
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
Performance Optimization Techniques
- Caching Strategies: Leverage Caddy's built-in caching mechanisms.
- Compression: Enable gzip/brotli compression.
- HTTP/3 Support: Utilize modern protocol capabilities.
Continuous Integration Considerations
- Use multi-stage builds for complex projects
- Implement automated testing before container build
- Create separate Dockerfiles for development and production
Conclusion
Containerizing static websites with Caddy offers a modern, secure, and simplified approach to web hosting. By leveraging Docker and Caddy's unique capabilities, developers can create robust, easily deployable web applications with minimal configuration overhead.
Key Takeaways
- Caddy simplifies HTTPS configuration
- Docker provides consistent deployment environments
- Security and performance are built into the workflow
- Minimal configuration required for powerful web hosting