Skip to main content

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