Skip to main content
The Roots UI ships as a two-stage Docker image. The first stage builds the Vite app; the second stage copies the compiled assets into an Nginx image and serves them. No Node.js runtime is present in the final image.

Prerequisites

  • Docker 20.10 or later
  • Docker Compose v2 or later (for Compose-based deployments)
  • An accessible instance of the ATT backend API
Environment variables are baked into the Vite build at compile time. Set VITE_API_BASE_URL (and any other VITE_ variables) before running docker build. Changing them later requires a rebuild.

Dockerfile

The repository includes the following multi-stage Dockerfile:
Dockerfile
FROM node:18-alpine AS build 
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

COPY . .

RUN npm run build

# serve
FROM nginx:stable-alpine

COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
Build stage — uses node:18-alpine to install dependencies with npm ci and produce the optimised static bundle via npm run build (Vite). Serve stage — copies /app/dist into the Nginx web root (/usr/share/nginx/html) and replaces the default Nginx site configuration with the project’s nginx.conf. The container listens on port 80.

Standalone deployment

1

Copy and edit the environment file

cp .env.example .env
# Edit .env and set VITE_API_BASE_URL to your backend URL
Vite reads .env at build time. See Environment variables for the full reference.
2

Build the image

docker build -t roots-ui .
To pass variables directly without a .env file, use --build-arg in combination with an ARG/ENV in the Dockerfile, or set them in your CI environment before building.
3

Run the container

docker run -p 80:80 roots-ui
The app is now available at http://localhost. To bind a different host port, change the first number: -p 8080:80.
4

Verify the deployment

Open http://localhost in a browser. You should see the Roots login screen.To check the container is running:
docker ps
To tail Nginx access logs:
docker logs -f <container_id>

Docker Compose deployment

The repository includes a docker-compose.yml for running the UI alongside the rest of the ATT platform:
docker-compose.yml
services:
  user-interface:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: att-user-interface
    develop:
      watch:
        - action: rebuild
          path: ./src
        - action: rebuild
          path: package.json

networks:
  att-orchestrator_att-network:
    external: true
The Compose file joins the external network att-orchestrator_att-network. This network is created by the ATT orchestrator stack. Start the orchestrator stack before bringing up the UI service.
1

Ensure the orchestrator network exists

docker network ls | grep att-orchestrator_att-network
If it is missing, start the orchestrator stack first.
2

Set environment variables

Create a .env file from the example:
cp .env.example .env
# Edit .env with your values
3

Start the service

docker-compose up -d
Docker Compose builds the image if it does not exist, then starts the container in the background.
4

Verify the deployment

docker-compose ps
docker-compose logs -f user-interface

Development watch mode

The Compose file includes a develop.watch configuration. When you run:
docker-compose watch
Docker automatically rebuilds the user-interface service whenever files under ./src or package.json change. This is intended for local development iteration, not production use.

Stopping and removing the container

docker stop <container_id>
docker rm <container_id>

Build docs developers (and LLMs) love