Docker Usage Guide

Docker Usage Guide

The following files were used as context for generating this wiki page:

Purpose and Scope

This document provides a comprehensive reference for using WSHawk's Docker containers in production and development environments. It covers basic container execution, volume mounting for report persistence, environment variable configuration, network setup, and docker-compose orchestration.

For information about Docker image distribution and registries, see Docker Images and Registries. For integrating WSHawk containers into CI/CD pipelines, see CI/CD Integration. For Kubernetes deployments, see Kubernetes Deployment. For using the web dashboard within containers, see Web Management Dashboard.


Container Architecture

WSHawk containers are built using a multi-stage Dockerfile process with production-grade security and optimization features.

Container Image Specification

graph TB
    subgraph "Base Images"
        Builder["python:3.11-slim<br/>(builder stage)"]
        Runtime["python:3.11-slim<br/>(final stage)"]
    end
    
    subgraph "Build Artifacts"
        WheelPkg["WSHawk Package<br/>/usr/local/lib/python3.11/site-packages"]
        Entrypoints["CLI Binaries<br/>/usr/local/bin/wshawk*"]
    end
    
    subgraph "Entrypoints"
        WshawkCLI["wshawk<br/>(default ENTRYPOINT)"]
        WshawkInteractive["wshawk-interactive"]
        WshawkAdvanced["wshawk-advanced"]
        WshawkDefensive["wshawk-defensive"]
    end
    
    subgraph "Runtime Environment"
        NonRoot["User: wshawk:1000<br/>(non-root)"]
        WorkDir["WORKDIR: /app"]
        EnvVars["PYTHONUNBUFFERED=1<br/>PYTHONDONTWRITEBYTECODE=1"]
    end
    
    subgraph "Volume Mounts (Optional)"
        Reports["/app/reports<br/>(scan reports)"]
        Database["/app/scans.db<br/>(SQLite persistence)"]
        Config["/app/wshawk.yaml<br/>(configuration)"]
        Plugins["/app/plugins<br/>(custom plugins)"]
    end
    
    Builder --> WheelPkg
    Builder --> Entrypoints
    
    WheelPkg --> Runtime
    Entrypoints --> Runtime
    
    Runtime --> WshawkCLI
    Runtime --> WshawkInteractive
    Runtime --> WshawkAdvanced
    Runtime --> WshawkDefensive
    
    Runtime --> NonRoot
    Runtime --> WorkDir
    Runtime --> EnvVars
    
    WshawkCLI -.-> Reports
    WshawkCLI -.-> Database
    WshawkCLI -.-> Config
    WshawkCLI -.-> Plugins

Sources: Dockerfile:1-66

Multi-Stage Build Process

The container build follows a two-stage optimization pattern defined in Dockerfile:4-53:

| Stage | Base Image | Purpose | Size Impact | |-------|-----------|---------|-------------| | builder | python:3.11-slim | Compile dependencies with gcc | ~300MB (discarded) | | final | python:3.11-slim | Runtime environment only | ~150MB (final) |

The builder stage installs gcc Dockerfile:10-12 to compile native extensions, then the final stage copies only the compiled packages Dockerfile:34-35 without build tools, reducing image size by ~50%.

Sources: Dockerfile:4-53


Basic Container Usage

Pulling Images

WSHawk images are available from two registries, as defined in .github/workflows/docker-build.yml:15-16:

# Docker Hub (public)
docker pull rothackers/wshawk:latest
docker pull rothackers/wshawk:3.0.0

# GitHub Container Registry
docker pull ghcr.io/regaan/wshawk:latest
docker pull ghcr.io/regaan/wshawk:3.0.0

Image Tag Strategy (from .github/workflows/docker-build.yml:63-69):

  • latest - Latest build from main branch
  • 3.0.0 - Specific semantic version
  • 3.0 - Major.minor version
  • 3 - Major version only

Sources: .github/workflows/docker-build.yml:15-16, .github/workflows/docker-build.yml:63-69

Running Basic Scans

The container's default ENTRYPOINT is wshawk Dockerfile:52, so you can pass target URLs directly:

# Quick scan (default mode)
docker run --rm rothackers/wshawk ws://target.com

# Show help
docker run --rm rothackers/wshawk --help

# Interactive mode
docker run --rm -it rothackers/wshawk wshawk-interactive

# Advanced mode with all features
docker run --rm rothackers/wshawk wshawk-advanced ws://target.com --full

