TREK Docker Container Security Options: Image and Runtime Hardening Guide
TREK Docker containers provide layered security through minimal base images, non-root execution, read-only filesystems, dropped Linux capabilities, and environment-driven HTTPS hardening.
The mauriceboe/TREK repository ships with defense-in-depth controls embedded directly in its container configuration. These security options are enforced at both the image build stage and runtime, minimizing the attack surface while maintaining functionality. Whether you deploy via Docker Compose or standalone docker run commands, TREK offers hardened defaults that follow container security best practices.
Image-Level Hardening in the Dockerfile
The TREK image is constructed using a multi-stage build process designed to eliminate unnecessary tooling and reduce vulnerable packages.
Minimal Base and Non-Root Execution
In Dockerfile lines 41-76, the build uses node:24-trixie-slim as the final runtime base to keep the footprint small. The container runs as the pre-defined node user rather than root, preventing privilege escalation attacks that rely on root access inside the container. The build also sets QT_QPA_PLATFORM=offscreen to disable GUI-related attack vectors in headless environments.
Build-Time Security Controls
The Dockerfile strips away build dependencies after compilation, ensuring the final image contains only runtime essentials. This minimal approach reduces the number of packages that could potentially harbor vulnerabilities, while the non-root user configuration ensures that even if an attacker compromises the application process, they lack elevated privileges within the container namespace.
Runtime Security Options in docker-compose.yml
The docker-compose.yml file implements runtime hardening mechanisms that restrict what the container can do once started. These controls are found in lines 5-15 of the compose file.
Read-Only Root Filesystem
Setting read_only: true prevents the container from writing to its own code tree, forcing all mutable data onto explicitly mounted volumes. This protects against attackers modifying application binaries or injecting malicious code into the container filesystem. The repository mounts /app/data and /app/uploads as writable volumes to handle necessary state persistence while keeping the application code immutable.
Linux Capabilities Restriction
TREK implements the principle of least privilege by dropping all Linux capabilities by default, then re-adding only the narrow set required for operation:
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
This configuration, found in docker-compose.yml lines 8-14, removes dangerous privileges like NET_ADMIN or SYS_ADMIN while retaining the minimum permissions needed for file ownership changes within the container.
No-New-Privileges Protection
The security_opt: - no-new-privileges:true setting prevents processes inside the container from gaining additional privileges through set-user-ID (setuid) binaries. Even if an attacker exploits a vulnerability to execute a setuid binary, this flag blocks privilege escalation, keeping the process confined to the node user permissions.
Tmpfs Mount Hardening
Temporary storage is mounted as an in-memory filesystem with execution restrictions:
tmpfs:
- /tmp:noexec,nosuid,size=128m
This configuration prevents the execution of binaries or scripts placed in /tmp and blocks setuid files from being created there, mitigating common attack vectors that rely on temporary file manipulation.
Network and Application Security
Beyond container-level hardening, TREK provides environment variables that enforce secure communication patterns.
HTTPS Enforcement and Cookie Security
According to wiki/Security-Hardening.md (lines 11-16 and 29-31), the following environment variables enable application-layer security:
FORCE_HTTPS=true: Activates HSTS headers and secure cookie attributesCOOKIE_SECURE=true: Ensures cookies are transmitted only over HTTPS connectionsTRUST_PROXY=1: Configures the application to correctly parse client IP addresses when running behind a TLS-terminating reverse proxy
These settings ensure that even if the container is deployed behind a load balancer, the application maintains secure session handling and transport encryption enforcement.
Implementation Examples
Deploy TREK with the recommended security configuration using the provided docker-compose.yml:
services:
app:
image: mauriceboe/trek:dev
container_name: trek
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
tmpfs:
- /tmp:noexec,nosuid,size=128m
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
- ENCRYPTION_KEY=${ENCRYPTION_KEY:-}
- FORCE_HTTPS=true
- TRUST_PROXY=1
volumes:
- ./data:/app/data
- ./uploads:/app/uploads
restart: unless-stopped
For standalone Docker deployments, apply the same hardening flags via command line:
docker run -d \
--name trek \
--read-only \
--security-opt no-new-privileges:true \
--cap-drop ALL \
--cap-add CHOWN \
--cap-add SETUID \
--cap-add SETGID \
--tmpfs /tmp:noexec,nosuid,size=128m \
-p 3000:3000 \
-e NODE_ENV=production \
-e PORT=3000 \
-e ENCRYPTION_KEY=$(openssl rand -hex 32) \
-e FORCE_HTTPS=true \
-e TRUST_PROXY=1 \
-v $(pwd)/data:/app/data \
-v $(pwd)/uploads:/app/uploads \
mauriceboe/trek:dev
Summary
- Image hardening: TREK uses
node:24-trixie-slimwith a non-rootnodeuser and minimal packages to reduce the attack surface. - Filesystem protection:
read_only: truecombined with explicit volume mounts prevents code modification while allowing necessary data persistence. - Capability restriction: The container drops all Linux capabilities (
cap_drop: ALL) and re-adds onlyCHOWN,SETUID, andSETGIDfor file ownership operations. - Privilege escalation prevention:
no-new-privileges:trueblocks setuid-based privilege escalation attempts. - Temporary file security:
/tmpis mounted as atmpfswithnoexecandnosuidflags to prevent execution of malicious binaries. - Transport security: Environment variables
FORCE_HTTPS,COOKIE_SECURE, andTRUST_PROXYenforce HTTPS and secure cookie handling when behind reverse proxies.
Frequently Asked Questions
What is the primary security benefit of running TREK with read_only: true?
The read_only: true setting prevents the container from modifying its own filesystem, which blocks attackers from injecting backdoors into application code or overwriting system binaries. This forces all mutable data to reside only on explicitly mounted volumes, creating a clear separation between immutable application code and writable data storage.
Why does TREK drop all Linux capabilities and then add specific ones back?
Dropping all capabilities with cap_drop: ALL removes every privileged operation available to the container by default, following the principle of least privilege. TREK then selectively re-adds only CHOWN, SETUID, and SETGID because these specific permissions are required for proper file ownership management within the application, while dangerous capabilities like NET_ADMIN or SYS_ADMIN remain unavailable to potential attackers.
How does TREK prevent privilege escalation inside the container?
TREK prevents privilege escalation through the no-new-privileges:true security option, which blocks processes from gaining additional privileges after startup, even if they execute setuid binaries. Combined with the non-root node user and dropped capabilities, this ensures that even if an attacker compromises the application process, they cannot elevate privileges beyond the restricted container environment.
What environment variables are required for HTTPS hardening in TREK?
To enforce HTTPS hardening, set FORCE_HTTPS=true to enable HSTS headers and secure cookies, COOKIE_SECURE=true to ensure cookies are only transmitted over encrypted connections, and TRUST_PROXY=1 to correctly identify client IP addresses when running behind a reverse proxy. These settings are documented in wiki/Security-Hardening.md and should be combined with a proper TLS-terminating proxy for complete transport security.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →