单域名下多应用及多版本的Apache适配配置技术问询
Great question—this is a common pain point when running multiple app environments on a single server, and the solution lies in using Apache VirtualHosts to isolate each app instance completely. Let's break this down step by step:
The core fix is to give each production/staging app instance its own VirtualHost with a unique hostname (either a subdomain of your company's domain or an internal custom hostname). This way, each app's code root becomes the web server's DocumentRoot, so relative paths and root-based routing work exactly as the app expects—no more hardcoding absolute paths.
1. Using Subdomains (For External/Internal Production/Staging Access)
If you want these apps accessible via your company's official domain structure, use subdomains like app1.example.com (production) and app1-staging.example.com (staging). Here's how to configure Apache:
Step 1: DNS Setup
First, add A records for each subdomain in your company's DNS manager, pointing all of them to your server's public IP address.
Step 2: Apache VirtualHost Config
Create separate VirtualHost blocks for each app environment. For example:
# Enable required modules first (if not already enabled) # a2enmod rewrite proxy proxy_fcgi # App 1 - Production Environment <VirtualHost *:80> ServerName app1.example.com # Point DocumentRoot directly to the app's public/web root (e.g., Laravel's public folder) DocumentRoot /var/www/app1/production/public <Directory /var/www/app1/production/public> Options -Indexes +FollowSymLinks AllowOverride All # Enables .htaccess for framework routing Require all granted # Configure PHP-FPM (adjust socket path to match your PHP version) SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" </Directory> # Logging for debugging ErrorLog ${APACHE_LOG_DIR}/app1-prod-error.log CustomLog ${APACHE_LOG_DIR}/app1-prod-access.log combined </VirtualHost> # App 1 - Staging Environment <VirtualHost *:80> ServerName app1-staging.example.com DocumentRoot /var/www/app1/staging/public <Directory /var/www/app1/staging/public> Options -Indexes +FollowSymLinks AllowOverride All Require all granted SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" </Directory> ErrorLog ${APACHE_LOG_DIR}/app1-staging-error.log CustomLog ${APACHE_LOG_DIR}/app1-staging-access.log combined </VirtualHost>
After adding these configs, restart Apache:
sudo systemctl restart apache2
2. Using /etc/hosts + VirtualHosts (Internal-Only Access)
Absolutely—this is a perfect approach for internal testing, development, or staging environments where you don't want to expose hostnames to public DNS. Here's how:
Step 1: Configure /etc/hosts
On every machine that needs to access these apps (including the server itself), edit /etc/hosts to map custom hostnames to your server's IP. For example:
# Replace 192.168.1.100 with your server's internal IP 192.168.1.100 app1-local.example.com 192.168.1.100 app1-staging-local.example.com
Step 2: Apache VirtualHost Config
Create VirtualHost blocks matching the hostnames you defined in /etc/hosts. The config is nearly identical to the subdomain setup—just change the ServerName:
<VirtualHost *:80> ServerName app1-local.example.com DocumentRoot /var/www/app1/production/public # Same directory and PHP config as production </VirtualHost> <VirtualHost *:80> ServerName app1-staging-local.example.com DocumentRoot /var/www/app1/staging/public # Same directory and PHP config as staging </VirtualHost>
Restart Apache, and you can now access http://app1-local.example.com or http://app1-staging-local.example.com from any machine with the updated /etc/hosts file.
Why This Works
- Each app instance has its own isolated
DocumentRoot, so relative paths like<link href="css/style.css">resolve to the app's owncssfolder, not a shared path. - Root-based routes (e.g.,
$router->map("GET", "/action", SomeController)) work because the app's root is the web server's root—no need to prefix routes with app-specific paths. - Production and staging code can be identical because they're running from separate directories, each mapped to its own hostname.
Key Notes
- SSL: If you need HTTPS, generate SSL certificates for each hostname (use Let's Encrypt for public subdomains, or self-signed certificates for internal hosts). Update the VirtualHosts to use
*:443and addSSLCertificateFile/SSLCertificateKeyFiledirectives. - Module Checks: Ensure Apache has
mod_rewrite,mod_proxy, andmod_proxy_fcgienabled (usea2enmod <module>to enable them). - Directory Permissions: Make sure Apache has read access to your app directories (set appropriate ownership, e.g.,
chown -R www-data:www-data /var/www/app1).
内容的提问来源于stack exchange,提问作者allpan

