Skip to main content

Overview

VulnTrack can be deployed using Docker for consistent, isolated environments. This guide covers both standalone Docker deployment and Docker Compose for running the full stack including PostgreSQL.

Prerequisites

  • Docker 20.10 or higher
  • Docker Compose 2.0 or higher (for multi-container setup)
  • At least 2GB RAM available
  • PostgreSQL 15 or higher (if running separately)

Docker Compose Setup

The recommended approach for local and development deployments.
1

Create docker-compose.yml

The repository includes a docker-compose.yml that sets up PostgreSQL:
docker-compose.yml
version: '3.8'
services:
  postgres:
    image: postgres:15-alpine
    container_name: vulntrack-db
    environment:
      POSTGRES_USER: vulntrack
      POSTGRES_PASSWORD: vulntrackpassword
      POSTGRES_DB: vulntrack
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
2

Configure environment variables

Create a .env file in your project root:
.env
# Database
DATABASE_URL="postgresql://vulntrack:vulntrackpassword@localhost:5432/vulntrack"

# NextAuth Configuration
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key-here-change-in-production"

# Application
NODE_ENV="production"
PORT=3000
Always change the default database password and generate a secure NEXTAUTH_SECRET for production deployments.
3

Start the database

docker-compose up -d
Verify the database is running:
docker ps
4

Build and run the application

Build the Docker image:
docker build -t vulntrack:latest .
Run the container:
docker run -d \
  --name vulntrack-app \
  -p 3000:3000 \
  --env-file .env \
  vulntrack:latest
5

Verify deployment

Check container logs:
docker logs vulntrack-app
Access the application at http://localhost:3000

Dockerfile Configuration

VulnTrack uses a multi-stage Docker build for optimized image size:
Dockerfile
FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# Production image
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production

# Don't run as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Leverage output traces to reduce image size
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs
EXPOSE 3000
ENV PORT 3000

CMD ["node", "server.js"]

Build Stages

Installs Node.js dependencies using npm ci for reproducible builds. Includes libc6-compat for Alpine Linux compatibility.
Runs the build script which:
  • Generates Prisma Client
  • Pushes database schema (use migrations in production)
  • Builds Next.js application with standalone output
Creates minimal production image:
  • Runs as non-root user (nextjs:1001)
  • Only includes necessary runtime files
  • Uses Next.js standalone output for reduced size

Complete Docker Compose Stack

For a production-like environment with the application and database:
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: vulntrack-db
    environment:
      POSTGRES_USER: vulntrack
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: vulntrack
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U vulntrack"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - vulntrack-network

  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: vulntrack-app
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      - DATABASE_URL=postgresql://vulntrack:${DB_PASSWORD}@postgres:5432/vulntrack
      - NEXTAUTH_URL=${NEXTAUTH_URL}
      - NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
      - NODE_ENV=production
    ports:
      - "3000:3000"
    networks:
      - vulntrack-network
    restart: unless-stopped

volumes:
  postgres_data:

networks:
  vulntrack-network:
    driver: bridge
Use docker-compose up -d to start all services in detached mode. The app will wait for PostgreSQL to be healthy before starting.

Volume Management

Persistent Data

The PostgreSQL data is stored in a named volume:
# List volumes
docker volume ls

# Inspect volume
docker volume inspect postgres_data

# Backup database
docker exec vulntrack-db pg_dump -U vulntrack vulntrack > backup.sql

Database Backups

docker exec vulntrack-db pg_dump \
  -U vulntrack \
  -F c \
  vulntrack > backup_$(date +%Y%m%d_%H%M%S).dump

Environment Variables

VariableRequiredDescriptionExample
DATABASE_URLYesPostgreSQL connection stringpostgresql://user:pass@host:5432/db
NEXTAUTH_URLYesApplication base URLhttps://vulntrack.example.com
NEXTAUTH_SECRETYesSecret for JWT signingRandom 32+ character string
NODE_ENVNoNode environmentproduction
PORTNoApplication port3000 (default)
Never commit .env files with actual secrets to version control. Use .env.example as a template.

Container Management

Common Commands

# View logs
docker logs -f vulntrack-app

# Access container shell
docker exec -it vulntrack-app sh

# Restart container
docker restart vulntrack-app

# Stop and remove
docker-compose down

# Stop and remove with volumes
docker-compose down -v

Health Checks

Add health checks to your docker-compose.yml:
app:
  # ... other config
  healthcheck:
    test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
    interval: 30s
    timeout: 10s
    retries: 3
    start_period: 40s

Resource Limits

Set resource limits for production:
docker-compose.yml
services:
  app:
    # ... other config
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M
  
  postgres:
    # ... other config
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G

Troubleshooting

Container Won’t Start

  1. Check logs: docker logs vulntrack-app
  2. Verify environment variables: docker exec vulntrack-app env
  3. Ensure database is accessible: docker exec vulntrack-app nc -zv postgres 5432

Database Connection Issues

# Test database connection from app container
docker exec vulntrack-app sh -c 'apk add postgresql-client && psql $DATABASE_URL -c "SELECT 1"'

Permission Denied Errors

Ensure the nextjs user has proper permissions:
docker exec -u root vulntrack-app chown -R nextjs:nodejs /app/.next
For production deployments, see the Production Deployment guide for scaling and performance optimization.

Next Steps

Production Deployment

Learn about production-ready configurations

Security Hardening

Secure your deployment

Build docs developers (and LLMs) love