6.1 KiB
packaging Specification
Purpose
Defines how the dashboard is built into its container image and what the image guarantees to whoever runs it: location of the Dockerfile, build arguments, base images, user, ports, health check, architectures and size budget.
Requirements
Requirement: One Dockerfile per edition inside its package
Edition: CE. The CE edition SHALL be built from dashboard-ce/docker/Dockerfile, with the workspace root
(openvidu-dashboard/) as build context, so one docker build sees the lockfile and every package.
Scenario: CE image built from the workspace root
- GIVEN a checkout of the workspace
- WHEN
docker build -f dashboard-ce/docker/Dockerfile .runs fromopenvidu-dashboard/ - THEN it produces a runnable CE image without any other input
Requirement: Base href build argument
Edition: CE. The Dockerfile SHALL accept the build argument BASE_HREF (default /) and build the SPA
with it, so the application can be served under a path prefix such as /dashboard/.
Scenario: Prefixed base href
- WHEN the image is built with
--build-arg BASE_HREF=/dashboard/ - THEN the served
index.htmldeclares<base href="/dashboard/">and its assets resolve under that prefix
Scenario: Default base href
- WHEN the image is built without
BASE_HREF - THEN the served
index.htmldeclares<base href="/">
Requirement: Reproducible dependency installation
Edition: CE. The image build SHALL install dependencies with pnpm from the committed lockfile in frozen mode and SHALL use a Node 24 base image pinned to an exact version tag.
Scenario: Lockfile out of date
- GIVEN a
package.jsonchange not reflected inpnpm-lock.yaml - WHEN the image is built
- THEN the build fails at the install step instead of resolving new versions
Requirement: CE runtime is a plain Node image without private dependencies
Edition: CE. The CE image SHALL run the built backend (which serves the SPA) on an official Node 24 image with only production dependencies and no private package; npm, npx, corepack and yarn SHALL be absent from the runtime image.
Scenario: CE build needs no private access
- GIVEN no build secret and no credentials for private repositories
- WHEN the CE image is built
- THEN the build succeeds
Scenario: CE image carries no private package
- WHEN the CE image filesystem is searched for packages of private repositories
- THEN nothing is found
Requirement: Non-root runtime user
Edition: CE. The main process of the image SHALL run as a non-root user with uid 1000 and gid 1000.
Scenario: Process identity
- WHEN a container of the image is running
- THEN its main process reports uid 1000 and the application files are readable by that user
Requirement: Exposed port and container health check
Edition: CE. The image SHALL declare EXPOSE 5000 and a HEALTHCHECK that requests
GET /api/healthcheck on 127.0.0.1:${SERVER_PORT} (default 5000) without external tools.
Scenario: Healthy container
- GIVEN a container that has started listening
- WHEN Docker evaluates the health check
- THEN the container becomes
healthywithin the start period
Scenario: Custom port
- GIVEN a container started with
SERVER_PORT=6000 - WHEN Docker evaluates the health check
- THEN the check targets port 6000 and the container becomes
healthy
Requirement: Multi-architecture images
Edition: CE. The Dockerfile SHALL build for linux/amd64 and linux/arm64: the platform-independent SPA build stage
runs once on $BUILDPLATFORM and the other stages run per target platform (buildx with QEMU, no native arm64
runner).
Scenario: Multi-platform build
- WHEN the image is built with
--platform linux/amd64,linux/arm64 - THEN the resulting manifest list contains both platforms and each variant starts on its architecture
Requirement: No timezone database in the images
Edition: CE. The runtime image SHALL NOT contain tzdata (it is purged from the Node base image); timestamps are
stored and logged in UTC and time zone conversion for bucketing uses the data bundled with Node.
Scenario: Time zone conversion without tzdata
- GIVEN a container with
TZunset and no/usr/share/zoneinfo - WHEN a time-series request specifies
tz=Europe/Madrid - THEN buckets are aligned to that zone and log timestamps are UTC
Requirement: Signal delivery to the application process
Edition: CE. The image CMD SHALL use exec form so the application process is PID 1 and receives SIGTERM
directly.
Scenario: docker stop
- GIVEN a running container of the image
- WHEN
docker stopis issued with the default 10 s timeout - THEN the container exits with code 0 before the timeout, without being killed
Requirement: Image names and build wrapper
Edition: CE. The image SHALL be named openvidu/openvidu-dashboard. ./dashboard.sh build-image ce SHALL build it
honouring IMAGE_TAG (default dev) and BASE_HREF (default /).
Scenario: Wrapper builds CE
- WHEN
./dashboard.sh build-image ceruns - THEN the image
openvidu/openvidu-dashboard:devexists locally
Requirement: Image size budget
Edition: CE. The uncompressed linux/amd64 CE image SHALL NOT exceed 300 MB; the image smoke test
(./dashboard.sh smoke-image ce) enforces the budget.
Scenario: Budget exceeded
- WHEN a built image is larger than its budget
- THEN the smoke test fails and reports the measured size
Requirement: Supply-chain verification inside the image build
Edition: CE. The Dockerfile SHALL install Aikido safe-chain in the build stage and run npm safe-chain-verify
(with SAFE_CHAIN_MINIMUM_PACKAGE_AGE_HOURS=0, so only packages flagged as malicious fail the build) before installing
dependencies, so the verification runs wherever the image is built.
Scenario: Build with a flagged package
- GIVEN a lockfile that resolves a package flagged as malicious by safe-chain
- WHEN the image is built
- THEN the build fails in the verification step before any dependency is installed