如何在单个VirtualHost上部署Django与Gatsby(Apache+mod_wsgi)
实现同一域名下Gatsby前端与Django后端的分离部署(Apache+mod_wsgi)
完全理解你的偏好——方案二确实是更优雅的选择,前后端职责清晰,维护起来也更省心,不会把静态托管的逻辑混进Django里。下面就一步步教你配置Apache VirtualHost,实现你想要的访问规则:
核心思路
让Apache同时承担两个角色:
- 作为静态文件服务器,处理根路径
/的所有请求,直接返回Gatsby生成的静态页面 - 作为WSGI网关,将
/api和/admin开头的请求转发给Django的mod_wsgi进程处理
完整VirtualHost配置
先把配置代码贴出来,后面再逐个解释关键部分:
<VirtualHost *:443> ServerName my-domain.com # SSL证书配置(根据你的实际证书路径调整) SSLEngine on SSLCertificateFile /etc/ssl/certs/my-domain.crt SSLCertificateKeyFile /etc/ssl/private/my-domain.key SSLCertificateChainFile /etc/ssl/certs/chain.crt # 若使用CA证书链则添加 # 1. 处理Gatsby前端:根路径指向静态文件目录 Alias / /var/www/gatsby/public/ <Directory /var/www/gatsby/public/> Options -Indexes +FollowSymLinks AllowOverride None Require all granted # 关键:处理Gatsby SPA路由(刷新子页面不会404) RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </Directory> # 2. 配置Django的mod_wsgi运行环境 WSGIDaemonProcess django \ python-home=/var/www/django/venv \ # Django虚拟环境路径 python-path=/var/www/django/project # Django项目根目录(包含settings.py的目录) WSGIProcessGroup django # 3. 路由/api和/admin请求到Django RewriteEngine On RewriteCond %{REQUEST_URI} ^/api/ [OR] RewriteCond %{REQUEST_URI} ^/admin/ RewriteRule ^/(.*)$ /var/www/django/project/wsgi.py/$1 [PT] WSGIScriptAlias / /var/www/django/project/wsgi.py process-group=django <Directory /var/www/django/project> <Files wsgi.py> Require all granted </Files> </Directory> # 关键:允许传递Authorization头给Django(API认证必备) WSGIPassAuthorization On </VirtualHost>
关键配置解释
Gatsby静态文件处理
Alias / /var/www/gatsby/public/:把根路径映射到Gatsby构建后的public目录(运行gatsby build生成)- 内部的Rewrite规则是为了解决SPA的路由问题:当用户刷新
/about这类前端路由时,Apache会把请求转发到index.html,让Gatsby的前端路由去处理,避免404
Django mod_wsgi配置
WSGIDaemonProcess:指定Django运行的虚拟环境和项目路径,确保mod_wsgi用正确的Python环境加载Django- Rewrite规则:只匹配
/api或/admin开头的请求,通过[PT]标志传递给后续的WSGIScriptAlias处理,这样Django收到的请求路径和你在urls.py中配置的一致(比如/api/users就是Django中path('api/users/', ...)对应的路由) WSGIPassAuthorization On:如果你的API使用Token认证(比如JWT),必须开启这个选项,否则Apache会自动丢弃Authorization请求头,导致Django无法识别认证信息
额外准备工作
Gatsby端
- 运行
gatsby build生成静态文件,把public目录放到Apache能访问的路径(比如/var/www/gatsby/public) - 确保目录权限正确:设置Apache运行用户(通常是
www-data)对该目录有可读权限
Django端
- 确保
ALLOWED_HOSTS包含my-domain.com - 运行
python manage.py collectstatic把admin的静态文件收集到STATIC_ROOT,并在Apache中配置Alias /static/指向该目录(可选补充配置:Alias /static/ /var/www/django/static/,然后对应Directory权限设置为Require all granted) - 安装并配置
django-cors-headers,允许Gatsby前端跨域调用API:# settings.py INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... ] CORS_ALLOWED_ORIGINS = [ "https://my-domain.com", ]
为什么方案二更优?
- 职责分离:Gatsby专注于静态页面构建,Django专注于API和后台管理,各自独立迭代部署
- 灵活性高:以后如果要替换前端框架(比如换成Next.js),只需要替换静态文件目录,不需要改动Django配置
- 性能更好:静态文件直接由Apache处理,比通过Django转发效率更高
验证步骤
- 重启Apache服务:
sudo systemctl restart apache2 - 访问
https://my-domain.com,确认Gatsby前端正常加载 - 访问
https://my-domain.com/admin,确认Django后台正常显示 - 测试API接口,比如
https://my-domain.com/api/hello,确认能返回预期数据
内容的提问来源于stack exchange,提问作者user3193620
相关产品推荐
相关产品推荐

