重构Dockerfile

This commit is contained in:
guyue 2025-01-02 14:36:51 +08:00
parent 0a6f5df0d5
commit 341d29300a
11 changed files with 104 additions and 21 deletions

View File

@ -1,4 +1,4 @@
如果觉得SoulBook对您有帮助,那么您可以给开发者一些支持: 如果觉得对您有帮助,那么您可以给开发者一些支持:
- 开源 - 开源
- 服务器的费用也是一笔开销 - 服务器的费用也是一笔开销

View File

@ -1,7 +1,8 @@
[[source]] [[source]]
verify_ssl = true verify_ssl = true
name = "pypi" name = "pypi"
url = "https://pypi.douban.com/simple/" #url = "https://pypi.douban.com/simple/"
url = "https://mirrors.aliyun.com/pypi/simple/"
[requires] [requires]
python_version = "3.6" python_version = "3.6"

1
build.sh Normal file
View File

@ -0,0 +1 @@
sudo docker build -t guyue55/soulbook . -f docker/Dockerfile-slim

View File

@ -1,9 +0,0 @@
version: '3'
services:
web:
image: howie6879/owllook
command: pipenv run gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app
ports:
- "8001:8001"
volumes:
- .:/soulbook

25
docker/Dockerfile-alpine Normal file
View File

@ -0,0 +1,25 @@
# 基于python3.6镜像来构建镜像
FROM python:3.6-alpine
MAINTAINER guyue55 <guyuecw@qq.com>
ENV TIME_ZONE=Asia/Shanghai
# 换源
RUN echo "https://mirrors.aliyun.com/alpine/v3.15/main" > /etc/apk/repositories \
&& echo "https://mirrors.aliyun.com/alpine/v3.15/community" >> /etc/apk/repositories \
&& echo "${TIME_ZONE}" > /etc/timezone \
&& ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime
# 安装基础库
RUN apk --no-cache add gcc g++ libc-dev libffi-dev musl-dev cmake build-base
WORKDIR /app
COPY . .
#RUN pip install --no-cache-dir --trusted-host mirrors.aliyun.com -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt
RUN pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt
RUN find . -name "*.pyc" -delete
EXPOSE 8001
CMD gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app --log-level=debug

16
docker/Dockerfile-slim Normal file
View File

@ -0,0 +1,16 @@
# 基于python3.6镜像来构建镜像
FROM python:3.6-slim
MAINTAINER guyue55 <guyuecw@qq.com>
ENV TIME_ZONE=Asia/Shanghai
RUN echo "${TIME_ZONE}" > /etc/timezone \
&& ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime
ADD . /app
WORKDIR /app
RUN pip install --no-cache-dir --trusted-host mirrors.aliyun.com -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt
RUN find . -name "*.pyc" -delete
EXPOSE 8001
CMD gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app --log-level=debug

View File

@ -0,0 +1,9 @@
version: '3'
services:
web:
image: guyue55/owllook
command: gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app
ports:
- "8001:8001"
volumes:
- .:/app

2
run_docker.sh Normal file
View File

@ -0,0 +1,2 @@
# sudo docker run -it -d -p 8001:8001 -e MONGO_HOST=127.0.0.1 -e MONGO_PORT=27017 -e REDIS_ENDPOINT=127.0.0.1 -e REDIS_PORT=6379 -e REDIS_PASSWORD=password guyue55/soulbook
sudo docker run -it -d -p 8001:8001 --env-file .env guyue55/soulbook

View File

@ -17,24 +17,24 @@ class DevConfig(Config):
REDIS_ENDPOINT=os.getenv('REDIS_ENDPOINT', "localhost"), REDIS_ENDPOINT=os.getenv('REDIS_ENDPOINT', "localhost"),
REDIS_PORT=int(os.getenv('REDIS_PORT', 6379)), REDIS_PORT=int(os.getenv('REDIS_PORT', 6379)),
REDIS_PASSWORD=os.getenv('REDIS_PASSWORD', None), REDIS_PASSWORD=os.getenv('REDIS_PASSWORD', None),
CACHE_DB=0, CACHE_DB=int(os.getenv('CACHE_DB', 0)),
SESSION_DB=1, SESSION_DB=int(os.getenv('SESSION_DB', 1)),
POOLSIZE=10, POOLSIZE=10,
) )
MONGODB = dict( MONGODB = dict(
MONGO_HOST=os.getenv('MONGO_HOST', "127.0.0.1"), MONGO_HOST=os.getenv('MONGO_HOST', "127.0.0.1"),
MONGO_PORT=int(os.getenv('MONGO_PORT', 27017)), MONGO_PORT=int(os.getenv('MONGO_PORT', 27017)),
MONGO_USERNAME="", MONGO_USERNAME=os.getenv('MONGO_USERNAME', ""),
MONGO_PASSWORD="", MONGO_PASSWORD=os.getenv('MONGO_PASSWORD', ""),
DATABASE='soulbook', DATABASE=os.getenv('MONGO_DB', "soulbook"),
) )
# website # website
WEBSITE = dict( WEBSITE = dict(
IS_RUNNING=os.getenv('OWLLOOK_IS_RUNNING', True), IS_RUNNING=os.getenv('IS_RUNNING', "true").lower() == "true",
TOKEN=os.getenv('OWLLOOK_TOKEN', '') TOKEN=os.getenv('TOKEN', '')
) )
AUTH = { AUTH = {
"Owllook-Api-Key": os.getenv('OWLLOOK_API_KEY', "your key") "Owllook-Api-Key": os.getenv('API_KEY', "your key")
} }

