Docker Deployment
Deploy Pentora using Docker containers for portable, reproducible, and scalable deployments.
Overview
Docker deployment is ideal for:
- Consistent environments across dev/staging/production
- Easy version management and rollback
- Container orchestration (Kubernetes, Docker Swarm)
- CI/CD pipeline integration
- Cloud-native deployments
- Development and testing
Quick Start
Pull and Run
# Pull official image
docker pull pentora/pentora:latest
# Run simple scan
docker run --rm pentora/pentora:latest scan 192.168.1.0/24
# Run with output
docker run --rm -v $(pwd):/output pentora/pentora:latest scan 192.168.1.100 -o /output/results.json
Interactive Mode
# Start interactive shell
docker run -it --rm pentora/pentora:latest /bin/bash
# Inside container
pentora scan 192.168.1.100
pentora workspace list
Docker Images
Official Images
Available on Docker Hub: pentora/pentora
Tags:
- latest- Latest stable release
- 1.0.0- Specific version
- 1.0- Minor version (auto-updates patches)
- 1- Major version (auto-updates minor/patches)
- edge- Development builds (unstable)
- alpine- Alpine-based lightweight image
- enterprise- Enterprise Edition (requires license)
# Pull specific version
docker pull pentora/pentora:1.0.0
# Pull Alpine variant
docker pull pentora/pentora:alpine
# Pull Enterprise Edition
docker pull pentora/pentora:enterprise
Image Variants
Standard Image (Debian-based)
FROM pentora/pentora:latest
# Size: ~150 MB
# Base: debian:bookworm-slim
# Includes: Full toolchain, debug tools
Alpine Image (Lightweight)
FROM pentora/pentora:alpine
# Size: ~50 MB
# Base: alpine:3.18
# Includes: Minimal runtime only
Enterprise Image
FROM pentora/pentora:enterprise
# Includes: Enterprise features, web UI, distributed scanning
Basic Usage
One-Time Scans
# Simple scan
docker run --rm pentora/pentora scan 192.168.1.100
# Scan with vulnerability assessment
docker run --rm pentora/pentora scan 192.168.1.100 --vuln
# Scan network range
docker run --rm pentora/pentora scan 192.168.1.0/24 --profile quick
# Discovery only
docker run --rm pentora/pentora scan 10.0.0.0/16 --only-discover
Persistent Workspace
# Create workspace directory
mkdir -p ~/pentora-workspace
# Run with workspace persistence
docker run --rm \
  -v ~/pentora-workspace:/workspace \
  -e PENTORA_WORKSPACE_DIR=/workspace \
  pentora/pentora scan 192.168.1.0/24
# List scans
docker run --rm \
  -v ~/pentora-workspace:/workspace \
  -e PENTORA_WORKSPACE_DIR=/workspace \
  pentora/pentora workspace list
# View specific scan
docker run --rm \
  -v ~/pentora-workspace:/workspace \
  -e PENTORA_WORKSPACE_DIR=/workspace \
  pentora/pentora workspace show <scan-id>
Configuration Files
# Create config directory
mkdir -p ~/pentora-config
# Create config file
cat > ~/pentora-config/config.yaml <<EOF
scanner:
  default_profile: standard
  rate: 2000
  concurrency: 200
logging:
  level: debug
  format: json
EOF
# Run with custom config
docker run --rm \
  -v ~/pentora-config:/config \
  -e PENTORA_CONFIG=/config/config.yaml \
  pentora/pentora scan 192.168.1.0/24
Docker Compose
Standalone Scanner
Create docker-compose.yml:
version: '3.8'
services:
  pentora:
    image: pentora/pentora:latest
    container_name: pentora
    volumes:
      - ./workspace:/workspace
      - ./config:/config
    environment:
      - PENTORA_WORKSPACE_DIR=/workspace
      - PENTORA_CONFIG=/config/config.yaml
      - PENTORA_LOG_LEVEL=info
    network_mode: host
    cap_add:
      - NET_RAW
      - NET_ADMIN
    command: ["scan", "192.168.1.0/24", "--profile", "standard"]