# Defensive validation
docker run --rm --entrypoint wshawk-defensive rothackers/wshawk ws://target.com

The --rm flag removes the container after execution. For persistent scans, see the Volume Mounts section below.

Sources: Dockerfile:52-53, docs/DOCKER.md:14-25


Volume Mounts and Persistence

WSHawk generates several artifacts that should be persisted outside the container for production use.

Volume Mount Architecture

graph LR
    subgraph "Host Filesystem"
        HostReports["./reports/"]
        HostDB["./data/scans.db"]
        HostConfig["./config/wshawk.yaml"]
        HostPlugins["./plugins/"]
    end
    
    subgraph "Container Filesystem"
        ContainerReports["/app/reports/<br/>(wshawk_report_*.html)"]
        ContainerDB["/app/scans.db<br/>(SQLite WAL mode)"]
        ContainerConfig["/app/wshawk.yaml<br/>(WSHawkConfig)"]
        ContainerPlugins["/app/plugins/<br/>(PluginManager)"]
    end
    
    subgraph "Scanner Components"
        Scanner["WSHawkV2.run()<br/>(scanner_v2.py)"]
        WebDash["FlaskApp<br/>(--web mode)"]
        PluginMgr["PluginManager<br/>(plugin_system.py)"]
    end
    
    HostReports -.->|"-v mount"| ContainerReports
    HostDB -.->|"-v mount"| ContainerDB
    HostConfig -.->|"-v mount"| ContainerConfig
    HostPlugins -.->|"-v mount"| ContainerPlugins
    
    ContainerReports --> Scanner
    ContainerDB --> Scanner
    ContainerDB --> WebDash
    ContainerConfig --> Scanner
    ContainerPlugins --> PluginMgr
    PluginMgr --> Scanner

Sources: Dockerfile:26, docs/DOCKER.md:58-63

Report Output Persistence

Reports are written to the current working directory (/app) by default. Mount a host directory to preserve them:

# Create reports directory on host
mkdir -p reports

# Run scan with report persistence
docker run --rm \
  -v $(pwd)/reports:/app/reports \
  rothackers/wshawk ws://target.com

# View generated reports
ls -lh reports/
# wshawk_report_20240115_143022.html
# wshawk_traffic_20240115_143022.log

Report filenames follow the pattern wshawk_report_YYYYMMDD_HHMMSS.html as generated by the scanner.

Sources: docs/DOCKER.md:58-63

Database Persistence for Web Dashboard

The web dashboard requires SQLite persistence to track scan history:

# Create data directory
mkdir -p data

# Run web dashboard with persistent database
docker run -d \
  --name wshawk-web \
  -p 5000:5000 \
  -v $(pwd)/data:/app \
  -e WSHAWK_WEB_PASSWORD=securepwd \
  rothackers/wshawk --web --host 0.0.0.0 --port 5000

# Database file: data/scans.db (SQLite WAL mode)

The database file scans.db is created in the working directory /app, which must be mounted to persist across container restarts. SQLite operates in WAL (Write-Ahead Logging) mode for crash recovery.

Sources: docs/DOCKER.md:58-63

Configuration File Mounting

External configuration files can override defaults:

# Mount custom configuration
docker run --rm \
  -v $(pwd)/config/wshawk.yaml:/app/wshawk.yaml \
  rothackers/wshawk ws://target.com

# Configuration hierarchy (highest to lowest):
# 1. Environment variables (WSHAWK_*)
# 2. Mounted wshawk.yaml
# 3. Built-in defaults

Configuration loading follows the hierarchical system described in Configuration System.

Sources: docs/DOCKER.md:58-63

Custom Plugin Loading

Custom plugins from Plugin System can be mounted at runtime:

# Mount plugin directory
docker run --rm \
  -v $(pwd)/plugins:/app/plugins \
  rothackers/wshawk ws://target.com

# PluginManager auto-discovers *.py files in /app/plugins

The PluginManager class scans /app/plugins for custom payload, detector, and protocol plugins as defined in wshawk/plugin_system.py:109-157.

Sources: wshawk/plugin_system.py:109-157, plugins/README.md:1-37


Environment Variables

WSHawk containers support extensive configuration via environment variables.

Environment Variable Flow