View File

@ -23,18 +23,30 @@ from soulbook.config import CONFIG, LOGGER
def authenticator(key): def authenticator(key):
""" """
验证请求头中的特定键值对是否与配置中的值匹配
:param keys: 验证方式 Owllook-Api-Key : Magic Key, Authorization : Token :param key: 需要验证的请求头键名例如 "Owllook-Api-Key" "Authorization"
:return: 返回值 :return: 装饰器函数用于验证请求头中的键值对
""" """
def wrapper(func): def wrapper(func):
@wraps(func) @wraps(func)
async def authenticate(request, *args, **kwargs): async def authenticate(request, *args, **kwargs):
"""
验证请求头中的键值对是否与配置中的值匹配
:param request: Sanic 请求对象
:param args: 位置参数
:param kwargs: 关键字参数
:return: 如果验证成功返回被装饰函数的结果否则返回未授权的响应
"""
# 从请求头中获取指定键的值
value = request.headers.get(key, None) value = request.headers.get(key, None)
# 如果值存在且与配置中的值匹配,则调用被装饰的函数
if value and CONFIG.AUTH[key] == value: if value and CONFIG.AUTH[key] == value:
response = await func(request, *args, **kwargs) response = await func(request, *args, **kwargs)
return response return response
# 如果值不存在或与配置中的值不匹配,则返回未授权的响应
else: else:
return response_handle(request, UniResponse.NOT_AUTHORIZED, status=401) return response_handle(request, UniResponse.NOT_AUTHORIZED, status=401)
@ -108,35 +120,61 @@ def cached(
:param plugins: plugins to use when calling the cmd hooks :param plugins: plugins to use when calling the cmd hooks
Default is the one configured in ``aiocache.settings.DEFAULT_PLUGINS`` Default is the one configured in ``aiocache.settings.DEFAULT_PLUGINS``
""" """
# 将传入的关键字参数存储在 cache_kwargs 中,以便后续使用
cache_kwargs = kwargs cache_kwargs = kwargs
def cached_decorator(func): def cached_decorator(func):
"""
装饰器函数用于缓存函数的返回值
:param func: 被装饰的函数
:return: 包装后的函数
"""
async def wrapper(*args, **kwargs): async def wrapper(*args, **kwargs):
"""
包装后的函数用于执行缓存逻辑
:param args: 位置参数
:param kwargs: 关键字参数
:return: 函数的返回值
"""
# 获取缓存实例,使用传入的参数或默认配置
cache_instance = get_cache( cache_instance = get_cache(
cache=cache, serializer=serializer, plugins=plugins, **cache_kwargs) cache=cache, serializer=serializer, plugins=plugins, **cache_kwargs)
# 获取函数的参数字典
args_dict = get_args_dict(func, args, kwargs) args_dict = get_args_dict(func, args, kwargs)
# 生成缓存键,如果没有指定 key则使用函数名、参数和关键字参数生成
cache_key = key or args_dict.get( cache_key = key or args_dict.get(
key_from_attr, key_from_attr,
(func.__module__ or 'stub') + func.__name__ + str(args) + str(kwargs)) (func.__module__ or 'stub') + func.__name__ + str(args) + str(kwargs))
try: try:
# 检查缓存中是否存在该键
if await cache_instance.exists(cache_key): if await cache_instance.exists(cache_key):
# 如果存在,从缓存中获取值并返回
return await cache_instance.get(cache_key) return await cache_instance.get(cache_key)
except Exception: except Exception:
# 如果发生异常,记录日志
logger.exception("Unexpected error with %s", cache_instance) logger.exception("Unexpected error with %s", cache_instance)
# 如果缓存中不存在该键,调用原始函数获取结果
result = await func(*args, **kwargs) result = await func(*args, **kwargs)
if result: if result:
try: try:
# 将结果存入缓存
await cache_instance.set(cache_key, result, ttl=ttl) await cache_instance.set(cache_key, result, ttl=ttl)
except Exception: except Exception:
# 如果发生异常,记录日志
logger.exception("Unexpected error with %s", cache_instance) logger.exception("Unexpected error with %s", cache_instance)
# 返回函数的结果
return result return result
# 返回包装后的函数
return wrapper return wrapper
# 返回装饰器函数
return cached_decorator return cached_decorator