feat(k8s): 新增 core 真应用(前端+Django API+Celery worker)构建与部署
- core/frontend: Vite 多阶段镜像 + nginx 同源反代 /api,/admin,/static(零 CORS) - core/backend: Django gunicorn 镜像 + entrypoint(自动 migrate/collectstatic)+ WhiteNoise - k8s/core: api/worker/web Deployment+Service + ingress(airshelf-web.airlabs.art) - workflow: 追加 core 前后端 build/push,从 core/backend/.env 套生产覆盖生成 env Secret 后部署 - .gitignore 放行 core/backend/.env;.env 白名单加入 airshelf-web 域名 - 含前端 WIP 还原改动 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
.venv/
|
||||
**/__pycache__/
|
||||
*.pyc
|
||||
db.sqlite3
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
tests/
|
||||
*.md
|
||||
staticfiles/
|
||||
@@ -0,0 +1,24 @@
|
||||
DJANGO_SETTINGS_MODULE=airshelf.settings.development
|
||||
DJANGO_SECRET_KEY=S2GYXa8YC21lmnFfVwC+6cyFNhCCSoclhpylOmSAm16vKflUgQi398VQQSM+Rbit
|
||||
DJANGO_DEBUG=true
|
||||
DJANGO_ALLOWED_HOSTS=airshelf-web.airlabs.art,airshelf-web.test.airlabs.art,localhost,127.0.0.1,192.168.124.86
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS=https://airshelf-web.airlabs.art,https://airshelf-web.test.airlabs.art,https://airshelf.airlabs.art,https://api.airshelf.airlabs.art,http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173,http://192.168.124.86:5173
|
||||
CORS_ALLOWED_ORIGINS=https://airshelf-web.airlabs.art,https://airshelf-web.test.airlabs.art,https://airshelf.airlabs.art,http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173,http://192.168.124.86:5173
|
||||
DB_ENGINE=mysql
|
||||
DB_NAME=airshelf_test
|
||||
DB_USER=airshelf_app
|
||||
DB_PASSWORD=d5020f4d41e0e4c52a371ecb913be3d1f1ab2b85
|
||||
DB_HOST=14.103.27.192
|
||||
DB_PORT=3306
|
||||
DB_BIND_ADDRESS=192.168.124.86
|
||||
REDIS_CACHE_URL=redis://zyc:Zyc188208@redis-shzlsczo52dft8mia.redis.volces.com:6379/0
|
||||
CELERY_BROKER_URL=redis://zyc:Zyc188208@redis-shzlsczo52dft8mia.redis.volces.com:6379/1
|
||||
CELERY_RESULT_BACKEND=redis://zyc:Zyc188208@redis-shzlsczo52dft8mia.redis.volces.com:6379/2
|
||||
REDIS_LOCK_URL=redis://zyc:Zyc188208@redis-shzlsczo52dft8mia.redis.volces.com:6379/3
|
||||
TOS_ENDPOINT=https://tos-s3-cn-shanghai.volces.com
|
||||
TOS_BUCKET=airshelf
|
||||
TOS_ACCESS_KEY_ID=AKLTODVhY2U1NzY1MTU3NDA4NThiYzk2ZDMyZDNjYmZhZGY
|
||||
TOS_SECRET_ACCESS_KEY=TWpjNVpqVm1NbVkzTWprNE5ESXlZMkUyT1dNNFlqVmtaRGRoTVdNME5qRQ==
|
||||
VOLCANO_ARK_API_KEY=ark-24d5627e-28e4-4412-8679-46a6e9f26aab-6e951
|
||||
VOLCANO_ARK_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
||||
DEFAULT_TRIAL_CREDITS=1000.0000
|
||||
@@ -0,0 +1,26 @@
|
||||
# ---- AirShelf core backend: Django + DRF + gunicorn / celery ----
|
||||
FROM docker.m.daocloud.io/python:3.12-slim
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# PyMySQL is pure-python (install_as_MySQLdb), boto3/gunicorn need no C deps,
|
||||
# so the slim image is enough — no build-essential required.
|
||||
COPY requirements.txt .
|
||||
RUN pip install --upgrade pip && pip install -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
# Collected admin/static lands here; served by WhiteNoise (see settings/production.py)
|
||||
RUN mkdir -p /app/staticfiles
|
||||
|
||||
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
EXPOSE 8000
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["gunicorn", "airshelf.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3", "--timeout", "120"]
|
||||
@@ -1,4 +1,7 @@
|
||||
from pathlib import Path
|
||||
|
||||
from .base import * # noqa: F403
|
||||
from .base import BASE_DIR, MIDDLEWARE
|
||||
|
||||
|
||||
DEBUG = False
|
||||
@@ -6,3 +9,16 @@ SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||
SESSION_COOKIE_SECURE = True
|
||||
CSRF_COOKIE_SECURE = True
|
||||
|
||||
# Serve admin/static behind gunicorn with DEBUG=False (no nginx static mount needed).
|
||||
# WhiteNoise sits right after SecurityMiddleware.
|
||||
MIDDLEWARE = (
|
||||
MIDDLEWARE[:1]
|
||||
+ ["whitenoise.middleware.WhiteNoiseMiddleware"]
|
||||
+ MIDDLEWARE[1:]
|
||||
)
|
||||
|
||||
STATIC_ROOT = Path(BASE_DIR) / "staticfiles"
|
||||
STORAGES = {
|
||||
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
|
||||
"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Only the web (gunicorn) container should run migrations / collectstatic.
|
||||
# The celery worker shares this image but skips DB schema mutation to avoid races.
|
||||
case "$1" in
|
||||
gunicorn)
|
||||
echo "[entrypoint] running migrations..."
|
||||
python manage.py migrate --noinput
|
||||
echo "[entrypoint] collecting static..."
|
||||
python manage.py collectstatic --noinput
|
||||
;;
|
||||
esac
|
||||
|
||||
exec "$@"
|
||||
@@ -8,4 +8,5 @@ python-dotenv>=1.0,<2.0
|
||||
boto3>=1.34,<2.0
|
||||
requests>=2.31,<3.0
|
||||
gunicorn>=21.2,<23.0
|
||||
whitenoise>=6.6,<7.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user