graph TB
    subgraph "Container Launch"
        DockerRun["docker run -e VAR=value"]
        DockerCompose["docker-compose.yml<br/>environment: section"]
        K8sSecret["Kubernetes Secret"]
    end
    
    subgraph "Runtime Environment"
        EnvVarBuiltin["Built-in Vars<br/>PYTHONUNBUFFERED=1<br/>PYTHONDONTWRITEBYTECODE=1"]
        EnvVarUser["User-Provided Vars<br/>WSHAWK_WEB_PASSWORD<br/>WSHAWK_API_KEY<br/>JIRA_API_TOKEN<br/>DEFECTDOJO_API_KEY"]
    end
    
    subgraph "Configuration System"
        WSHawkConfig["WSHawkConfig<br/>(wshawk.yaml loader)"]
        SecretResolver["Secret Resolution<br/>env: prefix<br/>file: prefix"]
    end
    
    subgraph "Scanner Components"
        WebAuth["Web Dashboard Auth<br/>(SHA-256 hashing)"]
        JiraInt["Jira Integration"]
        DDInt["DefectDojo Integration"]
        Scanner["WSHawkV2"]
    end
    
    DockerRun --> EnvVarUser
    DockerCompose --> EnvVarUser
    K8sSecret --> EnvVarUser
    
    EnvVarBuiltin --> WSHawkConfig
    EnvVarUser --> WSHawkConfig
    
    WSHawkConfig --> SecretResolver
    
    SecretResolver --> WebAuth
    SecretResolver --> JiraInt
    SecretResolver --> DDInt
    SecretResolver --> Scanner

Sources: Dockerfile:44-45, docs/DOCKER.md:113-118

Core Environment Variables

Python Runtime Variables

Set by Dockerfile:44-45:

| Variable | Value | Purpose | |----------|-------|---------| | PYTHONUNBUFFERED | 1 | Force stdout/stderr unbuffered for real-time logs | | PYTHONDONTWRITEBYTECODE | 1 | Prevent .pyc file generation |

Web Dashboard Variables

# Required for web mode
docker run -d \
  -p 5000:5000 \
  -e WSHAWK_WEB_PASSWORD=securepwd \
  -e WSHAWK_API_KEY=myapikey123 \
  rothackers/wshawk --web --host 0.0.0.0
  • WSHAWK_WEB_PASSWORD - Dashboard login password (SHA-256 hashed)
  • WSHAWK_API_KEY - Optional API key for REST endpoints

See Authentication and API Keys for details.

Integration Variables

# Jira integration
docker run --rm \
  -e JIRA_URL=https://company.atlassian.net \
  -e JIRA_API_TOKEN=your_token \
  -e JIRA_PROJECT_KEY=SEC \
  rothackers/wshawk ws://target.com

# DefectDojo integration
docker run --rm \
  -e DEFECTDOJO_URL=https://defectdojo.company.com \
  -e DEFECTDOJO_API_KEY=your_key \
  rothackers/wshawk ws://target.com

See Jira Integration and DefectDojo Integration for configuration details.

Sources: Dockerfile:44-45, docs/DOCKER.md:113-118


Network Configurations

WSHawk containers require proper network configuration to access target WebSocket servers.

Network Mode Matrix

| Target Location | Network Mode | Usage | |----------------|--------------|-------| | External server | bridge (default) | docker run --rm rothackers/wshawk ws://external.com | | Host localhost | --network host | docker run --rm --network host rothackers/wshawk ws://localhost:8765 | | Docker service | Custom network | See docker-compose section below | | Kubernetes pod | Cluster network | See Kubernetes Deployment |

Accessing Host Services

When scanning WebSocket servers running on the Docker host:

# Use host network mode
docker run --rm \
  --network host \
  rothackers/wshawk ws://localhost:8765

# Alternative: Use host.docker.internal (Docker Desktop only)
docker run --rm rothackers/wshawk ws://host.docker.internal:8765

The --network host option allows the container to access localhost services but removes network isolation.

Sources: docs/DOCKER.md:67-70

Custom Docker Networks

For scanning multiple containers:

# Create custom network
docker network create wshawk-net

# Start target server
docker run -d \
  --name vulnerable-server \
  --network wshawk-net \
  vulnerable-ws-app

# Scan from WSHawk container
docker run --rm \
  --network wshawk-net \
  rothackers/wshawk ws://vulnerable-server:8765

Containers on the same custom network can resolve each other by service name.

Sources: docs/DOCKER.md:134-143


Docker Compose Usage

The repository includes a docker-compose configuration for local testing and development.

Docker Compose Architecture

