Skip to main content
Beat App comes with a complete Docker setup that uses a multi-stage build process to create an optimized production image served by NGINX.

Quick Start

The fastest way to deploy Beat App is using Docker Compose:
docker-compose up -d --build
This command will build the application and start it on port 3000.

Docker Architecture

The Docker setup uses a two-stage build process for optimal image size and performance:

Stage 1: Build

The first stage uses Node.js 22 Alpine to build the application:
FROM node:22-alpine AS builder

WORKDIR /app

# Install dependencies
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
RUN npm ci

# Build the app
COPY . .
RUN npm run build

Stage 2: Serve

The second stage uses NGINX to serve the built static files:
FROM nginx:stable-alpine AS runner

# Copy custom nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Copy built assets from the builder stage
COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 3000

CMD ["nginx", "-g", "daemon off;"]

Deployment Options

1

Using Docker Compose (Recommended)

Docker Compose simplifies the deployment process and manages environment variables:
services:
  beat-app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        VITE_API_URL: ${VITE_API_URL}
        VITE_YOUTUBE_API_TOKEN: ${VITE_YOUTUBE_API_TOKEN}
    ports:
      - "3000:3000"
    restart: unless-stopped
Deploy with:
docker-compose up -d --build
2

Using Docker CLI

For manual Docker deployments, build and run separately:
docker build \
  --build-arg VITE_API_URL=http://localhost:3000 \
  --build-arg VITE_YOUTUBE_API_TOKEN=your_token_here \
  -t beat-app .

Port Mapping

The default configuration maps the following ports:
3000
HTTP
Main application port. NGINX listens on port 3000 inside the container and is mapped to port 3000 on the host.
To use a different host port, modify the port mapping in docker-compose.yml:
ports:
  - "8080:3000"  # Maps host port 8080 to container port 3000

Volume Mounts

The default Docker setup does not use persistent volumes since Beat App is a static frontend application. All built assets are copied into the image during the build process.
Build-time environment variables are baked into the static bundle. If you need to change environment variables, you must rebuild the Docker image.

NGINX Configuration

The included NGINX configuration (nginx.conf) is optimized for serving the React SPA:
server {
    listen 80;
    server_name _;
    root /usr/share/nginx/html;
    index index.html;

    # Gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # SPA fallback — all routes go to index.html
    location / {
        try_files $uri $uri/ /index.html;
    }
}
Key features:
  • Gzip compression for faster asset delivery
  • 1-year caching for static assets (JS, CSS, images, fonts)
  • SPA routing support with fallback to index.html

Container Management

# Follow logs in real-time
docker-compose logs -f

# View last 100 lines
docker-compose logs --tail=100

Troubleshooting

Container won’t start

Check container logs:
docker-compose logs beat-app

Port already in use

If port 3000 is already in use, modify docker-compose.yml:
ports:
  - "3001:3000"  # Use port 3001 instead

Changes not reflecting

Rebuild the image to apply changes:
docker-compose down
docker-compose up -d --build
Environment variables are embedded during build time. Always rebuild after changing .env values.

Docker Ignore

The .dockerignore file excludes unnecessary files from the build context:
node_modules
dist
.git
.gitignore
.env
.env.local
.env.*.local
*.md
This reduces build time and image size by preventing these files from being copied to the Docker build context.

Build docs developers (and LLMs) love