deploy(docker): support deploy with docker
This commit is contained in:
@@ -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"
|
||||
|
||||
|
||||
66
Dockerfile
66
Dockerfile
@@ -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
39
Dockerfile-osurx
Normal 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"]
|
||||
@@ -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
77
docker-compose-osurx.yml
Normal 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
|
||||
@@ -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
13
docker-entrypoint.sh
Normal 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 "$@"
|
||||
@@ -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.",
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user