deploy(docker): support deploy with docker

This commit is contained in:
MingxuanGame
2025-08-10 08:28:01 +00:00
parent 8c18c8e519
commit 314fbf827b
9 changed files with 260 additions and 142 deletions

View File

@@ -1,5 +1,10 @@
# 数据库 URL
DATABASE_URL="mysql+aiomysql://root:password@127.0.0.1:3306/osu_api"
# 数据库设置
MYSQL_HOST="localhost"
MYSQL_PORT=3306
MYSQL_DATABASE="osu_api"
MYSQL_USER="osu_api"
MYSQL_PASSWORD="password"
MYSQL_ROOT_PASSWORD="password"
# Redis URL
REDIS_URL="redis://127.0.0.1:6379/0"

View File

@@ -1,28 +1,38 @@
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim
WORKDIR /app
ENV UV_PROJECT_ENVIRONMENT=syncvenv
# 安装系统依赖
RUN apt-get update && apt-get install -y \
gcc \
pkg-config \
default-libmysqlclient-dev \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY uv.lock .
COPY pyproject.toml .
COPY requirements.txt .
# 安装Python依赖
RUN pip install -r requirements.txt
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 8000
# 启动命令
CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
WORKDIR /app
RUN apt-get update && apt-get install -y \
gcc \
pkg-config \
default-libmysqlclient-dev \
curl \
netcat-openbsd \
&& rm -rf /var/lib/apt/lists/*
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV UV_PROJECT_ENVIRONMENT=/app/.venv
COPY pyproject.toml uv.lock ./
COPY packages/ ./packages/
RUN uv sync --frozen --no-dev
RUN uv pip install rosu-pp-py
COPY . .
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["uv", "run", "--no-sync", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

39
Dockerfile-osurx Normal file
View File

@@ -0,0 +1,39 @@
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
WORKDIR /app
RUN apt-get update && apt-get install -y \
gcc \
pkg-config \
default-libmysqlclient-dev \
curl \
netcat-openbsd \
git \
&& rm -rf /var/lib/apt/lists/*
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV UV_PROJECT_ENVIRONMENT=/app/.venv
COPY pyproject.toml uv.lock ./
COPY packages/ ./packages/
RUN uv sync --frozen --no-dev
RUN uv pip install git+https://github.com/ppy-sb/rosu-pp-py.git
COPY . .
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["uv", "run", "--no-sync", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -10,9 +10,18 @@ class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
# 数据库设置
database_url: str = "mysql+aiomysql://root:password@127.0.0.1:3306/osu_api"
mysql_host: str = "localhost"
mysql_port: int = 3306
mysql_database: str = "osu_api"
mysql_user: str = "osu_api"
mysql_password: str = "password"
mysql_root_password: str = "password"
redis_url: str = "redis://127.0.0.1:6379/0"
@property
def database_url(self) -> str:
return f"mysql+aiomysql://{self.mysql_user}:{self.mysql_password}@{self.mysql_host}:{self.mysql_port}/{self.mysql_database}"
# JWT 设置
secret_key: str = Field(default="your-secret-key-here", alias="jwt_secret_key")
algorithm: str = "HS256"

77
docker-compose-osurx.yml Normal file
View File

@@ -0,0 +1,77 @@
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile-osurx
container_name: osu_api_server_osurx
ports:
- "8000:8000"
environment:
- MYSQL_HOST=mysql
- MYSQL_PORT=3306
- REDIS_URL=redis://redis:6379/0
- ENABLE_OSU_RX=true
- ENABLE_OSU_AP=true
- ENABLE_ALL_MODS_PP=true
- ENABLE_SUPPORTER_FOR_ALL_USERS=true
- ENABLE_ALL_BEATMAP_LEADERBOARD=true
env_file:
- .env
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./replays:/app/replays
- ./static:/app/static
restart: unless-stopped
networks:
- osu-network
mysql:
image: mysql:8.0
container_name: osu_api_mysql_osurx
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
interval: 10s
start_period: 40s
restart: unless-stopped
networks:
- osu-network
redis:
image: redis:7-alpine
container_name: osu_api_redis_osurx
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
timeout: 5s
retries: 5
interval: 10s
start_period: 10s
restart: unless-stopped
networks:
- osu-network
command: redis-server --appendonly yes
volumes:
mysql_data:
redis_data:
networks:
osu-network:
driver: bridge

View File

@@ -1,50 +1,72 @@
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: osu_api_mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: osu_api
MYSQL_USER: osu_user
MYSQL_PASSWORD: osu_password
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: osu_api_redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
command: redis-server --appendonly yes
api:
build: .
container_name: osu_api_server
ports:
- "8000:8000"
environment:
DATABASE_URL: mysql+aiomysql://osu_user:osu_password@mysql:3306/osu_api
REDIS_URL: redis://redis:6379/0
SECRET_KEY: your-production-secret-key-here
OSU_CLIENT_ID: "5"
OSU_CLIENT_SECRET: "FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"
depends_on:
- mysql
- redis
restart: unless-stopped
volumes:
- ./:/app
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
volumes:
mysql_data:
redis_data:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: osu_api_server
ports:
- "8000:8000"
environment:
- MYSQL_HOST=mysql
- MYSQL_PORT=3306
- REDIS_URL=redis://redis:6379/0
env_file:
- .env
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./replays:/app/replays
- ./static:/app/static
restart: unless-stopped
networks:
- osu-network
mysql:
image: mysql:8.0
container_name: osu_api_mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
interval: 10s
start_period: 40s
restart: unless-stopped
networks:
- osu-network
redis:
image: redis:7-alpine
container_name: osu_api_redis
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
timeout: 5s
retries: 5
interval: 10s
start_period: 10s
restart: unless-stopped
networks:
- osu-network
command: redis-server --appendonly yes
volumes:
mysql_data:
redis_data:
networks:
osu-network:
driver: bridge

13
docker-entrypoint.sh Normal file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -e
echo "Waiting for database connection..."
while ! nc -z $MYSQL_HOST $MYSQL_PORT; do
sleep 1
done
echo "Database connected"
echo "Running alembic..."
uv run --no-sync alembic upgrade head
exec "$@"

View File

@@ -2,8 +2,8 @@ from __future__ import annotations
import asyncio
from logging.config import fileConfig
import os
from app.config import settings
from app.database import * # noqa: F403
from alembic import context
@@ -45,7 +45,8 @@ def run_migrations_offline() -> None:
script output.
"""
url = os.environ.get("DATABASE_URL", config.get_main_option("sqlalchemy.url"))
url = settings.database_url
print(url)
context.configure(
url=url,
target_metadata=target_metadata,
@@ -73,8 +74,7 @@ async def run_async_migrations() -> None:
"""
sa_config = config.get_section(config.config_ini_section, {})
if db_url := os.environ.get("DATABASE_URL"):
sa_config["sqlalchemy.url"] = db_url
sa_config["sqlalchemy.url"] = settings.database_url
connectable = async_engine_from_config(
sa_config,
prefix="sqlalchemy.",

View File

@@ -1,57 +0,0 @@
aiomysql==0.2.0
alembic==1.16.4
annotated-types==0.7.0
anyio==4.9.0
bcrypt==4.3.0
certifi==2025.7.14
cffi==1.17.1
cfgv==3.4.0
click==8.2.1
cryptography==45.0.5
distlib==0.4.0
dnspython==2.7.0
ecdsa==0.19.1
email-validator==2.2.0
fastapi==0.116.1
filelock==3.18.0
greenlet==3.2.3
h11==0.16.0
httpcore==1.0.9
httptools==0.6.4
httpx==0.28.1
identify==2.6.12
idna==3.10
loguru==0.7.3
mako==1.3.10
markupsafe==3.0.2
maturin==1.9.2
-e file:///workspaces/osu_lazer_api/packages/msgpack_lazer_api
nodeenv==1.9.1
passlib==1.7.4
platformdirs==4.3.8
pre-commit==4.2.0
pyasn1==0.6.1
pycparser==2.22
pydantic==2.11.7
pydantic-core==2.33.2
pymysql==1.1.1
python-dotenv==1.1.1
python-jose==3.5.0
python-multipart==0.0.20
pyyaml==6.0.2
redis==6.2.0
rosu-pp-py==3.1.0
rsa==4.9.1
ruff==0.12.4
six==1.17.0
sniffio==1.3.1
sqlalchemy==2.0.41
sqlmodel==0.0.24
starlette==0.47.2
typing-extensions==4.14.1
typing-inspection==0.4.1
uvicorn==0.35.0
uvloop==0.21.0
virtualenv==20.32.0
watchfiles==1.1.0
websockets==15.0.1