diff --git a/.dockerignore b/.dockerignore index ea7e79c..7d6764a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,12 @@ __pycache__/ .venv/ .vscode/ .mypy_cache/ +.pytest_cache/ +.ruff_cache/ +.coverage +coverage.xml +TODO.md tests/ db_test_data.py -LICENSE \ No newline at end of file +LICENSE +.env \ No newline at end of file diff --git a/Dockerfile.api b/Dockerfile.api index 97154a8..f6dd8d7 100644 --- a/Dockerfile.api +++ b/Dockerfile.api @@ -5,6 +5,9 @@ FROM python:3.13-slim # создаем папку /app. Весь код будет тут WORKDIR /app +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + # Копируем только requrements.txt(кэшируется) COPY requirements.txt . @@ -18,6 +21,10 @@ COPY . . RUN rm -rf /app/src/bot RUN chmod +x entrypoint.sh +RUN useradd -m -r app \ + chown -R app:app /app +USER app + # Открываем порт EXPOSE 8000 diff --git a/Dockerfile.bot b/Dockerfile.bot index e46e5f8..4b70a78 100644 --- a/Dockerfile.bot +++ b/Dockerfile.bot @@ -3,9 +3,13 @@ FROM python:3.13-slim WORKDIR /app +#Отключаем создание файлов .pyc и __pycache__ +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + # Установка системных зависимостей RUN apt-get update && apt-get install -y \ - gcc \ + gcc \ && rm -rf /var/lib/apt/lists/* COPY requirements.txt . @@ -14,10 +18,20 @@ COPY requirements.txt . RUN pip install --no-cache-dir --upgrade pip && \ pip install --no-cache-dir -r requirements.txt +# Создаем пользователя +# -m создает домашнюю директорию пользователя. +# -r - создает системного пользователя(служебная учетка с ограниченными правами) +# через chown рекурсивно(-R) меняем права доступа на файлах каталога для пользователя app, группы app (app:app) + COPY src/presentation/bot ./src/presentation/bot COPY src/logger.py ./src/ COPY src/domain/services ./src/domain/services COPY src/shared/ ./src/shared/ COPY src/config.py ./src/ +RUN useradd -m -r app && \ + chown -R app:app /app + +USER app + CMD ["python", "-m", "src.presentation.bot.handlers.bot"] diff --git a/docker-compose.yml b/docker-compose.yml index 7b68220..6270bf2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,6 +16,10 @@ services: - postgres_data:/var/lib/postgresql/data # стандартное мето хранения файлов postgres (имя_volume:путь внутри контейнера) mem_limit: 512m mem_reservation: 256m + networks: + - api_db_net + security_opt: + - no-new-privileges:true # Запрет на повышение прав до root api: image: ghcr.io/fl1rix/steeltime-api:latest @@ -35,8 +39,17 @@ services: restart: unless-stopped mem_limit: 1g # Лимиты ресурсов cpus: 0.5 + networks: + - api_bot_net + - api_db_net + read_only: true + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + tmpfs: + - /tmp - bot: image: ghcr.io/fl1rix/steeltime-bot:latest restart: unless-stopped @@ -49,18 +62,34 @@ services: condition: service_healthy mem_limit: 256m cpus: 0.25 + networks: + - api_bot_net + read_only: true + security_opt: + - no-new-privileges:true + cap_drop: # Забирает все доступные привилегии у root пользователя. + - ALL + tmpfs: # Папка, доступная для записи инфорамции, в случае надобности. + - /tmp watchtower: image: containrrr/watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock command: --interval 300 + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp volumes: postgres_data: driver: local networks: - default: + api_db_net: driver: bridge - name: steeltime_network \ No newline at end of file + internal: true + + api_bot_net: + driver: bridge \ No newline at end of file diff --git a/src/logger.py b/src/logger.py index 2036122..493e140 100644 --- a/src/logger.py +++ b/src/logger.py @@ -9,8 +9,4 @@ console_handler = logging.StreamHandler() # вывод логов в консоль console_handler.setFormatter(formatter) -handler = logging.FileHandler(filename="SteelTime.log", encoding="utf-8") # файл для записи логов -handler.setFormatter(formatter) - -logger.addHandler(handler) logger.addHandler(console_handler) \ No newline at end of file diff --git a/src/presentation/api/v1/auth/tg_link.py b/src/presentation/api/v1/auth/tg_link.py index 90381cc..f706913 100644 --- a/src/presentation/api/v1/auth/tg_link.py +++ b/src/presentation/api/v1/auth/tg_link.py @@ -51,8 +51,6 @@ async def create_telegram_magic_link( token = secrets.token_urlsafe(32) expires = datetime.now(timezone.utc) + timedelta(minutes=10) - #! TODO: Добавить изоляцию на уровне docker - logger.info("Сохранение magic токена...") await TgLinkService.save_link_token(token=token, expires_at=expires, db=db, telegram_id=telegram_id) logger.info("Токен успешно сохранен!")