Docker Usage Guide
Docker Usage Guide
The following files were used as context for generating this wiki page:
- .dockerignore
- .github/workflows/docker-build.yml
- Dockerfile
- docker-compose.yml
- docs/DOCKER.md
- plugins/README.md
- wshawk/plugin_system.py
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 branch3.0.0- Specific semantic version3.0- Major.minor version3- 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
- Uses
network_mode: hostdocker-compose.yml:9 to access host services - Overrides entrypoint to
/bin/bashdocker-compose.yml:14 for interactive shell - Mounts
./reportsfor persistent output docker-compose.yml:12
Vulnerable Server Service
vulnerable-server:
image: python:3.11-slim
ports:
- "8765:8765"
volumes:
- ./examples:/app
networks:
- wshawk-network
- Provides a test WebSocket server on port 8765 docker-compose.yml:25
- Isolated on custom bridge network docker-compose.yml:31
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 serverslinux/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:
-
Trigger Events docker-build.yml:3-12):
- Push to
mainbranch - Version tags (
v*) - Pull requests
- Manual workflow dispatch
- Push to
-
Build Steps:
- Set up QEMU for multi-arch docker-build.yml:29-30
- Set up Docker Buildx docker-build.yml:32-33
- Extract metadata for tagging docker-build.yml:56-70
- Build for
linux/amd64,linux/arm64docker-build.yml:80
-
Testing docker-build.yml:82-88:
- Pull built image
- Verify
--helpcommand - 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 URLorg.opencontainers.image.version- Version numberorg.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