# TREK Docker Container Security Options: Image and Runtime Hardening Guide

> Explore TREK Docker container security. Learn about image and runtime hardening options including minimal images, non-root execution, read-only filesystems, and HTTPS hardening for enhanced security.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: how-to-guide
- Published: 2026-07-03

---

**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`](https://github.com/mauriceboe/TREK/blob/main/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:

```yaml
cap_drop:
  - ALL
cap_add:
  - CHOWN
  - SETUID
  - SETGID

```

This configuration, found in [`docker-compose.yml`](https://github.com/mauriceboe/TREK/blob/main/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:

```yaml
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`](https://github.com/mauriceboe/TREK/blob/main/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 attributes
- **`COOKIE_SECURE=true`**: Ensures cookies are transmitted only over HTTPS connections
- **`TRUST_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`](https://github.com/mauriceboe/TREK/blob/main/docker-compose.yml):

```yaml
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:

```bash
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-slim` with a non-root `node` user and minimal packages to reduce the attack surface.
- **Filesystem protection**: `read_only: true` combined 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 only `CHOWN`, `SETUID`, and `SETGID` for file ownership operations.
- **Privilege escalation prevention**: `no-new-privileges:true` blocks setuid-based privilege escalation attempts.
- **Temporary file security**: `/tmp` is mounted as a `tmpfs` with `noexec` and `nosuid` flags to prevent execution of malicious binaries.
- **Transport security**: Environment variables `FORCE_HTTPS`, `COOKIE_SECURE`, and `TRUST_PROXY` enforce 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`](https://github.com/mauriceboe/TREK/blob/main/wiki/Security-Hardening.md) and should be combined with a proper TLS-terminating proxy for complete transport security.