Skip to content

Docker Deployment

Complete guide for deploying TrojanHorse.js in containerized environments using Docker.

Overview

TrojanHorse.js provides production-ready Docker images for various deployment scenarios, from development to enterprise-scale deployments.

graph TB
    A[Source Code] --> B[Multi-stage Build]
    B --> C[Base Images]

    C --> D1[Alpine Linux]
    C --> D2[Ubuntu LTS]
    C --> D3[Distroless]

    D1 --> E1[Development Image]
    D2 --> E2[Production Image]
    D3 --> E3[Security-hardened Image]

    E1 --> F[Docker Registry]
    E2 --> F
    E3 --> F

    F --> G[Deployment]

Docker Images

Available Images

Image Base Size Use Case
trojanhorse/core:latest Alpine Linux ~150MB Development, testing
trojanhorse/production:latest Ubuntu LTS ~200MB Production deployments
trojanhorse/enterprise:latest Ubuntu LTS ~250MB Enterprise features
trojanhorse/minimal:latest Distroless ~80MB Security-critical environments

Quick Start

# Pull and run the latest image
docker pull trojanhorse/core:latest

# Run with basic configuration
docker run -d \
  --name trojanhorse \
  -p 3000:3000 \
  -e TROJANHORSE_MODE=production \
  trojanhorse/core:latest

# Run with custom configuration
docker run -d \
  --name trojanhorse \
  -p 3000:3000 \
  -v $(pwd)/config:/app/config \
  -v $(pwd)/data:/app/data \
  trojanhorse/core:latest

Building Custom Images

Multi-stage Dockerfile

# Stage 1: Dependencies and build
FROM node:20-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./
COPY tsconfig.json ./

# Install dependencies
RUN npm ci --only=production && \
    npm cache clean --force

# Copy source code
COPY src/ ./src/
COPY rollup.config.js ./

# Build application
RUN npm run build:all

# Stage 2: Production image
FROM node:20-alpine AS production

# Create non-root user
RUN addgroup -g 1001 -S trojanhorse && \
    adduser -S trojanhorse -u 1001

# Set working directory
WORKDIR /app

# Copy built application
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

# Copy configuration templates
COPY docker/config/ ./config/
COPY docker/scripts/ ./scripts/

# Set permissions
RUN chown -R trojanhorse:trojanhorse /app

# Switch to non-root user
USER trojanhorse

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node scripts/healthcheck.js

# Expose ports
EXPOSE 3000 9090

# Default command
CMD ["node", "dist/index.js"]

Enterprise Dockerfile

FROM ubuntu:22.04 AS enterprise

