From de1e56fe937b8fe1a404e8fdcd357d5917938ca0 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 13:35:19 +0300 Subject: [PATCH 01/15] edit imports --- backend/backlog_app/api/crud.py | 7 ++++--- backend/backlog_app/api/view/auth_view.py | 9 ++++++--- backend/backlog_app/api/view/movie_view.py | 13 ++++++++----- backend/backlog_app/api/view/users_view.py | 7 +++++-- backend/backlog_app/app_lifespan.py | 2 +- .../dependencies/authentification/access_tokens.py | 5 +++-- .../dependencies/authentification/backend.py | 3 ++- .../authentification/fastapi_users_routers.py | 3 ++- .../dependencies/authentification/strategy.py | 3 ++- .../dependencies/authentification/user_manager.py | 3 ++- .../dependencies/authentification/users.py | 5 +++-- backend/backlog_app/jinja2_templates.py | 3 ++- backend/backlog_app/main.py | 8 ++++---- backend/backlog_app/models/movie.py | 3 ++- backend/backlog_app/models/users.py | 3 ++- .../servicies/authentification/user_manager.py | 7 ++++--- backend/backlog_app/storages/database.py | 3 ++- backend/backlog_app/tasks/email_task.py | 6 +++--- 18 files changed, 57 insertions(+), 36 deletions(-) diff --git a/backend/backlog_app/api/crud.py b/backend/backlog_app/api/crud.py index f120bc7..d708c6c 100644 --- a/backend/backlog_app/api/crud.py +++ b/backend/backlog_app/api/crud.py @@ -1,13 +1,14 @@ import logging from fastapi import HTTPException -from models import User -from models.movie import Movie -from schemas.movie import MovieCreate, MovieRead, MovieUpdate from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from sqlalchemy.orm import selectinload +from backlog_app.models import User +from backlog_app.models.movie import Movie +from backlog_app.schemas.movie import MovieCreate, MovieRead, MovieUpdate + logger = logging.getLogger(__name__) diff --git a/backend/backlog_app/api/view/auth_view.py b/backend/backlog_app/api/view/auth_view.py index 6a7b441..3ff52a9 100644 --- a/backend/backlog_app/api/view/auth_view.py +++ b/backend/backlog_app/api/view/auth_view.py @@ -1,7 +1,10 @@ -from dependencies.authentification.backend import authentication_backend -from dependencies.authentification.fastapi_users_routers import fastapi_users from fastapi import APIRouter -from schemas.user import UserCreate, UserRead + +from backlog_app.dependencies.authentification.backend import authentication_backend +from backlog_app.dependencies.authentification.fastapi_users_routers import ( + fastapi_users, +) +from backlog_app.schemas.user import UserCreate, UserRead router = APIRouter( prefix="/auth", diff --git a/backend/backlog_app/api/view/movie_view.py b/backend/backlog_app/api/view/movie_view.py index cfb834a..8d6debb 100644 --- a/backend/backlog_app/api/view/movie_view.py +++ b/backend/backlog_app/api/view/movie_view.py @@ -1,12 +1,15 @@ from typing import Annotated, List -from api import crud -from dependencies.authentification.fastapi_users_routers import current_active_user from fastapi import APIRouter, Depends -from models.users import User -from schemas.movie import MovieCreate, MovieRead, MovieUpdate from sqlalchemy.ext.asyncio import AsyncSession -from storages.database import get_async_session + +from backlog_app.api import crud +from backlog_app.dependencies.authentification.fastapi_users_routers import ( + current_active_user, +) +from backlog_app.models.users import User +from backlog_app.schemas.movie import MovieCreate, MovieRead, MovieUpdate +from backlog_app.storages.database import get_async_session router = APIRouter(prefix="/movies", tags=["Movies"]) diff --git a/backend/backlog_app/api/view/users_view.py b/backend/backlog_app/api/view/users_view.py index a50d52e..bdd0fa3 100644 --- a/backend/backlog_app/api/view/users_view.py +++ b/backend/backlog_app/api/view/users_view.py @@ -1,6 +1,9 @@ -from dependencies.authentification.fastapi_users_routers import fastapi_users from fastapi import APIRouter -from schemas.user import UserRead, UserUpdate + +from backlog_app.dependencies.authentification.fastapi_users_routers import ( + fastapi_users, +) +from backlog_app.schemas.user import UserRead, UserUpdate router = APIRouter(prefix="/users", tags=["Users"]) diff --git a/backend/backlog_app/app_lifespan.py b/backend/backlog_app/app_lifespan.py index b5d4893..1f812bb 100644 --- a/backend/backlog_app/app_lifespan.py +++ b/backend/backlog_app/app_lifespan.py @@ -2,8 +2,8 @@ from contextlib import asynccontextmanager from fastapi import FastAPI -from storages.database import engine +from .storages.database import engine from .taskiq_broker import broker diff --git a/backend/backlog_app/dependencies/authentification/access_tokens.py b/backend/backlog_app/dependencies/authentification/access_tokens.py index 01cdc67..576f1bd 100644 --- a/backend/backlog_app/dependencies/authentification/access_tokens.py +++ b/backend/backlog_app/dependencies/authentification/access_tokens.py @@ -1,8 +1,9 @@ from typing import TYPE_CHECKING, Annotated from fastapi import Depends -from models import AccessToken -from storages.database import get_async_session + +from backlog_app.models import AccessToken +from backlog_app.storages.database import get_async_session if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession diff --git a/backend/backlog_app/dependencies/authentification/backend.py b/backend/backlog_app/dependencies/authentification/backend.py index 7f932ce..2f81b26 100644 --- a/backend/backlog_app/dependencies/authentification/backend.py +++ b/backend/backlog_app/dependencies/authentification/backend.py @@ -1,5 +1,6 @@ from fastapi_users.authentication import AuthenticationBackend -from servicies.authentification import bearer_transport + +from backlog_app.servicies.authentification import bearer_transport from .strategy import get_database_strategy diff --git a/backend/backlog_app/dependencies/authentification/fastapi_users_routers.py b/backend/backlog_app/dependencies/authentification/fastapi_users_routers.py index 73501f8..4fef678 100644 --- a/backend/backlog_app/dependencies/authentification/fastapi_users_routers.py +++ b/backend/backlog_app/dependencies/authentification/fastapi_users_routers.py @@ -1,7 +1,8 @@ import uuid from fastapi_users import FastAPIUsers -from models import User + +from backlog_app.models import User from .backend import authentication_backend from .user_manager import get_user_manager diff --git a/backend/backlog_app/dependencies/authentification/strategy.py b/backend/backlog_app/dependencies/authentification/strategy.py index 92d7481..c5c5c0f 100644 --- a/backend/backlog_app/dependencies/authentification/strategy.py +++ b/backend/backlog_app/dependencies/authentification/strategy.py @@ -1,9 +1,10 @@ from typing import TYPE_CHECKING, Annotated -from config import settings from fastapi import Depends from fastapi_users.authentication.strategy.db import DatabaseStrategy +from backlog_app.config import settings + from .access_tokens import get_access_token_db if TYPE_CHECKING: diff --git a/backend/backlog_app/dependencies/authentification/user_manager.py b/backend/backlog_app/dependencies/authentification/user_manager.py index 0c11d19..c7330f6 100644 --- a/backend/backlog_app/dependencies/authentification/user_manager.py +++ b/backend/backlog_app/dependencies/authentification/user_manager.py @@ -1,7 +1,8 @@ from typing import TYPE_CHECKING, Annotated from fastapi import Depends -from servicies.authentification import UserManager + +from backlog_app.servicies.authentification import UserManager from .users import get_user_db diff --git a/backend/backlog_app/dependencies/authentification/users.py b/backend/backlog_app/dependencies/authentification/users.py index 43790bb..7439e98 100644 --- a/backend/backlog_app/dependencies/authentification/users.py +++ b/backend/backlog_app/dependencies/authentification/users.py @@ -1,8 +1,9 @@ from typing import TYPE_CHECKING, Annotated from fastapi import Depends -from models import User -from storages.database import get_async_session + +from backlog_app.models import User +from backlog_app.storages.database import get_async_session if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession diff --git a/backend/backlog_app/jinja2_templates.py b/backend/backlog_app/jinja2_templates.py index f5c2d6d..3f72495 100644 --- a/backend/backlog_app/jinja2_templates.py +++ b/backend/backlog_app/jinja2_templates.py @@ -1,6 +1,7 @@ __all__ = ("templates",) -from config import BASE_DIR from fastapi.templating import Jinja2Templates +from backlog_app.config import BASE_DIR + templates = Jinja2Templates(directory=BASE_DIR / "templates") diff --git a/backend/backlog_app/main.py b/backend/backlog_app/main.py index a50a9e9..554643a 100644 --- a/backend/backlog_app/main.py +++ b/backend/backlog_app/main.py @@ -2,13 +2,13 @@ from datetime import datetime import uvicorn -from api import router as api_router -from api.view.main_view import router as main_router -from config import settings from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from backend.backlog_app.app_lifespan import lifespan +from .api import router as api_router +from .api.view.main_view import router as main_router +from .app_lifespan import lifespan +from .config import settings logging.basicConfig( format=settings.logging.log_format, diff --git a/backend/backlog_app/models/movie.py b/backend/backlog_app/models/movie.py index fbc4a62..a872340 100644 --- a/backend/backlog_app/models/movie.py +++ b/backend/backlog_app/models/movie.py @@ -2,11 +2,12 @@ from datetime import datetime from typing import TYPE_CHECKING -from models.base import Base from sqlalchemy import Boolean, DateTime, Float, ForeignKey, Integer, String, func from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column, relationship +from .base import Base + if TYPE_CHECKING: from .users import User diff --git a/backend/backlog_app/models/users.py b/backend/backlog_app/models/users.py index 2dee427..37a2fb4 100644 --- a/backend/backlog_app/models/users.py +++ b/backend/backlog_app/models/users.py @@ -4,9 +4,10 @@ SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase, ) -from models.base import Base from sqlalchemy.orm import Mapped, relationship +from .base import Base + if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession diff --git a/backend/backlog_app/servicies/authentification/user_manager.py b/backend/backlog_app/servicies/authentification/user_manager.py index 956b3de..289e584 100644 --- a/backend/backlog_app/servicies/authentification/user_manager.py +++ b/backend/backlog_app/servicies/authentification/user_manager.py @@ -2,10 +2,11 @@ import uuid from typing import TYPE_CHECKING, Optional -from config import settings from fastapi_users import BaseUserManager, UUIDIDMixin -from models import User -from tasks.email_task import send_email_confirmed, send_verification_email + +from backlog_app.config import settings +from backlog_app.models import User +from backlog_app.tasks.email_task import send_email_confirmed, send_verification_email if TYPE_CHECKING: from fastapi import Request diff --git a/backend/backlog_app/storages/database.py b/backend/backlog_app/storages/database.py index 1a1d4ac..865d404 100644 --- a/backend/backlog_app/storages/database.py +++ b/backend/backlog_app/storages/database.py @@ -1,6 +1,7 @@ -from config import settings from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine +from backlog_app.config import settings + engine = create_async_engine( settings.db.connection.database_url_asyncpg, echo=False, diff --git a/backend/backlog_app/tasks/email_task.py b/backend/backlog_app/tasks/email_task.py index 9379088..e38b8b9 100644 --- a/backend/backlog_app/tasks/email_task.py +++ b/backend/backlog_app/tasks/email_task.py @@ -1,8 +1,8 @@ from textwrap import dedent -from jinja2_templates import templates -from servicies.mailing import send_email -from taskiq_broker import broker +from backlog_app.jinja2_templates import templates +from backlog_app.servicies.mailing import send_email +from backlog_app.taskiq_broker import broker @broker.task From d0bfd9b5b4416312b4751006b93ec4445d307e59 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 16:38:28 +0300 Subject: [PATCH 02/15] edit imports --- backend/backlog_app/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/backlog_app/main.py b/backend/backlog_app/main.py index 554643a..e9cdc94 100644 --- a/backend/backlog_app/main.py +++ b/backend/backlog_app/main.py @@ -5,10 +5,10 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from .api import router as api_router -from .api.view.main_view import router as main_router -from .app_lifespan import lifespan -from .config import settings +from backlog_app.api import router as api_router +from backlog_app.api.view.main_view import router as main_router +from backlog_app.app_lifespan import lifespan +from backlog_app.config import settings logging.basicConfig( format=settings.logging.log_format, From d51dcc44b5947c14b26ab00e3b2e821669e62ad7 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 16:38:48 +0300 Subject: [PATCH 03/15] add to env api url --- frontend/src/services/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/services/auth.js b/frontend/src/services/auth.js index 46d02f1..9baddba 100644 --- a/frontend/src/services/auth.js +++ b/frontend/src/services/auth.js @@ -1,6 +1,6 @@ import axios from 'axios' -const API_URL = 'http://127.0.0.1:8000/api' +const API_URL = import.meta.env.VITE_API_URL; class AuthService { constructor() { From 027d4b37bc1167470dd5dde9c3b98ada8b9533fb Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 16:39:04 +0300 Subject: [PATCH 04/15] add docker files --- backend/.dockerignore | 89 +++++++++++++++++++++++++++++++++++++++++++ backend/Dockerfile | 15 ++++++++ docker-compose.yaml | 52 +++++++++++++++++++++++++ frontend/Dockerfile | 36 +++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 backend/.dockerignore create mode 100644 backend/Dockerfile create mode 100644 docker-compose.yaml create mode 100644 frontend/Dockerfile diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..0a53e44 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,89 @@ +# Git +.git +.gitignore +.gitattributes + + +# CI +.codeclimate.yml +.travis.yml +.taskcluster.yml + +# Docker +docker-compose.yml +Dockerfile +.docker +.dockerignore + +# Byte-compiled / optimized / DLL files +**/__pycache__/ +**/*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# 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/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Virtual environment +.env +.venv/ +venv/ + +# PyCharm +.idea + +# Python mode for VIM +.ropeproject +**/.ropeproject + +# Vim swap files +**/*.swp + +# VS Code +.vscode/ diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..775eed7 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.13-slim + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + +WORKDIR /app + +COPY ./pyproject.toml ./ +COPY ./uv.lock ./ +COPY ./backlog_app ./backlog_app + +RUN uv sync + +EXPOSE 8000 + +CMD ["uv", "run", "fastapi", "run", "backlog_app/main.py", "--port", "8000"] diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..a0b4fd7 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,52 @@ +services: + + backend: + container_name: fastapi_app + build: + context: ./backend + dockerfile: Dockerfile + env_file: + - ./backend/backlog_app/.env + ports: + - "8000:8000" + depends_on: + pg: + condition: service_healthy + volumes: + - ./backend/backlog_app:/app/backlog_app + + frontend: + container_name: vite_vue_frontend + build: + context: frontend + dockerfile: Dockerfile + args: + VITE_API_URL: http://backend:8000/api + ports: + - "80:80" + depends_on: + pg: + condition: service_healthy + backend: + condition: service_started + restart: unless-stopped + + pg: + image: postgres:18-alpine + environment: + POSTGRES_DB: backlog + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + PGDATA: /var/lib/postgresql/data + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready"] + interval: 5s + timeout: 3s + retries: 3 + +volumes: + pgdata: diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..1cc3f3a --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,36 @@ +# Stage 1: Build +FROM node:20-alpine AS build + +# Устанавливаем рабочую директорию +WORKDIR /app + +# Копируем package.json и package-lock.json (или pnpm-lock.yaml / yarn.lock) +COPY package*.json ./ + +# Устанавливаем зависимости +RUN npm ci + +# Копируем исходники +COPY . . + +# Передаем API URL как build-arg +ARG VITE_API_URL +ENV VITE_API_URL=$VITE_API_URL + +# Собираем приложение +RUN npm run build + +# Stage 2: Production +FROM nginx:alpine + +# Копируем собранные файлы из предыдущего этапа +COPY --from=build /app/dist /usr/share/nginx/html + +# Копируем кастомный конфиг nginx (опционально) +# COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Экспонируем порт +EXPOSE 80 + +# Запускаем nginx +CMD ["nginx", "-g", "daemon off;"] From bfc0e94537379dc8d0d306ea28b91d1e271a1dde Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 16:51:53 +0300 Subject: [PATCH 05/15] fix imoprts --- backend/backlog_app/alembic/env.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/backlog_app/alembic/env.py b/backend/backlog_app/alembic/env.py index 1e16910..e786e49 100644 --- a/backend/backlog_app/alembic/env.py +++ b/backend/backlog_app/alembic/env.py @@ -8,8 +8,8 @@ from logging.config import fileConfig from alembic import context -from config import settings -from models.base import Base +from backlog_app.config import settings +from backlog_app.models import Base from sqlalchemy import pool from sqlalchemy.ext.asyncio import AsyncConnection, create_async_engine From 2e11b225fc19b692d45d4981db9f8899f8d7f6db Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 17:14:08 +0300 Subject: [PATCH 06/15] add script for apply migration --- backend/backlog_app/prestart.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 backend/backlog_app/prestart.sh diff --git a/backend/backlog_app/prestart.sh b/backend/backlog_app/prestart.sh new file mode 100644 index 0000000..b0cd115 --- /dev/null +++ b/backend/backlog_app/prestart.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e +set -x + +echo "Run apply migrations.." +alembic upgrade head +echo "Migrations applied!" + +exec "$@" From a0fbeb6646f84cc136593978a6cabbb3349129e5 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 17:33:40 +0300 Subject: [PATCH 07/15] edit Dockerfile --- backend/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 775eed7..5881597 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,6 +1,9 @@ FROM python:3.13-slim -COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 + +COPY --from=ghcr.io/astral-sh/uv:0.9.29 /uv /uvx /bin/ WORKDIR /app From ca4289900bcbaeb9afc1585091f047d53cd17172 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 17:48:42 +0300 Subject: [PATCH 08/15] add nginx config --- frontend/nginx.conf | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 frontend/nginx.conf diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..c17f38a --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,21 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + allow 123.45.67.89; + deny all; + + location / { + try_files $uri /index.html; + } + + error_page 403 /403.html; + location = /403.html { + internal; + default_type text/html; + return 403 'Access forbidden'; + } +} From 93351f4eeca6235027fc11916321247fd6bfdc67 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 17:48:58 +0300 Subject: [PATCH 09/15] edit frontend Dockerfile --- frontend/Dockerfile | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 1cc3f3a..6877a3d 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,36 +1,25 @@ # Stage 1: Build FROM node:20-alpine AS build -# Устанавливаем рабочую директорию WORKDIR /app -# Копируем package.json и package-lock.json (или pnpm-lock.yaml / yarn.lock) COPY package*.json ./ - -# Устанавливаем зависимости RUN npm ci -# Копируем исходники COPY . . -# Передаем API URL как build-arg ARG VITE_API_URL ENV VITE_API_URL=$VITE_API_URL -# Собираем приложение RUN npm run build # Stage 2: Production FROM nginx:alpine -# Копируем собранные файлы из предыдущего этапа COPY --from=build /app/dist /usr/share/nginx/html -# Копируем кастомный конфиг nginx (опционально) -# COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d/default.conf -# Экспонируем порт EXPOSE 80 -# Запускаем nginx CMD ["nginx", "-g", "daemon off;"] From 2b256d5aec8b655bdf6b8a1bd58294d87f881862 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 21:25:55 +0300 Subject: [PATCH 10/15] edit volume name --- docker-compose.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index a0b4fd7..2126f67 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,7 +3,7 @@ services: backend: container_name: fastapi_app build: - context: ./backend + context: backend dockerfile: Dockerfile env_file: - ./backend/backlog_app/.env @@ -32,16 +32,16 @@ services: restart: unless-stopped pg: - image: postgres:18-alpine + image: postgres:18 environment: POSTGRES_DB: backlog POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - PGDATA: /var/lib/postgresql/data + PGDATA: /var/lib/postgresql/data/pgdata ports: - "5432:5432" volumes: - - pgdata:/var/lib/postgresql/data + - pgdata:/var/lib/postgresql/data/pgdata healthcheck: test: ["CMD-SHELL", "pg_isready"] interval: 5s From e216bb76ddbda8a36189e3d02a440171fc1a07c2 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 22:18:30 +0300 Subject: [PATCH 11/15] edit frontend nginx --- frontend/nginx.conf | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/frontend/nginx.conf b/frontend/nginx.conf index c17f38a..6d95b8c 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -5,17 +5,12 @@ server { root /usr/share/nginx/html; index index.html; - allow 123.45.67.89; - deny all; - location / { - try_files $uri /index.html; + try_files $uri $uri/ /index.html; } - error_page 403 /403.html; - location = /403.html { - internal; - default_type text/html; - return 403 'Access forbidden'; + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; } } From 6c0ef8afaabc532ac5db5bd942aec34b4030c9c3 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 22:18:54 +0300 Subject: [PATCH 12/15] add server nginx config --- nginx/nginx.conf | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 nginx/nginx.conf diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..6d02e66 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,38 @@ +events { + worker_connections 1024; +} + +http { + upstream backend { + server backend:8000; + } + + upstream frontend { + server frontend:80; + } + + server { + listen 80; + server_name _; + + allow 123.456.789.101; # Change IP + deny all; + + location / { + proxy_pass http://frontend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /api { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + } + } +} From 64138ed7b76ddba8bbe369700a3d7fa404ad3178 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Wed, 4 Feb 2026 22:33:20 +0300 Subject: [PATCH 13/15] add nginx to docker compose --- .gitignore | 1 + docker-compose.yaml | 60 +++++++++++++++++++++++++++++++-------------- nginx/nginx.conf | 2 +- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index c3002d8..e432cec 100644 --- a/.gitignore +++ b/.gitignore @@ -149,6 +149,7 @@ activemq-data/ # Environments .env +.env.production .envrc .venv env/ diff --git a/docker-compose.yaml b/docker-compose.yaml index 2126f67..3ea9ab7 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,13 +7,14 @@ services: dockerfile: Dockerfile env_file: - ./backend/backlog_app/.env - ports: - - "8000:8000" + expose: + - "8000" depends_on: pg: condition: service_healthy - volumes: - - ./backend/backlog_app:/app/backlog_app + restart: unless-stopped + networks: + - app-network frontend: container_name: vite_vue_frontend @@ -21,32 +22,55 @@ services: context: frontend dockerfile: Dockerfile args: - VITE_API_URL: http://backend:8000/api - ports: - - "80:80" + VITE_API_URL: /api + expose: + - "80" depends_on: - pg: - condition: service_healthy backend: condition: service_started restart: unless-stopped + networks: + - app-network pg: image: postgres:18 + env_file: + - .env environment: - POSTGRES_DB: backlog - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} PGDATA: /var/lib/postgresql/data/pgdata - ports: - - "5432:5432" + expose: + - "5432" volumes: - pgdata:/var/lib/postgresql/data/pgdata healthcheck: - test: ["CMD-SHELL", "pg_isready"] - interval: 5s - timeout: 3s - retries: 3 + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 + restart: unless-stopped + networks: + - app-network + + nginx: + image: nginx:alpine + container_name: nginx_proxy + ports: + - "80:80" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + depends_on: + - backend + - frontend + restart: unless-stopped + networks: + - app-network volumes: pgdata: + +networks: + app-network: + driver: bridge diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 6d02e66..a39d59b 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -15,7 +15,7 @@ http { listen 80; server_name _; - allow 123.456.789.101; # Change IP + allow 127.0.0.1; # Change IP deny all; location / { From c2e15c041fb4673147fab2b4b24023afd2dabce6 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Thu, 5 Feb 2026 10:09:20 +0300 Subject: [PATCH 14/15] add compose for developing --- docker-compose.dev.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 docker-compose.dev.yaml diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml new file mode 100644 index 0000000..9bf719b --- /dev/null +++ b/docker-compose.dev.yaml @@ -0,0 +1,24 @@ +services: + + pg: + image: postgres:18 + env_file: + - .env + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + PGDATA: /var/lib/postgresql/data/pgdata + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data/pgdata + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 + restart: unless-stopped + +volumes: + pgdata: From 59832d12337c6d4114a099be1b567c4dbca41f43 Mon Sep 17 00:00:00 2001 From: Nikita Yakovlev Date: Thu, 5 Feb 2026 10:23:05 +0300 Subject: [PATCH 15/15] fix lint --- backend/backlog_app/alembic/env.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/backlog_app/alembic/env.py b/backend/backlog_app/alembic/env.py index e786e49..1e671d8 100644 --- a/backend/backlog_app/alembic/env.py +++ b/backend/backlog_app/alembic/env.py @@ -8,11 +8,12 @@ from logging.config import fileConfig from alembic import context -from backlog_app.config import settings -from backlog_app.models import Base from sqlalchemy import pool from sqlalchemy.ext.asyncio import AsyncConnection, create_async_engine +from backlog_app.config import settings +from backlog_app.models import Base + config = context.config if config.config_file_name is not None: