# F1.5 — Docker Deployment Engine
What This Feature Does
Manages the container deployment lifecycle for Vexlyx projects. After Nixpacks builds a Docker image (F1.4), the deployment engine generates a tailored docker-compose.yml file, starts the container using Docker Compose, configures Traefik reverse-proxy routing labels, dynamically allocates host ports, enforces memory limits, handles container lifecycle actions (start, stop, restart, remove), and provides runtime logs.
Architecture
Dashboard (BuildPanel.tsx / ContainerControls.tsx / useDeploy.ts)
│
│ POST /api/projects/:id/deploy
│ POST /api/projects/:id/container/:action (start | stop | restart | remove)
│ GET /api/projects/:id/container/status
│ GET /api/projects/:id/logs?tail=N
▼
API (apps/api/src/modules/deploy/)
├── routes.ts — Fastify route handlers with authentication & input validation
├── service.ts — Business logic, Docker manager execution, Project DB updates
└── schema.ts — DeployBodySchema, ContainerActionBodySchema, LogsQuerySchema
│
│ stdin: JSON payload { command: "deploy" | "start" | "stop" | "restart" | "remove" | "status" | "logs", ... }
│ stdout: JSON results / log streaming
▼
system/python/docker_manager.py
├── cmd_deploy() — Generates compose file from template & runs `docker compose up -d`
├── cmd_start() — `docker compose start`
├── cmd_stop() — `docker compose stop`
├── cmd_restart() — `docker compose restart`
├── cmd_remove() — `docker compose down --volumes --remove-orphans`
├── cmd_status() — `docker inspect` to verify container state
└── cmd_logs() — `docker compose logs --tail=N`
│
├── system/templates/docker-compose/node.yml
├── system/templates/docker-compose/python.yml
└── system/templates/docker-compose/static.ymlDeployment Lifecycle & Pipeline
Build & Deploy Pipeline:
BuildServiceruns Nixpacks plan and image build (QUEUED→BUILDING).- When image build completes, it automatically transitions to
DEPLOYING. runDockerDeploy()runsdocker_manager.py deploy:- Selects the appropriate compose template (
node.yml,python.yml, orstatic.yml). - Substitutes template tokens:
image_name,service_name,hostname,host_port,container_port,memory_limit, andenv_block. - Writes
docker-compose.ymlin{PROJECTS_DIR}/{projectId}/deploy/. - Executes
docker compose up -d --force-recreate --pull never. - Resolves container ID and verifies container startup.
- Selects the appropriate compose template (
- Updates
Projectrecord in PostgreSQL (containerId,containerStatus,internalPort,deployedDomain,deployedAt,status = ACTIVE). - Marks
Deploymentrecord asRUNNING.
Container Lifecycle Management:
- Start:
POST /api/projects/:id/container/start→ sets project status toACTIVE. - Stop:
POST /api/projects/:id/container/stop→ sets project status toSTOPPED. - Restart:
POST /api/projects/:id/container/restart→ restarts container and sets status toACTIVE. - Remove:
POST /api/projects/:id/container/remove→ destroys container & volumes, clears container metadata, and sets status toSTOPPED.
- Start:
Runtime Logs:
GET /api/projects/:id/logs?tail=100retrieves stdout & stderr output from the running container.
Key Files
| File | Role |
|---|---|
apps/api/src/modules/deploy/routes.ts | Fastify routes for deploy, lifecycle actions, container status, and runtime logs |
apps/api/src/modules/deploy/service.ts | DeployService class and subprocess helpers for docker_manager.py |
apps/api/src/modules/deploy/schema.ts | Zod request validation schemas (DeployBodySchema, ContainerActionBodySchema, LogsQuerySchema) |
system/python/docker_manager.py | Python daemon script handling compose generation, Docker CLI execution, and log retrieval |
system/templates/docker-compose/node.yml | Docker Compose template for Node.js and Next.js applications |
system/templates/docker-compose/python.yml | Docker Compose template for Python WSGI/ASGI applications |
system/templates/docker-compose/static.yml | Docker Compose template for static React/HTML sites |
packages/shared/src/schemas/projects.ts | Shared DeployBodySchema and ContainerActionSchema |
packages/shared/src/types/index.ts | Extended Project type with container fields (containerId, containerStatus, etc.) |
apps/dashboard/src/hooks/useDeploy.ts | React hooks: useContainerAction, useContainerStatus, useContainerLogs |
apps/dashboard/src/components/projects/ContainerControls.tsx | Live container status badge, start/stop/restart/remove action buttons, endpoint link, and runtime log viewer |
Database Model Changes
The following fields were added to the Project model in apps/api/prisma/schema.prisma:
| Column | Type | Description |
|---|---|---|
containerId | String? | Docker container ID of the running container |
containerStatus | String? | Last known status reported by Docker (e.g. running, exited) |
internalPort | Int? | Host-side port dynamically allocated for this container (8100–8999) |
deployedDomain | String? | Traefik hostname (e.g. {project-name}.{BASE_DOMAIN}) |
deployedAt | DateTime? | Timestamp of the most recent successful deployment |
Environment Variables
| Variable | Default (dev) | Description |
|---|---|---|
BASE_DOMAIN | vexlyx.localhost | Base domain used to generate Traefik routing hostnames: {name}.{BASE_DOMAIN} |
DEPLOY_MEMORY_LIMIT | 128m | Default memory limit passed to Docker container resource limits |
DEPLOY_PORT_RANGE_START | 8100 | Start of host-port range for dynamic allocation |
DEPLOY_PORT_RANGE_END | 8999 | End of host-port range for dynamic allocation |
API Reference
POST /api/projects/:id/deploy
Triggers container deployment for the built Docker image.
- Request Body:
{ domain?: string }(optional domain override) - Response:json
{ "containerId": "a1b2c3d4e5f6", "internalPort": 8142, "deployedDomain": "my-app.vexlyx.localhost", "containerStatus": "running" }
POST /api/projects/:id/container/:action
Executes a lifecycle action on the project container.
- URL Parameter:
action—"start"|"stop"|"restart"|"remove" - Response:json
{ "message": "Container restart completed successfully", "containerStatus": "running" }
GET /api/projects/:id/container/status
Returns real-time container status from Docker inspect.
- Response:json
{ "containerStatus": "running", "containerId": "a1b2c3d4e5f6" }
GET /api/projects/:id/logs?tail=100
Fetches runtime logs from the container.
- Response:json
{ "logs": "Server listening on port 3000\nConnected to database\n" }
How to Test
Verify Full Build + Deploy Pipeline:
- Go to a project with a connected git repository.
- Click "Deploy" in the Deployments panel.
- Observe status progression:
QUEUED→BUILDING→DEPLOYING→RUNNING. - Verify that Live Container card updates with container ID, host port, and endpoint domain.
Test Container Lifecycle:
- Click "Stop" → container status updates to "Stopped", status badge turns gray.
- Click "Start" → container restarts, status badge turns green ("Running").
- Click "Restart" → container restarts smoothly.
- Click "Runtime Logs" → terminal viewer opens displaying runtime stdout/stderr.
- Click "Remove" → confirmation dialog opens; on confirm, container and volumes are deleted and status resets to "Not Deployed".