The classic approach. Run your app on a VPS (DigitalOcean, Hetzner, AWS EC2) or any container platform (Fly.io, Railway, ECS).
# Build with Docker support
npx alepha build --docker
# Build the image
docker build -t my-app ./dist
# Run it
docker run -p 3000:3000 -e NODE_ENV=production -e DATABASE_URL=postgres://... -e APP_SECRET=your-secret-key my-app
The generated Dockerfile is lean. We prune node_modules to production dependencies only, so your image stays small.
dist/
├── index.js # Your compiled server
├── public/ # Static assets (CSS, JS, images)
├── Dockerfile # Ready-to-build Docker image
└── package.json # Production dependencies only
1version: "3.8" 2 3services: 4 app: 5 build: ./dist 6 ports: 7 - "3000:3000" 8 environment: 9 - NODE_ENV=production10 - DATABASE_URL=postgres://postgres:postgres@db:5432/app11 - APP_SECRET=${APP_SECRET}12 depends_on:13 - db14 15 db:16 image: postgres:16-alpine17 volumes:18 - postgres_data:/var/lib/postgresql/data19 environment:20 - POSTGRES_DB=app21 - POSTGRES_PASSWORD=postgres22 23volumes:24 postgres_data:
Add health checks to your Docker configuration:
1services:2 app:3 # ...4 healthcheck:5 test: ["CMD", "curl", "-f", "http://localhost:3000/health"]6 interval: 30s7 timeout: 10s8 retries: 39 start_period: 40s
This requires AlephaServerHealth module to be enabled in your app.
# Install flyctl
curl -L https://fly.io/install.sh | sh
# Launch (first time)
cd dist && fly launch
# Deploy (subsequent)
npx alepha build --docker && cd dist && fly deploy
# Install Railway CLI
npm install -g @railway/cli
# Deploy
npx alepha build --docker
cd dist && railway up
npx alepha build --docker
docker build -t my-app ./dist
aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URL
docker tag my-app:latest $ECR_URL/my-app:latest
docker push $ECR_URL/my-app:latest
The generated Dockerfile already uses multi-stage builds. If you need to customize:
# Build stage
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn build
# Production stage
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./
RUN npm prune --production
EXPOSE 3000
CMD ["node", "index.js"]
node:22-alpine).dockerignore to exclude unnecessary filesnode_modules
.git
*.md
test
coverage