diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0847e88 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +dist +.angular +.git +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e9224c6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:24.15-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +FROM nginx:1.27-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist/admin-frontend/browser /usr/share/nginx/html +EXPOSE 80 +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 CMD wget -q -O /dev/null http://127.0.0.1/ || exit 1 diff --git a/angular.json b/angular.json index 57ef391..f9219ab 100644 --- a/angular.json +++ b/angular.json @@ -25,9 +25,7 @@ "input": "public" } ], - "styles": [ - "src/styles.css" - ] + "styles": ["src/styles.css"] }, "configurations": { "production": { @@ -63,7 +61,10 @@ "buildTarget": "admin-frontend:build:development" } }, - "defaultConfiguration": "development" + "defaultConfiguration": "development", + "options": { + "proxyConfig": "proxy.conf.json" + } }, "test": { "builder": "@angular/build:unit-test" diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..74f8fce --- /dev/null +++ b/compose.yaml @@ -0,0 +1,10 @@ +services: + admin: + build: + context: . + dockerfile: Dockerfile + ports: + - "4200:80" + extra_hosts: + - "host.docker.internal:host-gateway" + restart: unless-stopped diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..a752a20 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,16 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + location /api/ { + proxy_pass http://host.docker.internal:8000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/proxy.conf.json b/proxy.conf.json new file mode 100644 index 0000000..83454af --- /dev/null +++ b/proxy.conf.json @@ -0,0 +1,8 @@ +{ + "/api": { + "target": "http://localhost:8000", + "secure": false, + "changeOrigin": true, + "pathRewrite": { "^/api": "" } + } +} diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 5337bd8..13d8fe0 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,7 +1,14 @@ /** * Runtime configuration for local development. * - * `apiBaseUrl` points at the FastAPI service; `keycloak` matches the realm + * `apiBaseUrl` is a same-origin path, not a host. Both ways of running this app + * map `/api` onto the FastAPI service — nginx does it in the container, + * `proxy.conf.json` does it for `ng serve` — so the application never carries a + * hardcoded API host and the two behave identically. + * + * The Keycloak URL stays absolute because the browser is redirected to it, so a + * same-origin path would be meaningless there. + * `keycloak` matches the realm * committed in the API repository (`keycloak/opentaberna-realm.json`). * * The client id matters: the API only accepts tokens on `/v1/admin/**` whose @@ -10,7 +17,7 @@ */ export const environment = { production: false, - apiBaseUrl: 'http://localhost:8000', + apiBaseUrl: '/api', /** * Uncaught error reporting. Off by default; requires FRONTEND_ERRORS_ENABLED * on the API, which otherwise answers the endpoint with a 404. diff --git a/tsconfig.app.json b/tsconfig.app.json index cb151e1..1eb42f4 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -5,10 +5,6 @@ "compilerOptions": { "types": [] }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "src/**/*.spec.ts" - ] + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.spec.ts"] } diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 9c8efb9..aecce35 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -3,12 +3,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "types": [ - "vitest/globals" - ] + "types": ["vitest/globals"] }, - "include": [ - "src/**/*.d.ts", - "src/**/*.spec.ts" - ] + "include": ["src/**/*.d.ts", "src/**/*.spec.ts"] }