From 3d69f592f61d3ba29b93ad19f937aa89b7673fd6 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Sun, 21 Apr 2024 14:34:45 +0200 Subject: [PATCH] split Dockerfile, dynamic backend URL --- Dockerfile | 38 ++------------------ Makefile | 3 ++ .dockerignore => tank-frontend/.dockerignore | 4 +-- tank-frontend/.env | 3 -- tank-frontend/Dockerfile | 13 +++++++ tank-frontend/src/ClientScreen.tsx | 3 +- tank-frontend/src/Controls.tsx | 3 +- tank-frontend/src/PlayerInfo.tsx | 4 +-- tank-frontend/src/Scoreboard.tsx | 4 +-- tank-frontend/src/serverCalls.tsx | 8 +++-- tank-frontend/vite.config.ts | 2 +- tanks-backend/.dockerignore | 13 +++++++ tanks-backend/Dockerfile | 26 ++++++++++++++ tanks-backend/TanksServer/TanksServer.csproj | 9 +---- tanks-backend/TanksServer/appsettings.json | 2 +- 15 files changed, 75 insertions(+), 60 deletions(-) rename .dockerignore => tank-frontend/.dockerignore (83%) delete mode 100644 tank-frontend/.env create mode 100644 tank-frontend/Dockerfile create mode 100644 tanks-backend/.dockerignore create mode 100644 tanks-backend/Dockerfile diff --git a/Dockerfile b/Dockerfile index 2a97396..ff42485 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,38 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build-server +FROM localhost/cccb-tanks-cs-backend:latest -RUN apk add clang binutils musl-dev build-base zlib-static cmake openssl-dev openssl-libs-static openssl +COPY --from=localhost/cccb-tanks-cs-frontend /app/dist ./client -WORKDIR /src/TanksServer - -# dependencies -COPY TanksServer/TanksServer.csproj . -RUN dotnet restore --runtime linux-musl-x64 TanksServer.csproj - -#build -COPY TanksServer . -RUN dotnet build TanksServer.csproj -c Release -o /app/build -RUN dotnet publish TanksServer.csproj -r linux-musl-x64 -c Release -o /app/publish - - -FROM node:21-alpine AS build-client -WORKDIR /app - -# dependencies -COPY tank-frontend/package.json . -COPY tank-frontend/package-lock.json . -RUN npm i - -# build -env CONTAINERMODE 1 -COPY tank-frontend . -RUN npm run build - - -FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine AS final -WORKDIR /app - -COPY --from=build-server /app/publish . -COPY --from=build-client /app/dist ./client - -EXPOSE 80 -ENTRYPOINT ./TanksServer diff --git a/Makefile b/Makefile index aea9456..9432c05 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ TAG=cccb-tanks-cs build: + podman build tanks-backend --tag=$(TAG)-backend + podman build tank-frontend --tag=$(TAG)-frontend podman build . --tag=$(TAG) run: build podman run -i -p 3000:3000 localhost/$(TAG):latest + diff --git a/.dockerignore b/tank-frontend/.dockerignore similarity index 83% rename from .dockerignore rename to tank-frontend/.dockerignore index 2cee31d..ac8dfc1 100644 --- a/.dockerignore +++ b/tank-frontend/.dockerignore @@ -14,6 +14,7 @@ **/azds.yaml **/bin **/charts +**/dist **/docker-compose* **/Dockerfile* **/node_modules @@ -21,6 +22,3 @@ **/obj **/secrets.dev.yaml **/values.dev.yaml -LICENSE -README.md -**/node_modules diff --git a/tank-frontend/.env b/tank-frontend/.env deleted file mode 100644 index 8551df8..0000000 --- a/tank-frontend/.env +++ /dev/null @@ -1,3 +0,0 @@ -TANK_DOMAIN=vinzenz-lpt2 -VITE_TANK_API=http://$TANK_DOMAIN -VITE_TANK_WS=ws://$TANK_DOMAIN diff --git a/tank-frontend/Dockerfile b/tank-frontend/Dockerfile new file mode 100644 index 0000000..ed202e2 --- /dev/null +++ b/tank-frontend/Dockerfile @@ -0,0 +1,13 @@ +FROM node:21-alpine AS build-client +WORKDIR /app + +# dependencies +COPY package.json . +COPY package-lock.json . +RUN npm i + +# build +env CONTAINERMODE 1 +COPY . . +RUN npm run build + diff --git a/tank-frontend/src/ClientScreen.tsx b/tank-frontend/src/ClientScreen.tsx index 3249805..a5c636c 100644 --- a/tank-frontend/src/ClientScreen.tsx +++ b/tank-frontend/src/ClientScreen.tsx @@ -3,6 +3,7 @@ import {useEffect, useRef} from 'react'; import './ClientScreen.css'; import {hslToString, Theme} from "./theme.ts"; import {Guid} from "./Guid.ts"; +import {makeApiUrl} from './serverCalls.tsx'; const pixelsPerRow = 352; const pixelsPerCol = 160; @@ -104,7 +105,7 @@ export default function ClientScreen({logout, theme, playerId}: { }) { const canvasRef = useRef(null); - const url = new URL('/screen', import.meta.env.VITE_TANK_WS); + const url = makeApiUrl('/screen', 'ws'); if (playerId) url.searchParams.set('player', playerId); diff --git a/tank-frontend/src/Controls.tsx b/tank-frontend/src/Controls.tsx index f922e3f..9ce50f7 100644 --- a/tank-frontend/src/Controls.tsx +++ b/tank-frontend/src/Controls.tsx @@ -2,9 +2,10 @@ import './Controls.css'; import useWebSocket, {ReadyState} from 'react-use-websocket'; import {useEffect} from 'react'; import {Guid} from "./Guid.ts"; +import {makeApiUrl} from './serverCalls.tsx'; export default function Controls({playerId}: { playerId: Guid }) { - const url = new URL('controls', import.meta.env.VITE_TANK_WS); + const url = makeApiUrl('/controls', 'ws'); url.searchParams.set('playerId', playerId); const { diff --git a/tank-frontend/src/PlayerInfo.tsx b/tank-frontend/src/PlayerInfo.tsx index 348503e..0832adc 100644 --- a/tank-frontend/src/PlayerInfo.tsx +++ b/tank-frontend/src/PlayerInfo.tsx @@ -1,5 +1,5 @@ import {useQuery} from '@tanstack/react-query' -import {Player} from './serverCalls'; +import {makeApiUrl, Player} from './serverCalls'; import {Guid} from "./Guid.ts"; import Column from "./components/Column.tsx"; @@ -18,7 +18,7 @@ export default function PlayerInfo({playerId}: { playerId: Guid }) { queryKey: ['player'], refetchInterval: 1000, queryFn: async () => { - const url = new URL('/player', import.meta.env.VITE_TANK_API); + const url = makeApiUrl('/player'); url.searchParams.set('id', playerId); const response = await fetch(url, {method: 'GET'}); diff --git a/tank-frontend/src/Scoreboard.tsx b/tank-frontend/src/Scoreboard.tsx index 2b0cc29..13e987f 100644 --- a/tank-frontend/src/Scoreboard.tsx +++ b/tank-frontend/src/Scoreboard.tsx @@ -1,4 +1,4 @@ -import {Player} from "./serverCalls.tsx"; +import {makeApiUrl, Player} from './serverCalls.tsx'; import DataTable from "./components/DataTable.tsx"; import {useQuery} from "@tanstack/react-query"; @@ -11,7 +11,7 @@ export default function Scoreboard({}: {}) { queryKey: ['scores'], refetchInterval: 1000, queryFn: async () => { - const url = new URL('/scores', import.meta.env.VITE_TANK_API); + const url = makeApiUrl('/scores'); const response = await fetch(url, {method: 'GET'}); if (!response.ok) throw new Error(`response failed with code ${response.status} (${response.status})${await response.text()}`) diff --git a/tank-frontend/src/serverCalls.tsx b/tank-frontend/src/serverCalls.tsx index 8a0dd16..9a03ded 100644 --- a/tank-frontend/src/serverCalls.tsx +++ b/tank-frontend/src/serverCalls.tsx @@ -1,5 +1,9 @@ import {Guid} from './Guid.ts'; +export function makeApiUrl(path: string, protocol: 'http' | 'ws' = 'http') { + return new URL(`${protocol}://${window.location.hostname}${path}`); +} + export type ServerResponse = { ok: boolean; statusCode: number; @@ -29,7 +33,7 @@ export async function fetchTyped({url, method}: { url: URL; method: string; } ok: response.ok, statusCode: response.status, statusText: response.statusText - } + }; if (response.ok) result.successResult = await response.json(); @@ -39,7 +43,7 @@ export async function fetchTyped({url, method}: { url: URL; method: string; } } export function postPlayer({name, id}: NameId) { - const url = new URL('/player', import.meta.env.VITE_TANK_API); + const url = makeApiUrl('/player'); url.searchParams.set('name', name); url.searchParams.set('id', id); diff --git a/tank-frontend/vite.config.ts b/tank-frontend/vite.config.ts index 208faab..5986416 100644 --- a/tank-frontend/vite.config.ts +++ b/tank-frontend/vite.config.ts @@ -8,7 +8,7 @@ export default defineConfig(() => { plugins: [react()], build: { - outDir: isContainer ? undefined : '../TanksServer/client', + outDir: isContainer ? undefined : '../tanks-backend/TanksServer/client', emptyOutDir: true } }; diff --git a/tanks-backend/.dockerignore b/tanks-backend/.dockerignore new file mode 100644 index 0000000..d041927 --- /dev/null +++ b/tanks-backend/.dockerignore @@ -0,0 +1,13 @@ +**/.dockerignore +**/.env +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/bin +**/Dockerfile* +**/obj diff --git a/tanks-backend/Dockerfile b/tanks-backend/Dockerfile new file mode 100644 index 0000000..4fcda7d --- /dev/null +++ b/tanks-backend/Dockerfile @@ -0,0 +1,26 @@ +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build-server + +RUN apk add clang binutils musl-dev build-base zlib-static cmake openssl-dev openssl-libs-static openssl + +WORKDIR /src/tanks-server + +# dependencies +COPY ./shared.props . +COPY ./TanksServer.sln . +COPY ./EndiannessSourceGenerator/EndiannessSourceGenerator.csproj EndiannessSourceGenerator/EndiannessSourceGenerator.csproj +COPY ./DisplayCommands/DisplayCommands.csproj DisplayCommands/DisplayCommands.csproj +COPY ./TanksServer/TanksServer.csproj TanksServer/TanksServer.csproj +RUN dotnet restore --runtime linux-musl-x64 TanksServer.sln + +#build +COPY . . +RUN dotnet build TanksServer/TanksServer.csproj -c Release -r linux-musl-x64 -o /build +RUN dotnet publish TanksServer/TanksServer.csproj -c Release -r linux-musl-x64 -o /app + +FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine AS final +WORKDIR /app + +COPY --from=build-server /app . + +EXPOSE 80 +ENTRYPOINT ./TanksServer diff --git a/tanks-backend/TanksServer/TanksServer.csproj b/tanks-backend/TanksServer/TanksServer.csproj index f2c2490..307de71 100644 --- a/tanks-backend/TanksServer/TanksServer.csproj +++ b/tanks-backend/TanksServer/TanksServer.csproj @@ -4,11 +4,6 @@ true - - false - true - true - true @@ -18,9 +13,7 @@ - - - + diff --git a/tanks-backend/TanksServer/appsettings.json b/tanks-backend/TanksServer/appsettings.json index 1ef31e6..045fd04 100644 --- a/tanks-backend/TanksServer/appsettings.json +++ b/tanks-backend/TanksServer/appsettings.json @@ -11,7 +11,7 @@ "Kestrel": { "Endpoints": { "Http": { - "Url": "http://localhost:3000" + "Url": "http://0.0.0.0:3000" } } },