Traefik与Apache虚拟主机配置:多域名路由至单个Apache容器的实现方案咨询
Hey there! Great question—you’re totally right that spinning up separate Apache containers for each site is inefficient. Let’s get this working with one Apache instance and Traefik handling all the routing magic.
Core Concept
Traefik will act as your entry point, routing all incoming requests for page1.mydomain.es, page2.mydomain.es, etc., to the same Apache container. Apache will then use its virtual host (VirtualHost) functionality to serve the correct site content based on the requested domain.
Step 1: Configure Traefik to Route Multiple Domains to Apache
In your Docker Compose file, you’ll need to add Traefik labels to your Apache service that tell Traefik to match all your target domains. Here’s how that looks:
services: traefik: image: traefik:v2.11 command: - "--api.insecure=true" # Only for testing, disable in production - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" ports: - "80:80" - "8080:8080" # Traefik Dashboard volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" apache: image: httpd:2.4 volumes: # Mount your site directories and Apache configs - ./apache/sites:/usr/local/apache2/htdocs - ./apache/config/httpd.conf:/usr/local/apache2/conf/httpd.conf - ./apache/config/extra/httpd-vhosts.conf:/usr/local/apache2/conf/extra/httpd-vhosts.conf labels: - "traefik.enable=true" # Route requests for ALL your domains to this Apache container - "traefik.http.routers.apache.rule=Host(`page1.mydomain.es`) || Host(`page2.mydomain.es`) || Host(`page3.mydomain.es`)" - "traefik.http.routers.apache.entrypoints=web" - "traefik.http.services.apache.loadbalancer.server.port=80" # Apache's internal port
Step 2: Configure Apache Virtual Hosts
Now you need to set up Apache to recognize each domain and serve the right content. You have two easy options here:
Option A: Use mod_vhost_alias (Automated Setup)
This module lets you map domains to directories dynamically, so you don’t have to write a separate VirtualHost block for every site.
First, enable
mod_vhost_aliasin your Apachehttpd.conf:LoadModule vhost_alias_module modules/mod_vhost_alias.soAdd this to your
httpd-vhosts.conf:<VirtualHost *:80> UseCanonicalName Off VirtualDocumentRoot /usr/local/apache2/htdocs/%0 # Optional: Logs per domain CustomLog /usr/local/apache2/logs/access.log vhost_combined </VirtualHost>%0will match the full domain (e.g.,page1.mydomain.esmaps to/usr/local/apache2/htdocs/page1.mydomain.es)- Just create a directory for each site under
./apache/sites(likepage1.mydomain.es,page2.mydomain.es) and drop your site files there.
Option B: Manual Virtual Host Blocks (For Fine-Grained Control)
If you need specific settings for individual sites (like custom headers or SSL), define separate VirtualHost blocks:
<VirtualHost *:80> ServerName page1.mydomain.es DocumentRoot /usr/local/apache2/htdocs/page1 ErrorLog /usr/local/apache2/logs/page1-error.log CustomLog /usr/local/apache2/logs/page1-access.log combined </VirtualHost> <VirtualHost *:80> ServerName page2.mydomain.es DocumentRoot /usr/local/apache2/htdocs/page2 ErrorLog /usr/local/apache2/logs/page2-error.log CustomLog /usr/local/apache2/logs/page2-access.log combined </VirtualHost>
- Make sure your site files are in the corresponding
page1,page2directories under./apache/sites.
Step 3: Verify Everything Works
- Start your containers with
docker-compose up -d - Check the Traefik Dashboard at
http://your-docker-host-ip:8080to confirm the Apache router is listed with all your domains. - Test each domain in a browser or with
curl:
You should see the content from each respective site directory.curl http://page1.mydomain.es curl http://page2.mydomain.es
Bonus: Production Considerations
- Disable
--api.insecure=truein Traefik and set up HTTPS with Let’s Encrypt using Traefik’s ACME provider. - Ensure your domain DNS records point to your Docker host’s public IP.
- Restrict Traefik’s Docker socket access for security (use a Docker network instead of mounting the socket directly if possible).
内容的提问来源于stack exchange,提问作者rodriciru