graph TB
    subgraph "docker-compose.yml Services"
        WSHawkSvc["wshawk service<br/>image: wshawk/wshawk:latest<br/>network_mode: host<br/>entrypoint: /bin/bash"]
        VulnServer["vulnerable-server service<br/>image: python:3.11-slim<br/>ports: 8765:8765<br/>command: python3 -m http.server"]
    end
    
    subgraph "Volume Mounts"
        ReportsVol["./reports:/app/reports"]
        ExamplesVol["./examples:/app"]
    end
    
    subgraph "Networks"
        HostNet["host network<br/>(wshawk)"]
        BridgeNet["wshawk-network<br/>(vulnerable-server)"]
    end
    
    WSHawkSvc --> ReportsVol
    WSHawkSvc --> HostNet
    
    VulnServer --> ExamplesVol
    VulnServer --> BridgeNet

Sources: docker-compose.yml:1-36

Service Definitions

The compose file docker-compose.yml:1-36 defines two services:

WSHawk Service

services:
  wshawk:
    build: .
    image: wshawk/wshawk:latest
    network_mode: host
    volumes:
      - ./reports:/app/reports
    entrypoint: /bin/bash
    stdin_open: true
    tty: true

Vulnerable Server Service

  vulnerable-server:
    image: python:3.11-slim
    ports:
      - "8765:8765"
    volumes:
      - ./examples:/app
    networks:
      - wshawk-network

Sources: docker-compose.yml:4-32

Starting Services

# Start all services in background
docker-compose up -d

# View logs
docker-compose logs -f wshawk

# Execute commands in running container
docker-compose exec wshawk wshawk ws://localhost:8765

# Interactive shell
docker-compose exec wshawk bash

# Stop services
docker-compose down

Sources: docs/DOCKER.md:89-98

Custom Compose Configuration

Modify docker-compose.yml:1-36 to customize:

services:
  wshawk:
    environment:
      - WSHAWK_WEB_PASSWORD=custompass
      - JIRA_API_TOKEN=token123
    volumes:
      - ./config:/app/config
      - ./plugins:/app/plugins
    ports:
      - "5000:5000"  # Expose web dashboard
    command: wshawk --web --host 0.0.0.0  # Override entrypoint

Sources: docs/DOCKER.md:100-107


Advanced Container Usage

Playwright Browser Testing

The container includes Playwright support but requires browser installation:

# Method 1: Install browsers at runtime
docker run --rm -it \
  --entrypoint /bin/bash \
  rothackers/wshawk

# Inside container:
playwright install chromium
wshawk-advanced ws://target.com --playwright

# Method 2: Create custom image with browsers pre-installed
FROM rothackers/wshawk:latest
RUN playwright install --with-deps chromium

Playwright verification is documented in Playwright XSS Verification.

Sources: docs/DOCKER.md:125-131

Multi-Architecture Support

Images are built for multiple architectures via .github/workflows/docker-build.yml:80:

# Automatic platform selection
docker pull rothackers/wshawk:latest

# Explicit platform (for testing)
docker pull --platform linux/amd64 rothackers/wshawk:latest
docker pull --platform linux/arm64 rothackers/wshawk:latest

Supported platforms:

  • linux/amd64 - x86_64 servers
  • linux/arm64 - ARM-based systems (Apple Silicon, AWS Graviton)

Sources: .github/workflows/docker-build.yml:29-33, .github/workflows/docker-build.yml:80

Interactive Shell Access

For debugging or manual testing:

# Bash shell
docker run --rm -it \
  --entrypoint /bin/bash \
  rothackers/wshawk

# Run commands inside container
wshawk ws://target.com
wshawk-defensive ws://target.com
python3 -m wshawk.scanner_v2

The --entrypoint flag overrides the default wshawk entrypoint Dockerfile:52.

Sources: docs/DOCKER.md:74-81


Security Best Practices

Non-Root Execution

The container runs as user wshawk:1000 Dockerfile:38-41 by default:

# Verify non-root user
docker run --rm rothackers/wshawk id
# uid=1000(wshawk) gid=1000(wshawk) groups=1000(wshawk)

# Explicitly set user (already default)
docker run --rm --user wshawk rothackers/wshawk ws://target.com

Running as non-root prevents privilege escalation attacks.

Sources: Dockerfile:38-41, docs/DOCKER.md:212-215

Read-Only Filesystem

For maximum security in production:

# Run with read-only root filesystem
docker run --rm \
  --read-only \
  -v $(pwd)/reports:/app/reports \
  rothackers/wshawk ws://target.com