# Install system dependencies
RUN apt-get update && apt-get install -y \
    curl \
    ca-certificates \
    gnupg \
    lsb-release \
    && rm -rf /var/lib/apt/lists/*

# Install Node.js
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
    apt-get install -y nodejs

# Install security tools
RUN apt-get update && apt-get install -y \
    clamav \
    fail2ban \
    logrotate \
    && rm -rf /var/lib/apt/lists/*

# Create application user
RUN groupadd -r trojanhorse && \
    useradd -r -g trojanhorse -s /bin/false trojanhorse

WORKDIR /app

# Copy application
COPY --chown=trojanhorse:trojanhorse dist/ ./dist/
COPY --chown=trojanhorse:trojanhorse node_modules/ ./node_modules/
COPY --chown=trojanhorse:trojanhorse package.json ./

# Copy enterprise configurations
COPY --chown=trojanhorse:trojanhorse docker/enterprise/ ./enterprise/

# Security hardening
RUN chmod -R 755 /app && \
    chmod -R 644 /app/dist && \
    chmod +x /app/dist/index.js

USER trojanhorse

EXPOSE 3000 8080 9090

CMD ["node", "dist/index.js", "--mode=enterprise"]

Docker Compose Configurations

Development Setup

# docker-compose.dev.yml
version: '3.8'

services:
  trojanhorse:
    build:
      context: .
      dockerfile: Dockerfile
      target: development
    ports:
      - "3000:3000"
      - "9090:9090"
    environment:
      - NODE_ENV=development
      - TROJANHORSE_MODE=development
      - LOG_LEVEL=debug
    volumes:
      - ./src:/app/src
      - ./config:/app/config
      - ./data:/app/data
    depends_on:
      - redis
      - mongodb
    networks:
      - trojanhorse-dev

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - trojanhorse-dev

  mongodb:
    image: mongo:7
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
    volumes:
      - mongodb_data:/data/db
    networks:
      - trojanhorse-dev

volumes:
  redis_data:
  mongodb_data:

networks:
  trojanhorse-dev:
    driver: bridge

Production Setup

# docker-compose.prod.yml
version: '3.8'

services:
  trojanhorse:
    image: trojanhorse/production:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - TROJANHORSE_MODE=production
      - REDIS_URL=redis://redis:6379
      - MONGODB_URL=mongodb://mongodb:27017/trojanhorse
    volumes:
      - ./config/production:/app/config:ro
      - logs:/app/logs
      - data:/app/data
    depends_on:
      - redis
      - mongodb
      - nginx
    networks:
      - trojanhorse-prod
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
    depends_on:
      - trojanhorse
    networks:
      - trojanhorse-prod

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - trojanhorse-prod
    deploy:
      resources:
        limits:
          memory: 512M

  mongodb:
    image: mongo:7
    restart: unless-stopped
    environment:
      - MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/mongo_root_username
      - MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_root_password
    volumes:
      - mongodb_data:/data/db
      - ./mongodb/mongod.conf:/etc/mongod.conf:ro
    secrets:
      - mongo_root_username
      - mongo_root_password
    networks:
      - trojanhorse-prod

secrets:
  mongo_root_username:
    external: true
  mongo_root_password:
    external: true

volumes:
  redis_data:
  mongodb_data:
  logs:
  data:

networks:
  trojanhorse-prod:
    driver: overlay
    encrypted: true

Enterprise Cluster Setup

# docker-compose.enterprise.yml
version: '3.8'

services:
  trojanhorse-api:
    image: trojanhorse/enterprise:latest
    restart: unless-stopped
    environment:
      - TROJANHORSE_MODE=api
      - CLUSTER_ROLE=api
    volumes:
      - ./config/enterprise:/app/config:ro
    networks:
      - trojanhorse-enterprise
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.labels.type == api

  trojanhorse-worker:
    image: trojanhorse/enterprise:latest
    restart: unless-stopped
    environment:
      - TROJANHORSE_MODE=worker
      - CLUSTER_ROLE=worker
    volumes:
      - ./config/enterprise:/app/config:ro
    networks:
      - trojanhorse-enterprise
    deploy:
      replicas: 5
      placement:
        constraints:
          - node.labels.type == worker

  trojanhorse-coordinator:
    image: trojanhorse/enterprise:latest
    restart: unless-stopped
    environment:
      - TROJANHORSE_MODE=coordinator
      - CLUSTER_ROLE=coordinator
    volumes:
      - ./config/enterprise:/app/config:ro
    networks:
      - trojanhorse-enterprise
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.labels.type == coordinator

  load-balancer:
    image: haproxy:2.8
    ports:
      - "80:80"
      - "443:443"
      - "8404:8404"
    volumes:
      - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    networks:
      - trojanhorse-enterprise
    deploy:
      replicas: 2
      placement:
        constraints:
          - node.labels.type == lb

networks:
  trojanhorse-enterprise:
    driver: overlay
    encrypted: true

Configuration Management

Environment Variables

# Core configuration
TROJANHORSE_MODE=production
NODE_ENV=production
LOG_LEVEL=info

# Database connections
REDIS_URL=redis://redis:6379/0
MONGODB_URL=mongodb://mongodb:27017/trojanhorse
POSTGRES_URL=postgresql://user:pass@postgres:5432/trojanhorse

# Security
JWT_SECRET_FILE=/run/secrets/jwt_secret
API_KEY_ENCRYPTION_KEY_FILE=/run/secrets/api_encryption_key
SESSION_SECRET_FILE=/run/secrets/session_secret

# External APIs
URLHAUS_API_KEY_FILE=/run/secrets/urlhaus_key
VIRUSTOTAL_API_KEY_FILE=/run/secrets/virustotal_key
ALIENVAULT_API_KEY_FILE=/run/secrets/alienvault_key

# Performance
MAX_WORKERS=4
CACHE_TTL=3600
REQUEST_TIMEOUT=30000

# Monitoring
PROMETHEUS_ENABLED=true
PROMETHEUS_PORT=9090
HEALTH_CHECK_ENABLED=true

Configuration Files

# config/docker.yml
server:
  host: 0.0.0.0
  port: 3000

database:
  redis:
    url: ${REDIS_URL}
    maxConnections: 10

  mongodb:
    url: ${MONGODB_URL}
    options:
      maxPoolSize: 20
      serverSelectionTimeoutMS: 5000

security:
  encryption:
    keyFile: ${API_KEY_ENCRYPTION_KEY_FILE}

  authentication:
    jwtSecret: ${JWT_SECRET_FILE}
    sessionSecret: ${SESSION_SECRET_FILE}

feeds:
  urlhaus:
    apiKey: ${URLHAUS_API_KEY_FILE}
    enabled: true

  virustotal:
    apiKey: ${VIRUSTOTAL_API_KEY_FILE}
    enabled: true

monitoring:
  prometheus:
    enabled: ${PROMETHEUS_ENABLED}
    port: ${PROMETHEUS_PORT}

  health:
    enabled: ${HEALTH_CHECK_ENABLED}
    interval: 30000

Security Best Practices

Container Security

# Security-hardened Dockerfile
FROM node:20-alpine AS security-hardened

# Install security updates
RUN apk update && apk upgrade && \
    apk add --no-cache dumb-init && \
    rm -rf /var/cache/apk/*

# Create non-root user with no shell
RUN addgroup -g 1001 -S trojanhorse && \
    adduser -S trojanhorse -u 1001 -G trojanhorse -s /sbin/nologin

# Set up application directory
WORKDIR /app

# Copy application with proper ownership
COPY --chown=trojanhorse:trojanhorse dist/ ./dist/
COPY --chown=trojanhorse:trojanhorse node_modules/ ./node_modules/

# Remove unnecessary packages and files
RUN apk del curl wget && \
    rm -rf /tmp/* /var/tmp/* && \
    find /app -name "*.md" -delete && \
    find /app -name "test*" -delete

# Set strict permissions
RUN chmod -R 755 /app && \
    chmod -R 644 /app/dist && \
    chmod +x /app/dist/index.js

# Switch to non-root user
USER trojanhorse

# Use dumb-init for proper signal handling
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["node", "dist/index.js"]

Secret Management

# docker-compose.secrets.yml
version: '3.8'

services:
  trojanhorse:
    image: trojanhorse/production:latest
    secrets:
      - jwt_secret
      - api_encryption_key
      - urlhaus_api_key
      - virustotal_api_key
    environment:
      - JWT_SECRET_FILE=/run/secrets/jwt_secret
      - API_KEY_ENCRYPTION_KEY_FILE=/run/secrets/api_encryption_key
      - URLHAUS_API_KEY_FILE=/run/secrets/urlhaus_api_key
      - VIRUSTOTAL_API_KEY_FILE=/run/secrets/virustotal_api_key

secrets:
  jwt_secret:
    external: true
  api_encryption_key:
    external: true
  urlhaus_api_key:
    external: true
  virustotal_api_key:
    external: true
# Create Docker secrets
echo "your-jwt-secret" | docker secret create jwt_secret -
echo "your-encryption-key" | docker secret create api_encryption_key -
echo "your-urlhaus-key" | docker secret create urlhaus_api_key -
echo "your-virustotal-key" | docker secret create virustotal_api_key -

Monitoring and Logging

Container Monitoring

# docker-compose.monitoring.yml
version: '3.8'

services:
  trojanhorse:
    image: trojanhorse/production:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    labels:
      - "prometheus.io/scrape=true"
      - "prometheus.io/port=9090"
      - "prometheus.io/path=/metrics"

  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./grafana/datasources:/etc/grafana/provisioning/datasources

volumes:
  prometheus_data:
  grafana_data:

Health Checks

// scripts/healthcheck.js
const http = require('http');

const options = {
  hostname: 'localhost',
  port: 3000,
  path: '/health',
  timeout: 2000
};

const request = http.request(options, (res) => {
  if (res.statusCode === 200) {
    process.exit(0);
  } else {
    process.exit(1);
  }
});

request.on('error', () => {
  process.exit(1);
});

request.on('timeout', () => {
  request.abort();
  process.exit(1);
});

request.end();

Deployment Strategies

Rolling Updates

#!/bin/bash
# rolling-update.sh

SERVICE_NAME="trojanhorse_trojanhorse"
NEW_IMAGE="trojanhorse/production:latest"

echo "Starting rolling update..."

# Pull new image
docker pull $NEW_IMAGE

# Update service with rolling update
docker service update \
  --image $NEW_IMAGE \
  --update-parallelism 1 \
  --update-delay 30s \
  --update-failure-action rollback \
  --rollback-parallelism 1 \
  --rollback-delay 10s \
  $SERVICE_NAME

echo "Rolling update completed"

# Monitor deployment
docker service ps $SERVICE_NAME

Blue-Green Deployment

#!/bin/bash
# blue-green-deploy.sh

CURRENT_ENV=$(docker service ls --filter name=trojanhorse --format "{{.Name}}" | grep -o "blue\|green")
NEW_ENV="blue"

if [ "$CURRENT_ENV" = "blue" ]; then
  NEW_ENV="green"
fi

echo "Deploying to $NEW_ENV environment..."

# Deploy to new environment
docker stack deploy -c docker-compose.$NEW_ENV.yml trojanhorse-$NEW_ENV

# Wait for health check
sleep 30

# Switch traffic
docker service update \
  --publish-add 80:3000 \
  --publish-rm 80:3000 \
  trojanhorse-$NEW_ENV_trojanhorse

# Remove old environment
docker stack rm trojanhorse-$CURRENT_ENV

echo "Blue-green deployment completed"

Troubleshooting

Common Issues

Container Won't Start

# Check container logs
docker logs trojanhorse

# Check container configuration
docker inspect trojanhorse

# Verify environment variables
docker exec trojanhorse env

Memory Issues

# Monitor memory usage
docker stats trojanhorse

# Increase memory limits
docker update --memory 2g trojanhorse

Network Connectivity

# Test network connectivity
docker exec trojanhorse ping redis
docker exec trojanhorse telnet mongodb 27017

Performance Issues

# Profile application
docker exec trojanhorse node --prof dist/index.js

# Monitor resource usage
docker exec trojanhorse top
docker exec trojanhorse iostat


Next Steps: Explore Kubernetes Deployment for container orchestration or check Production Deployment for additional deployment strategies.