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
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
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:
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
View Logs
Stop Container
Restart Container
Rebuild
# 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.