The --read-only flag prevents any writes to the container filesystem. Mount /app/reports for output.

Sources: docs/DOCKER.md:217-220

Resource Limits

Prevent resource exhaustion:

# Limit memory and CPU
docker run --rm \
  --memory=512m \
  --cpus=1 \
  --pids-limit=100 \
  rothackers/wshawk ws://target.com

Resource limits prevent denial-of-service scenarios if the scanner encounters pathological responses.

Sources: docs/DOCKER.md:222-225

Version Pinning

Always use specific version tags in production:

# Avoid latest tag in production
docker pull rothackers/wshawk:3.0.0

# Verify image digest
docker inspect rothackers/wshawk:3.0.0 | grep RepoDigests

The CI/CD pipeline generates semantic version tags .github/workflows/docker-build.yml:66-68 for reproducible deployments.

Sources: docs/DOCKER.md:207-210, .github/workflows/docker-build.yml:66-68


Troubleshooting

Permission Issues with Volume Mounts

If mounted volumes have permission errors:

# Run as current user (loses non-root security)
docker run --rm \
  --user $(id -u):$(id -g) \
  -v $(pwd)/reports:/app/reports \
  rothackers/wshawk ws://target.com

# Better: Fix host directory permissions
sudo chown -R 1000:1000 reports/

The container user wshawk has UID/GID 1000 Dockerfile:38.

Sources: Dockerfile:38, docs/DOCKER.md:170-174

Network Connectivity Issues

For debugging network problems:

# Test DNS resolution
docker run --rm rothackers/wshawk nslookup target.com

# Test connectivity
docker run --rm rothackers/wshawk ping -c 3 target.com

# Check container network
docker run --rm rothackers/wshawk ip addr

Sources: docs/DOCKER.md:176-184

Volume Mount Path Issues

Use absolute paths on Linux/macOS:

# Incorrect: relative path may fail on some systems
docker run -v ./reports:/app/reports rothackers/wshawk

# Correct: absolute path
docker run -v $(pwd)/reports:/app/reports rothackers/wshawk

# Windows (PowerShell)
docker run -v ${PWD}/reports:/app/reports rothackers/wshawk

Sources: docs/DOCKER.md:186-191

Healthcheck Verification

The container includes a health check Dockerfile:48-49:

# Check container health
docker ps --format "table {{.Names}}\t{{.Status}}"

# Manual healthcheck test
docker run --rm rothackers/wshawk --help
# Exit code 0 = healthy

The healthcheck runs wshawk --help every 30 seconds with a 10-second timeout.

Sources: Dockerfile:48-49


CI/CD Container Usage

For automated security testing in CI/CD pipelines, see CI/CD Integration for complete examples using GitHub Actions and GitLab CI with the WSHawk container.

Quick example:

# .github/workflows/security-scan.yml
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - name: Run WSHawk Scan
        run: |
          docker pull rothackers/wshawk:3.0.0
          docker run --rm \
            -v ${{ github.workspace }}/reports:/app/reports \
            rothackers/wshawk ws://staging.example.com
      
      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: reports/wshawk_sarif.json

Sources: docs/DOCKER.md:146-163


Image Build Information

Build Process

The automated build process defined in .github/workflows/docker-build.yml:1-89:

  1. Trigger Events docker-build.yml:3-12):

    • Push to main branch
    • Version tags (v*)
    • Pull requests
    • Manual workflow dispatch
  2. Build Steps:

  3. Testing docker-build.yml:82-88:

    • Pull built image
    • Verify --help command
    • Test defensive mode entrypoint

Image Metadata

Container labels follow OpenContainers standards Dockerfile:55-66:

# View image labels
docker inspect rothackers/wshawk:latest | jq '.[0].Config.Labels'

Labels include:

  • org.opencontainers.image.source - GitHub repository URL
  • org.opencontainers.image.version - Version number
  • org.opencontainers.image.licenses - MIT

Sources: Dockerfile:55-66, .github/workflows/docker-build.yml:1-89

Image Size Optimization

The multi-stage build reduces image size through:

  • Build-time dependencies excluded Dockerfile:10-12: gcc, build-essential removed from final image
  • .dockerignore filtering .dockerignore:1-72: Excludes test files, documentation, git history
  • Slim base image Dockerfile:4,23: Uses python:3.11-slim (~150MB vs ~1GB for full image)

Final image size: ~150MB compressed.

Sources: Dockerfile:4-53, .dockerignore:1-72, docs/DOCKER.md:195-202