Docker Deployment
Deploy with containers for maximum portability
Docker is the recommended deployment method for ATStatus. It provides a consistent, isolated environment that works the same way everywhere - from your local machine to cloud providers.
Why Docker?
Isolated Environment
Run ATStatus in a completely isolated container with no dependency conflicts
Easy Deployment
Deploy anywhere Docker runs - cloud, VPS, or local server
Scalability
Scale horizontally with Docker Swarm or Kubernetes
Persistent Data
Use volumes to persist your database and configurations
Deployment Steps
Create Dockerfile
Create a multi-stage Dockerfile for optimized production builds
Configure Environment
Set up environment variables for your deployment
Build Image
Build the Docker image with your configuration
Run Container
Start the container with volume mounts for data persistence
Dockerfile
FROM node:18-alpine AS base
# Install dependencies
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
# Build
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate
RUN npm run build
# Production
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder /app/prisma ./prisma
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]Docker Compose
version: '3.8'
services:
atstatus:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=file:./data/prod.db
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- SESSION_SECRET=${SESSION_SECRET}
- CRON_SECRET=${CRON_SECRET}
volumes:
- ./data:/app/data
restart: unless-stoppedWith PostgreSQL
For production deployments, use PostgreSQL for better performance and reliability:
version: '3.8'
services:
atstatus:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://atstatus:password@postgres:5432/atstatus
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- SESSION_SECRET=${SESSION_SECRET}
- CRON_SECRET=${CRON_SECRET}
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=atstatus
- POSTGRES_PASSWORD=password
- POSTGRES_DB=atstatus
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U atstatus"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
postgres_data:Quick Commands
- Build: docker build -t atstatus .
- Run: docker run -d -p 3000:3000 atstatus
- Logs: docker logs -f atstatus
- Shell: docker exec -it atstatus sh
Build & Run
# Build the image
docker build -t atstatus .
# Run with Docker
docker run -d \
-p 3000:3000 \
-e DATABASE_URL="file:./data/prod.db" \
-e ADMIN_PASSWORD="your-secure-password" \
-e SESSION_SECRET="your-session-secret-min-32-chars" \
-e CRON_SECRET="your-cron-secret" \
-v $(pwd)/data:/app/data \
--name atstatus \
atstatus
# Or with Docker Compose
docker compose up -d/app/data to persist your SQLite database. Without this, your data will be lost when the container restarts.