From aad319f80a0036598227f7a3e288efdaa79abb9d Mon Sep 17 00:00:00 2001 From: Gerard Smit Date: Fri, 26 Jan 2024 13:52:07 +0100 Subject: [PATCH] feat/fix: fix backend docker paths, migration db connection issue, add frontend dockerfile * feat: docker compose support * Set base URL outside of generated client --------- Co-authored-by: Yukine --- backend/MangaMagnet.Api/Dockerfile | 13 +++++---- backend/MangaMagnet.Api/Program.cs | 7 ++++- docker-compose.yml | 45 ++++++++++++++++++++++++++++++ frontend/.dockerignore | 5 ++++ frontend/Dockerfile | 25 +++++++++++++++++ frontend/next.config.js | 1 + frontend/src/middleware.ts | 16 +++++++++++ frontend/src/pages/_app.tsx | 3 ++ frontend/tsconfig.json | 2 +- frontend/typings.d.ts | 7 +++++ 10 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 docker-compose.yml create mode 100644 frontend/.dockerignore create mode 100644 frontend/Dockerfile create mode 100644 frontend/src/middleware.ts create mode 100644 frontend/typings.d.ts diff --git a/backend/MangaMagnet.Api/Dockerfile b/backend/MangaMagnet.Api/Dockerfile index 63f6e9f..6d3b6cc 100644 --- a/backend/MangaMagnet.Api/Dockerfile +++ b/backend/MangaMagnet.Api/Dockerfile @@ -7,17 +7,18 @@ EXPOSE 8081 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src -COPY ["MangaMagnet/MangaMagnet.csproj", "MangaMagnet/"] -RUN dotnet restore "MangaMagnet/MangaMagnet.csproj" +COPY ["MangaMagnet.Api/MangaMagnet.Api.csproj", "MangaMagnet.Api/"] +COPY ["MangaMagnet.Core/MangaMagnet.Core.csproj", "MangaMagnet.Core/"] +RUN dotnet restore "MangaMagnet.Api/MangaMagnet.Api.csproj" COPY . . -WORKDIR "/src/MangaMagnet" -RUN dotnet build "MangaMagnet.csproj" -c $BUILD_CONFIGURATION -o /app/build +WORKDIR "/src/MangaMagnet.Api" +RUN dotnet build "MangaMagnet.Api.csproj" --no-restore -c $BUILD_CONFIGURATION -o /app/build FROM build AS publish ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "MangaMagnet.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false +RUN dotnet publish "MangaMagnet.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "MangaMagnet.dll"] +ENTRYPOINT ["dotnet", "MangaMagnet.Api.dll"] diff --git a/backend/MangaMagnet.Api/Program.cs b/backend/MangaMagnet.Api/Program.cs index f291f90..ab05327 100644 --- a/backend/MangaMagnet.Api/Program.cs +++ b/backend/MangaMagnet.Api/Program.cs @@ -1,3 +1,4 @@ +using System.Data; using System.Net; using System.Text.Json.Serialization; using Asp.Versioning; @@ -151,7 +152,11 @@ if (dbContext?.Database.GetDbConnection() is NpgsqlConnection npgsqlConnection) { - await npgsqlConnection.OpenAsync(); + if (npgsqlConnection.State != ConnectionState.Open) + { + await npgsqlConnection.OpenAsync(); + } + try { await npgsqlConnection.ReloadTypesAsync(); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9d0981c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,45 @@ +version: '3.1' + +services: + postgres: + image: postgres:16 + environment: + POSTGRES_USER: mangamagnet + POSTGRES_PASSWORD: password + POSTGRES_DB: mangamagnet + healthcheck: + test: ["CMD-SHELL", "pg_isready -U mangamagnet -d mangamagnet"] + interval: 5s + timeout: 5s + retries: 5 + volumes: + - data:/var/lib/postgresql/data + + backend: + image: mangamagnet-backend + build: + context: ./backend + dockerfile: MangaMagnet.Api/Dockerfile + ports: + - 43524:8080 + depends_on: + postgres: + condition: service_healthy + environment: + DOTNET_ConnectionStrings__PostgreSQLConnection: Host=postgres;Port=5432;Database=mangamagnet;Username=mangamagnet;Password=password + DOTNET_ConnectionStrings__QuartzPostgresSQLConnection: Host=postgres;Port=5432;Database=mangamagnet;Username=mangamagnet;Password=password;Search Path=quartz + + frontend: + image: mangamagnet-frontend + build: + context: ./frontend + dockerfile: Dockerfile + ports: + - 43525:3000 + depends_on: + - backend + environment: + API_BASE: http://backend:8080 + +volumes: + data: \ No newline at end of file diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..b0c2031 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,5 @@ +node_modules +.git +.gitignore +*.md +dist \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..4e31d74 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,25 @@ +FROM node:20-slim AS base +WORKDIR /app + +FROM base AS base-pnpm +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable + +FROM base-pnpm AS prod-deps +COPY package.json pnpm-lock.yaml ./ +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile + +FROM base-pnpm AS build +COPY . /app +ENV NEXT_TELEMETRY_DISABLED 1 +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile +RUN pnpm run build + +FROM base +COPY --from=build /app/public ./public +COPY --from=build /app/.next/standalone ./ +COPY --from=build /app/.next/static ./.next/static +ENV PORT 3000 +EXPOSE 3000 +CMD ["node", "server.js"] \ No newline at end of file diff --git a/frontend/next.config.js b/frontend/next.config.js index c282ac2..a48abe0 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -1,5 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + output: 'standalone', reactStrictMode: true, images: { remotePatterns: [{ diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts new file mode 100644 index 0000000..4bf506c --- /dev/null +++ b/frontend/src/middleware.ts @@ -0,0 +1,16 @@ +import { NextRequest, NextResponse } from "next/server"; + +export const config = { + matcher: ["/api/:path*"], +}; + +export function middleware(request: NextRequest) { + const API_BASE = process.env.API_BASE ?? 'http://localhost:5248' + + return NextResponse.rewrite( + new URL( + `${API_BASE}${request.nextUrl.pathname}${request.nextUrl.search}` + ), + { request } + ); +} \ No newline at end of file diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx index 021681f..ba778b3 100644 --- a/frontend/src/pages/_app.tsx +++ b/frontend/src/pages/_app.tsx @@ -1,6 +1,9 @@ +import { OpenAPI } from '@/services/openapi' import '@/styles/globals.css' import type { AppProps } from 'next/app' +OpenAPI.BASE = ''; + export default function App({ Component, pageProps }: AppProps) { return } diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 3ca6a9a..6a2a96d 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es2015", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, diff --git a/frontend/typings.d.ts b/frontend/typings.d.ts new file mode 100644 index 0000000..8587856 --- /dev/null +++ b/frontend/typings.d.ts @@ -0,0 +1,7 @@ +interface ImportMetaEnv { + readonly API_BASE: string +} + +interface ImportMeta { + readonly env?: ImportMetaEnv +} \ No newline at end of file