diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c9a12d7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +node_modules +dist +.angular +.git +.env +coverage +npm-debug.log* +apps/api/dist +apps/web/dist diff --git a/.env.example b/.env.example index 9be13bc..bc86ce4 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,7 @@ NODE_ENV=development API_PORT=3000 WEB_PORT=4200 PUBLIC_WEB_URL=http://localhost:4200 +API_BASE_URL=http://localhost:3000 DATABASE_URL=mysql://ldap_portal:change-me@mysql.example.com:3306/ldap_portal DATABASE_SSL=false diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c9d3e61 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +FROM node:22-alpine AS deps +WORKDIR /app +COPY package*.json ./ +COPY apps/api/package.json apps/api/package.json +COPY apps/web/package.json apps/web/package.json +RUN npm ci + +FROM deps AS build +COPY tsconfig.base.json ./ +COPY eslint.config.mjs ./ +COPY apps/api apps/api +COPY apps/web apps/web +RUN npm run build + +FROM node:22-alpine AS runtime +WORKDIR /app +ENV NODE_ENV=production +ENV API_PORT=3000 +ENV WEB_PORT=8080 +ENV API_BASE_URL=http://localhost:3000 + +RUN apk add --no-cache nginx + +COPY --from=deps /app/node_modules node_modules +COPY --from=build /app/apps/api/dist api +COPY --from=build /app/apps/web/dist/web/browser /usr/share/nginx/html +COPY apps/api/package.json package.json +COPY docker/single-container.nginx.conf /etc/nginx/http.d/default.conf +COPY docker/start-single-container.sh /usr/local/bin/start-ldap-portal +RUN chmod +x /usr/local/bin/start-ldap-portal \ + && mkdir -p /run/nginx /var/log/nginx + +EXPOSE 3000 8080 +CMD ["start-ldap-portal"] diff --git a/README.md b/README.md index 3549397..31cbc98 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,33 @@ docker compose up --build Passe vor dem Start mindestens `DATABASE_URL`, `JWT_SECRET`, `TOKEN_SECRET`, `LLDAP_*` und `SMTP_*` an. Fuer OIDC muessen zusaetzlich `OIDC_ISSUER`, `OIDC_COOKIE_SECRET`, `OIDC_ADMIN_GROUP` und `OIDC_ADMIN_GROUP_UUID` gesetzt werden. +## Single Container Image + +Das Root-`Dockerfile` baut API und Angular in ein einzelnes Image. Der Container startet: + +- NestJS API / IdP auf Port `3000` +- Nginx Web-UI auf Port `8080` + +Build und Push: + +```bash +docker build -t registry.example.com/ldap-portal/idp:latest . +docker push registry.example.com/ldap-portal/idp:latest +``` + +Start: + +```bash +docker run -d --name ldap-portal-idp \ + --env-file .env \ + -e API_BASE_URL=https://id.example.com \ + -p 3000:3000 \ + -p 8080:8080 \ + registry.example.com/ldap-portal/idp:latest +``` + +`API_BASE_URL` wird beim Containerstart in `/config.js` geschrieben und vom Angular-Frontend gelesen. Setze es auf die aus Browser-Sicht erreichbare API-/IdP-URL. + ## Externe Dienste Die Anwendung bringt keine Datenbank und keinen LLDAP-Server mehr per Compose mit. Erwartet werden: diff --git a/apps/web/angular.json b/apps/web/angular.json index 1ade458..1c45420 100644 --- a/apps/web/angular.json +++ b/apps/web/angular.json @@ -18,7 +18,7 @@ "browser": "src/main.ts", "polyfills": ["zone.js"], "tsConfig": "tsconfig.app.json", - "assets": ["src/favicon.ico"], + "assets": ["src/favicon.ico", "src/config.js"], "styles": ["src/styles.css"] }, "configurations": { diff --git a/apps/web/src/config.js b/apps/web/src/config.js new file mode 100644 index 0000000..9f68964 --- /dev/null +++ b/apps/web/src/config.js @@ -0,0 +1,3 @@ +window.__LDAP_PORTAL_CONFIG__ = { + apiBaseUrl: 'http://localhost:3000' +}; diff --git a/apps/web/src/index.html b/apps/web/src/index.html index 79216a6..e2a2801 100644 --- a/apps/web/src/index.html +++ b/apps/web/src/index.html @@ -5,6 +5,7 @@