From b4ee793b6f71fab95102063380e83f37b1465e85 Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Sat, 18 Oct 2025 15:34:41 -0400 Subject: [PATCH] add docker --- .dockerignore | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 2 +- Dockerfile | 22 +++++++ api_server.py | 7 +- compose.yaml | 9 +++ create_db.py | 9 +-- start.sh | 3 +- 7 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..440bfce --- /dev/null +++ b/.dockerignore @@ -0,0 +1,178 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + + +data/ diff --git a/.gitignore b/.gitignore index 6f543f5..440bfce 100644 --- a/.gitignore +++ b/.gitignore @@ -175,4 +175,4 @@ cython_debug/ .pypirc -safe_marks.db +data/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a8e3df2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# 使用官方 Python 镜像作为基础 +FROM python:3.12-slim + +# 设置工作目录 +WORKDIR /app + +# 将你的项目文件复制到工作目录 +COPY . . + +# 安装依赖 +# --no-cache-dir: 不存储缓存,保持镜像小巧 +# --upgrade pip: 升级 pip +# -r requirements.txt: 从文件安装 +RUN pip install --no-cache-dir --upgrade pip -r requirements.txt + +RUN chmod +x /app/start.sh + +# 暴露 Gunicorn 运行的端口 +EXPOSE 8000 + +# 容器启动时运行的命令 +CMD ["/app/start.sh"] diff --git a/api_server.py b/api_server.py index e1e133e..52e6aef 100644 --- a/api_server.py +++ b/api_server.py @@ -1,3 +1,4 @@ +import os import datetime from fastapi import FastAPI, Depends, HTTPException from pydantic import BaseModel, Field @@ -6,7 +7,11 @@ from sqlalchemy.orm import sessionmaker, Session, declarative_base from enum import IntEnum # --- 数据库设置 --- -SQLALCHEMY_DATABASE_URL = "sqlite:///./safe_marks.db" +# 将数据库放在一个专门的 /data 子目录中 +DB_DIR = "/app/data" +os.makedirs(DB_DIR, exist_ok=True) +SQLALCHEMY_DATABASE_URL = f"sqlite:///{DB_DIR}/safe-marks.db" + engine = create_engine( SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} ) diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..2b1d14e --- /dev/null +++ b/compose.yaml @@ -0,0 +1,9 @@ +services: + api: + build: . + container_name: safe-marks-server-api + ports: + - "127.0.0.1:17701:8000" + volumes: + - ./data:/app/data + restart: unless-stopped diff --git a/create_db.py b/create_db.py index 2508ceb..e3283f4 100644 --- a/create_db.py +++ b/create_db.py @@ -1,11 +1,8 @@ from api_server import Base, engine -print("连接数据库 ...") -# 从 api_server.py 导入 Base (包含了所有模型) 和 engine (数据库连接) +print("Creating database and tables...") -print("创建表(如果表不存在)...") -# create_all 默认会检查表是否存在 (checkfirst=True),所以重复运行是安全的 -# 但我们只在需要时手动运行它 +# create_all 会检查表是否存在,只创建不存在的表 Base.metadata.create_all(bind=engine, checkfirst=True) -print("数据表创建成功(或已经存在)。") +print("Database and tables created successfully (if they didn't exist).") \ No newline at end of file diff --git a/start.sh b/start.sh index bea2e17..9d1b523 100644 --- a/start.sh +++ b/start.sh @@ -1,4 +1,5 @@ #!/bin/bash python create_db.py -gunicorn -w 4 -k uvicorn.workers.UvicornWorker api_server:app -b 127.0.0.1:17701 +# 这里必须是 0.0.0.0:8000 +gunicorn -w 4 -k uvicorn.workers.UvicornWorker api_server:app -b 0.0.0.0:8000