Run:
docker-compose up
Server Mode
Create docker-compose.yml:
version: '3.8'
services:
  pentora-server:
    image: pentora/pentora:latest
    container_name: pentora-server
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./workspace:/workspace
      - ./config:/config
      - ./logs:/logs
    environment:
      - PENTORA_WORKSPACE_DIR=/workspace
      - PENTORA_CONFIG=/config/config.yaml
      - PENTORA_LOG_LEVEL=info
    networks:
      - pentora-network
    cap_add:
      - NET_RAW
      - NET_ADMIN
    command: ["server", "start", "--bind", "0.0.0.0:8080"]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
networks:
  pentora-network:
    driver: bridge
Create configuration file config/config.yaml:
server:
  bind: 0.0.0.0:8080
  workers: 4
  api:
    enabled: true
    auth: true
  queue:
    max_jobs: 1000
workspace:
  dir: /workspace
  enabled: true
logging:
  level: info
  format: json
  file:
    enabled: true
    path: /logs/pentora.log
Start services:
# Start in background
docker-compose up -d
# View logs
docker-compose logs -f pentora-server
# Check status
docker-compose ps
# Stop services
docker-compose down
Complete Stack with Database (Enterprise)
Create docker-compose.yml:
version: '3.8'
services:
  postgres:
    image: postgres:15-alpine
    container_name: pentora-db
    restart: unless-stopped
    environment:
      - POSTGRES_DB=pentora
      - POSTGRES_USER=pentora
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - pentora-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U pentora"]
      interval: 10s
      timeout: 5s
      retries: 5
  redis:
    image: redis:7-alpine
    container_name: pentora-redis
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - pentora-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
  pentora:
    image: pentora/pentora:enterprise
    container_name: pentora-server
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      - "8080:8080"
      - "443:443"
    volumes:
      - ./workspace:/workspace
      - ./config:/config
      - ./logs:/logs
      - ./tls:/tls
    environment:
      - PENTORA_WORKSPACE_DIR=/workspace
      - PENTORA_CONFIG=/config/config.yaml
      - PENTORA_DB_HOST=postgres
      - PENTORA_DB_PORT=5432
      - PENTORA_DB_NAME=pentora
      - PENTORA_DB_USER=pentora
      - PENTORA_DB_PASSWORD=${DB_PASSWORD}
      - PENTORA_REDIS_HOST=redis
      - PENTORA_REDIS_PORT=6379
      - PENTORA_LICENSE_FILE=/config/license.key
    networks:
      - pentora-network
    cap_add:
      - NET_RAW
      - NET_ADMIN
    command: ["server", "start"]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
  nginx:
    image: nginx:alpine
    container_name: pentora-nginx
    restart: unless-stopped
    depends_on:
      - pentora
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./tls:/etc/nginx/tls:ro
    networks:
      - pentora-network
volumes:
  postgres-data:
  redis-data:
networks:
  pentora-network:
    driver: bridge
Create .env file:
DB_PASSWORD=changeme
Create nginx/nginx.conf:
events {
    worker_connections 1024;
}
http {
    upstream pentora {
        server pentora:8080;
    }
    server {
        listen 80;
        server_name pentora.company.com;
        return 301 https://$server_name$request_uri;
    }
    server {
        listen 443 ssl http2;
        server_name pentora.company.com;
        ssl_certificate /etc/nginx/tls/cert.pem;
        ssl_certificate_key /etc/nginx/tls/key.pem;
        location / {
            proxy_pass http://pentora;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        location /health {
            proxy_pass http://pentora;
            access_log off;
        }
    }
}
Start stack:
docker-compose up -d
Kubernetes Deployment
Simple Deployment
Create pentora-deployment.yaml:
apiVersion: v1
kind: Namespace
metadata:
  name: pentora
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: pentora-config
  namespace: pentora
