How Project N.O.M.A.D. Handles Docker Container Orchestration

Project N.O.M.A.D. uses Docker Compose to orchestrate a multi-service stack where the admin container mounts the host Docker socket to dynamically manage containers, supplemented by a dedicated sidecar updater for zero-downtime rolling updates.

Project N.O.M.A.D. (Network-Orchestrated Media-Asset Delivery) from the Crosstalk-Solutions/project-nomad repository implements a sophisticated Docker container orchestration strategy that balances deployment simplicity with powerful runtime control. The entire application stack runs inside Docker containers coordinated through a declarative Compose file, eliminating external orchestration dependencies like Kubernetes while providing enterprise-grade container lifecycle management. This self-contained architecture enables single-command deployments with intelligent update capabilities through a custom sidecar pattern.

Docker Compose Foundation and Service Architecture

The orchestration layer centers on install/management_compose.yaml, which defines six tightly-coupled services in a single Compose project:

  • admin – The main AdonisJS web/API server (ghcr.io/crosstalk-solutions/project-nomad:latest) that drives the UI and background workers.
  • disk-collector – A read-only filesystem metadata scanner (ghcr.io/crosstalk-solutions/project-nomad-disk-collector:latest) with host-root bind access.
  • mysql – Persistent relational database using the official mysql:8.0 image.
  • redis – In-memory cache and queue backend running redis:7-alpine.
  • dozzle – Real-time log viewer (amir20/dozzle:v10.0) for container monitoring.
  • updater – Sidecar service built from install/sidecar-updater/Dockerfile that manages rolling updates.

Each service mounts specific volumes for persistence, with the admin and updater containers receiving special access to the host Docker socket for runtime orchestration.

Admin Container as Runtime Orchestrator

By mounting /var/run/docker.sock directly into the admin container, Project N.O.M.A.D. grants the AdonisJS application direct Docker CLI capabilities without requiring external orchestration tools. This design allows the admin service to invoke dockerode (Node.js Docker library) or native Docker commands to start, stop, or remove background worker containers on demand.

The socket mount configuration in install/management_compose.yaml appears as:

services:
  admin:
    image: ghcr.io/crosstalk-solutions/project-nomad:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /opt/project-nomad/storage:/app/storage
    depends_on:
      - mysql
      - redis

This architecture centralizes control within the admin service while maintaining strict isolation for filesystem-focused containers like the disk-collector, which runs with read-only host root access (/:/host:ro,rslave) but no Docker socket privileges.

Container Bootstrap and Entrypoint Management

When the admin container starts, install/entrypoint.sh executes a deterministic boot sequence that ensures dependent services are healthy before accepting traffic:

#!/bin/sh
set -e
/usr/local/bin/wait-for-it.sh ${DB_HOST}:${DB_PORT} -t 60 -- echo "MySQL is up and running!"
node ace migration:run --force
node ace db:seed
node ace queue:work --all &
exec node bin/server.js

This script handles database migrations, seeding, and queue worker initialization, preventing race conditions during stack startup. The depends_on directives in the Compose file coordinate container start order, while the entrypoint script handles application-level readiness.

Zero-Downtime Updates via Sidecar Pattern

Project N.O.M.A.D. implements a unique sidecar updater that achieves zero-downtime deployments without complex orchestration platforms. The updater runs in an isolated Alpine container that watches for update requests and performs sequential service replacements.

Update Trigger Mechanism

When an operator initiates an update through the UI, the admin service writes a JSON request to a shared volume mounted at /opt/project-nomad/update-shared/:

cat <<EOF > /opt/project-nomad/update-shared/update-request
{
  "target_tag": "v2.3.0"
}
EOF

Rolling Update Execution

The install/sidecar-updater/update-watcher.sh script detects this file and executes a controlled rolling update:

  1. Patch the Compose file – Uses sed to substitute the image tag:

    sed -i "s|\(image: ghcr\.io/crosstalk-solutions/project-nomad\):.*|\1:${target_tag}|" "$COMPOSE_FILE"
  2. Pull updated images – Runs docker compose pull to fetch new layers.

  3. Sequential recreation – Stops, removes, and recreates each service individually (excluding itself), ensuring the application remains available throughout the process.

  4. Status reporting – Writes progress to a JSON status file in the shared volume for UI feedback.

Initial Deployment and Lifecycle Commands

Deploying the stack requires only Docker and the Compose file:

docker compose -p project-nomad -f ./install/management_compose.yaml up -d

This command starts all services detached, creates the project network, and establishes volume mounts. For routine management, the repository includes convenience scripts:

Summary

  • Docker Compose serves as the declarative orchestration engine, defined entirely in install/management_compose.yaml.
  • Admin socket access enables dynamic container management by mounting /var/run/docker.sock, allowing runtime control without Kubernetes.
  • Sidecar updater provides sophisticated rolling updates through install/sideside-updater/update-watcher.sh, patching Compose files and sequentially recreating services.
  • Entrypoint orchestration via install/entrypoint.sh ensures database readiness and proper worker initialization before serving traffic.
  • Service isolation limits security exposure by granting filesystem access only to the disk-collector and Docker socket access only to admin and updater containers.

Frequently Asked Questions

Does Project N.O.M.A.D. require Kubernetes for container orchestration?

No, Project N.O.M.A.D. deliberately avoids Kubernetes dependencies, using Docker Compose as its native orchestration layer. The architecture achieves dynamic container management through Docker socket access rather than external orchestrators, making it suitable for single-node or small-scale deployments without the operational complexity of Kubernetes clusters.

How does the admin container safely manage other containers?

The admin container receives privileged access to the host Docker socket through a volume mount (/var/run/docker.sock:/var/run/docker.sock), allowing it to execute Docker API calls as if running on the host. This capability enables the AdonisJS application to spawn background workers and trigger updates while maintaining container isolation for other services like the disk-collector, which lacks socket access.

What happens during a zero-downtime update process?

The sidecar updater container detects update requests written to a shared volume, then sequentially stops and recreates each service defined in the Compose file while excluding itself from the rotation. It patches the image tags using sed, pulls new images via docker compose pull, and recreates containers one-by-one, ensuring the admin API remains available throughout the deployment.

Where are the Docker orchestration files located in the repository?

All orchestration assets reside in the install/ directory: install/management_compose.yaml defines the service topology, install/entrypoint.sh handles container bootstrapping, install/sidecar-updater/Dockerfile builds the updater image, and install/sidecar-updater/update-watcher.sh contains the rolling update logic. The main application Dockerfile sits in the repository root for building the ghcr.io/crosstalk-solutions/project-nomad:latest image.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →