Building the Image

Deployments normally consume the image published by CI (see Installation & Deployment). Build locally only for development or a patched release.

CI Build

.github/workflows/build-callable.yml runs on the rd-runner self-hosted runner and performs, in order:

  1. npm install --legacy-peer-deps

  2. a compatibility symlink for chart.js (Chart.jschart.umd.js) — the case-insensitive import that works on macOS would otherwise fail on the Linux runner

  3. ng build --project=ft-common — the shared library must exist before the applications

  4. both applications in parallel, each with its deployed base path:

    ng build --project=management-console -c=production --base-href /management-portal/
    ng build --project=support-center     -c=production --base-href /support-portal/
  5. docker/build-push-action builds docker/Dockerfile and pushes hub.friendly-tech.com/ui/portals:<tags> to Harbor.

Triggers:

Workflow Trigger

build-on-auto.yml

Every push to main, tagged dev. The paths .github/ and docs/ are excluded, so a documentation-only change does not rebuild the image.

build-on-manually.yml

workflow_dispatch with a chosen branch and tag list.

The default platforms input is linux/amd64; another architecture requires an explicit value.

Local Build

docker/Dockerfile is a runtime-only image — it contains no Node.js and copies the dist/ output produced on the build host. Build the Angular projects first, in this order, or the COPY steps fail:

npm install --legacy-peer-deps
ng build --project=ft-common
ng build --project=support-center     -c=production --base-href /support-portal/
ng build --project=management-console -c=production --base-href /management-portal/

docker build -f docker/Dockerfile -t ui/portals:local .

docker/docker-compose.yml wraps the same build (context: ../) for a one-command local run, and docker/docker-push.sh shows the buildx variant used to push manually.

--base-href must match the path Nginx serves the app under (/support-portal/, /management-portal/). A mismatch produces a page that loads index.html but requests all JavaScript and CSS from the wrong prefix — a blank screen with 404s in DevTools.

Image Contents

Path in the image Source

/usr/share/nginx/html/support-center/

dist/support-center (Angular 19 application builder output, with the app itself under browser/)

/usr/share/nginx/html/management-console/

dist/management-console

/etc/nginx/nginx.conf.template

docker/ops/nginx.conf, rendered to /etc/nginx/nginx.conf by the entrypoint

/entrypoint.sh

docker/ops/entrypoint.sh

The base image is nginx:alpine with jq, bash and gettext added — jq patches the runtime config, envsubst (from gettext) renders the Nginx template.