Docker Deployment

Containerize your Nixi application with Docker for consistent deployments across environments. This guide covers Dockerfiles, Docker Compose, multi-stage builds, and Kubernetes.

Dockerfile Examples

Basic Dockerfile

# Dockerfile
FROM lua:5.4

WORKDIR /app

RUN luarocks install luasocket && luarocks install luafilesystem

COPY src/ ./src/
COPY server.lua ./

EXPOSE 3000

ENV LUA_PATH="/app/src/?.lua;;"
ENV PORT=3000

CMD ["lua", "server.lua"]

Multi-Stage Build

Multi-stage builds reduce the final image size by separating build and runtime stages:

# Build stage
FROM lua:5.4 AS builder

WORKDIR /build

RUN luarocks install luasocket && luarocks install luafilesystem

COPY src/ ./src/

# Production stage
FROM lua:5.4-slim

WORKDIR /app

COPY --from=builder /usr/local/share/lua /usr/local/share/lua
COPY --from=builder /usr/local/lib/lua /usr/local/lib/lua

COPY src/ ./src/
COPY server.lua ./

RUN useradd -m -u 1000 nixi && chown -R nixi:nixi /app

USER nixi

EXPOSE 3000

ENV LUA_PATH="/app/src/?.lua;;"
ENV PORT=3000
ENV NIXI_ENV=production

HEALTHCHECK --interval=30s --timeout=3s CMD lua -e "require('socket').connect('127.0.0.1', 3000)"

CMD ["lua", "server.lua"]

Alpine-Based Dockerfile

FROM alpine:3.19 AS builder

RUN apk add --no-cache lua5.4 lua5.4-dev luarocks lua5.4-libs

WORKDIR /build

RUN luarocks install luasocket && luarocks install luafilesystem

COPY src/ ./src/

FROM alpine:3.19

RUN apk add --no-cache lua5.4 lua5.4-libs

WORKDIR /app

COPY --from=builder /usr/local/share/lua /usr/local/share/lua
COPY --from=builder /usr/local/lib/lua /usr/local/lib/lua

COPY src/ ./src/
COPY server.lua ./

RUN addgroup -S nixi && adduser -S nixi -G nixi && chown -R nixi:nixi /app

USER nixi

EXPOSE 3000

ENV LUA_PATH="/app/src/?.lua;;"
ENV PORT=3000

CMD ["lua", "server.lua"]

Docker Compose

Basic Docker Compose

# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - PORT=3000
      - HOST=0.0.0.0
      - NIXI_ENV=production
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "lua", "-e", "require('socket').connect('127.0.0.1', 3000)"]
      interval: 30s
      timeout: 3s
      retries: 3

Development Configuration

# docker-compose.yml
version: '3.8'

services:
  app:
    build:
      context: .
      target: development
    ports:
      - "3000:3000"
    volumes:
      - ./src:/app/src
      - ./server.lua:/app/server.lua
    environment:
      - PORT=3000
      - DEBUG=true
    command: lua -e "package.path = './src/?.lua;' .. package.path" server.lua

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - app

Production Stack with Redis

# docker-compose.yml
version: '3.8'

services:
  app:
    build:
      context: .
      target: production
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      - PORT=3000
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - NIXI_ENV=production
    depends_on:
      redis:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
        reservations:
          cpus: '0.1'
          memory: 64M

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - app
    restart: unless-stopped

volumes:
  redis_data:

Kubernetes Deployment

Deployment Manifest

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nixi-app
  labels:
    app: nixi-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nixi-app
  template:
    metadata:
      labels:
        app: nixi-app
    spec:
      containers:
        - name: app
          image: yourregistry/nixi-app:latest
          ports:
            - containerPort: 3000
          env:
            - name: PORT
              value: "3000"
            - name: HOST
              value: "0.0.0.0"
            - name: NIXI_ENV
              value: "production"
          resources:
            requests:
              memory: "64Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "500m"
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 30
            timeoutSeconds: 3
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
            timeoutSeconds: 3

Service Manifest

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nixi-app-service
spec:
  type: ClusterIP
  selector:
    app: nixi-app
  ports:
    - port: 80
      targetPort: 3000

Ingress Configuration

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nixi-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
spec:
  ingressClassName: nginx
  rules:
    - host: yourdomain.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nixi-app-service
                port:
                  number: 80
  tls:
    - hosts:
        - yourdomain.com
      secretName: nixi-tls-secret

Horizontal Pod Autoscaler

# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nixi-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nixi-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

ConfigMap and Secrets

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nixi-config
data:
  LUA_PATH: "/app/src/?.lua;;"
  PORT: "3000"
  HOST: "0.0.0.0"
  NIXI_ENV: "production"
# deployment with config
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nixi-app
spec:
  template:
    spec:
      containers:
        - name: app
          image: yourregistry/nixi-app:latest
          envFrom:
            - configMapRef:
                name: nixi-config

Building and Running

# Build the image
docker build -t nixi-app:latest .

# Run with Docker
docker run -d -p 3000:3000 --name nixi-app nixi-app:latest

# Run with Docker Compose
docker-compose up -d

# View logs
docker logs -f nixi-app

# Execute commands in container
docker exec -it nixi-app lua -v

Image Registry

# Tag for registry
docker tag nixi-app:latest yourregistry.io/nixi-app:v1.0.0

# Push to registry
docker push yourregistry.io/nixi-app:v1.0.0

# Pull from registry
docker pull yourregistry.io/nixi-app:v1.0.0