data:
  config.yaml: |
    server:
      bind: 0.0.0.0:8080
      workers: 4
    workspace:
      dir: /workspace
      enabled: true
    logging:
      level: info
      format: json
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pentora-workspace
  namespace: pentora
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pentora-server
  namespace: pentora
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pentora
  template:
    metadata:
      labels:
        app: pentora
    spec:
      containers:
      - name: pentora
        image: pentora/pentora:latest
        imagePullPolicy: Always
        command: ["pentora", "server", "start"]
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: PENTORA_WORKSPACE_DIR
          value: /workspace
        - name: PENTORA_CONFIG
          value: /config/config.yaml
        volumeMounts:
        - name: workspace
          mountPath: /workspace
        - name: config
          mountPath: /config
        resources:
          requests:
            cpu: 500m
            memory: 2Gi
          limits:
            cpu: 2000m
            memory: 8Gi
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
        securityContext:
          capabilities:
            add:
            - NET_RAW
            - NET_ADMIN
      volumes:
      - name: workspace
        persistentVolumeClaim:
          claimName: pentora-workspace
      - name: config
        configMap:
          name: pentora-config
---
apiVersion: v1
kind: Service
metadata:
  name: pentora-service
  namespace: pentora
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: pentora
Deploy:
kubectl apply -f pentora-deployment.yaml
# Check status
kubectl -n pentora get pods
kubectl -n pentora get svc
# View logs
kubectl -n pentora logs -f deployment/pentora-server
# Access service
kubectl -n pentora port-forward service/pentora-service 8080:80
StatefulSet for HA
Create pentora-statefulset.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: pentora
  namespace: pentora
spec:
  serviceName: pentora
  replicas: 3
  selector:
    matchLabels:
      app: pentora
  template:
    metadata:
      labels:
        app: pentora
    spec:
      containers:
      - name: pentora
        image: pentora/pentora:enterprise
        command: ["pentora", "server", "start"]
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: PENTORA_WORKSPACE_DIR
          value: /workspace
        - name: PENTORA_REDIS_HOST
          value: redis-service
        volumeMounts:
        - name: workspace
          mountPath: /workspace
        resources:
          requests:
            cpu: 1000m
            memory: 4Gi
          limits:
            cpu: 4000m
            memory: 16Gi
  volumeClaimTemplates:
  - metadata:
      name: workspace
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 100Gi
Building Custom Images
Dockerfile
Create custom Dockerfile:
FROM pentora/pentora:latest
# Install additional tools
RUN apt-get update && apt-get install -y \
    nmap \
    masscan \
    jq \
    curl \
    && rm -rf /var/lib/apt/lists/*
# Copy custom configuration
COPY config/config.yaml /etc/pentora/config.yaml
# Copy custom fingerprints
COPY fingerprints/ /usr/share/pentora/fingerprints/
# Copy custom scripts
COPY scripts/ /usr/local/bin/
# Set default environment variables
ENV PENTORA_CONFIG=/etc/pentora/config.yaml
ENV PENTORA_WORKSPACE_DIR=/workspace
# Expose ports
EXPOSE 8080
# Default command
CMD ["pentora", "server", "start"]
Build and push:
# Build image
docker build -t mycompany/pentora:custom .
# Test locally
docker run --rm mycompany/pentora:custom version
# Push to registry
docker push mycompany/pentora:custom
Multi-Stage Build
Create optimized Dockerfile:
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /build
# Copy source
COPY . .
# Build binary
RUN go build -o pentora -ldflags="-s -w" ./cmd/pentora
# Runtime stage
FROM alpine:3.18
# Install runtime dependencies
RUN apk add --no-cache \
    ca-certificates \
    libcap \
    && rm -rf /var/cache/apk/*
# Copy binary from builder
COPY --from=builder /build/pentora /usr/local/bin/pentora
# Set capabilities
RUN setcap cap_net_raw,cap_net_admin+eip /usr/local/bin/pentora
# Create non-root user
RUN adduser -D -u 1000 pentora
# Create directories
RUN mkdir -p /workspace /config && \
    chown -R pentora:pentora /workspace /config
USER pentora
WORKDIR /workspace
EXPOSE 8080
CMD ["pentora", "server", "start"]
Build:
docker build -t mycompany/pentora:optimized .
Security Considerations
Network Mode
# Host network (full access)
docker run --network host pentora/pentora scan 192.168.1.0/24
# Bridge network (isolated)
docker run --network bridge pentora/pentora scan scanme.nmap.org
# Custom network
docker network create pentora-net
docker run --network pentora-net pentora/pentora scan targets
Capabilities
# Add required capabilities
docker run --cap-add NET_RAW --cap-add NET_ADMIN pentora/pentora scan 192.168.1.0/24
# Drop unnecessary capabilities
docker run --cap-drop ALL --cap-add NET_RAW pentora/pentora scan 192.168.1.0/24
# Run as non-root (if capabilities set in image)
docker run --user pentora pentora/pentora scan 192.168.1.0/24
Read-Only Filesystem
docker run --read-only \
  -v /tmp --tmpfs /tmp \
  -v $(pwd)/workspace:/workspace \
  pentora/pentora scan 192.168.1.0/24
Security Scanning
# Scan image for vulnerabilities
docker scan pentora/pentora:latest
# Use Trivy
trivy image pentora/pentora:latest
# Use Snyk
snyk container test pentora/pentora:latest
Performance Optimization
Resource Limits
# Set CPU and memory limits
docker run --cpus=2 --memory=4g pentora/pentora scan 192.168.1.0/24
# CPU shares
docker run --cpu-shares=512 pentora/pentora scan 192.168.1.0/24
# Memory reservation
docker run --memory=4g --memory-reservation=2g pentora/pentora scan 192.168.1.0/24
In Docker Compose:
services:
  pentora:
    image: pentora/pentora
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4G
        reservations:
          cpus: '0.5'
          memory: 1G
Volume Performance
# Use tmpfs for temporary data
docker run --tmpfs /tmp:rw,size=1g pentora/pentora scan 192.168.1.0/24
# Use volumes instead of bind mounts
docker volume create pentora-workspace
docker run -v pentora-workspace:/workspace pentora/pentora scan 192.168.1.0/24
Monitoring and Logging
Container Logs
# View logs
docker logs pentora-server
# Follow logs
docker logs -f pentora-server
# Last 100 lines
docker logs --tail 100 pentora-server
# Since timestamp
docker logs --since 2024-10-06T10:00:00 pentora-server
Log Drivers
# JSON file (default)
docker run --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  pentora/pentora server start
# Syslog
docker run --log-driver syslog \
  --log-opt syslog-address=udp://logs.company.com:514 \
  pentora/pentora server start
# Fluentd
docker run --log-driver fluentd \
  --log-opt fluentd-address=localhost:24224 \
  pentora/pentora server start
Health Checks
# Add health check
docker run --health-cmd="curl -f http://localhost:8080/health || exit 1" \
  --health-interval=30s \
  --health-timeout=10s \
  --health-retries=3 \
  pentora/pentora server start
# Check health status
docker inspect --format='{{.State.Health.Status}}' pentora-server
CI/CD Integration
GitHub Actions
name: Security Scan with Pentora
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - name: Run Pentora Scan
        run: |
          docker run --rm \
            -v $(pwd):/output \
            pentora/pentora:latest \
            scan ${{ secrets.SCAN_TARGETS }} \
            -o /output/results.json
      - name: Upload Results
        uses: actions/upload-artifact@v3
        with:
          name: scan-results
          path: results.json
GitLab CI
pentora_scan:
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker pull pentora/pentora:latest
    - docker run --rm pentora/pentora scan $SCAN_TARGETS -o results.json
  artifacts:
    paths:
      - results.json
Troubleshooting
Permission Denied
# Add capabilities
docker run --cap-add NET_RAW --cap-add NET_ADMIN pentora/pentora scan 192.168.1.0/24
# Run as root
docker run --user root pentora/pentora scan 192.168.1.0/24
Network Not Reachable
# Use host network
docker run --network host pentora/pentora scan 192.168.1.0/24
# Check network connectivity
docker run --rm pentora/pentora ping 192.168.1.1
Container Crashes
# Check logs
docker logs pentora-server
# Inspect container
docker inspect pentora-server
# Check resource limits
docker stats pentora-server
Next Steps
- Standalone Deployment - CLI deployment
- Server Mode Deployment - Systemd service
- Air-Gapped Deployment - Offline deployment
- Enterprise Features - Scale and features