14 KiB
Docker Feature
The Docker feature provides complete container management for Unraid through a GraphQL API, including lifecycle operations, real-time monitoring, update detection, and organizational tools.
Table of Contents
- Overview
- Architecture
- Core Services
- GraphQL API
- Data Models
- Caching Strategy
- WebGUI Integration
- Permissions
- Configuration Files
- Development
Overview
Location: src/unraid-api/graph/resolvers/docker/
Feature Flag: Many next-generation features are gated behind ENABLE_NEXT_DOCKER_RELEASE. See Feature Flags for details on enabling.
Key Capabilities:
- Container lifecycle management (start, stop, pause, update, remove)
- Real-time container stats streaming
- Network and port conflict detection
- Container log retrieval
- Automatic update detection via digest comparison
- Tailscale container integration
- Container organization with folders and views
- Template-based metadata resolution
Architecture
Module Structure
The Docker module (docker.module.ts) serves as the entry point and exports:
- 13 services for various Docker operations
- 3 resolvers for GraphQL query/mutation/subscription handling
Dependencies:
JobModule- Background job schedulingNotificationsModule- User notificationsServicesModule- Shared service utilities
Data Flow
Docker Daemon (Unix Socket)
↓
dockerode library
↓
DockerService (transform & cache)
↓
GraphQL Resolvers
↓
Client Applications
The API communicates with the Docker daemon through the dockerode library via Unix socket. Container data is transformed from raw Docker API format to GraphQL types, enriched with Unraid-specific metadata (templates, autostart config), and cached for performance.
Core Services
DockerService
File: docker.service.ts
Central orchestrator for all container operations.
Key Methods:
getContainers(skipCache?, includeSize?)- List containers with cachingstart(id),stop(id),pause(id),unpause(id)- Lifecycle operationsupdateContainer(id),updateContainers(ids),updateAllContainers()- Image updatesremoveContainer(id, withImage?)- Remove container and optionally its image
Caching:
- Cache TTL: 60 seconds (60000ms)
- Cache keys:
docker_containers,docker_containers_with_size - Invalidated automatically on mutations
DockerNetworkService
File: docker-network.service.ts
Lists Docker networks with metadata including driver, scope, IPAM settings, and connected containers.
Caching: 60 seconds
DockerPortService
File: docker-port.service.ts
Detects port conflicts between containers and with the host.
Features:
- Deduplicates port mappings from Docker API
- Identifies container-to-container conflicts
- Detects host-level port collisions
- Separates TCP and UDP conflicts
- Calculates LAN-accessible IP:port combinations
DockerLogService
File: docker-log.service.ts
Retrieves container logs with configurable options.
Parameters:
tail- Number of lines (default: 200, max: 2000)since- Timestamp filter for log entries
Additional Features:
- Calculates container log file sizes
- Supports timestamp-based filtering
DockerStatsService
File: docker-stats.service.ts
Provides real-time container statistics via GraphQL subscription.
Metrics:
- CPU percentage
- Memory usage and limit
- Network I/O (received/transmitted bytes)
- Block I/O (read/written bytes)
Implementation:
- Spawns
docker statsprocess with streaming output - Publishes to
PUBSUB_CHANNEL.DOCKER_STATS - Auto-starts on first subscriber, stops when last disconnects
DockerAutostartService
File: docker-autostart.service.ts
Manages container auto-start configuration.
Features:
- Parses auto-start file format (name + wait time per line)
- Maintains auto-start order and wait times
- Persists configuration changes
- Tracks container primary names
DockerConfigService
File: docker-config.service.ts
Persistent configuration management using ConfigFilePersister.
Configuration Options:
templateMappings- Container name to template file path mappingsskipTemplatePaths- Containers excluded from template scanningupdateCheckCronSchedule- Cron expression for digest refresh (default: daily at 6am)
DockerManifestService
File: docker-manifest.service.ts
Detects available container image updates.
Implementation:
- Compares local and remote image SHA256 digests
- Reads cached status from
/var/lib/docker/unraid-update-status.json - Triggers refresh via PHP integration
DockerPhpService
File: docker-php.service.ts
Integration with legacy Unraid PHP Docker scripts.
PHP Scripts Used:
DockerUpdate.php- Refresh container digestsDockerContainers.php- Get update statuses
Update Statuses:
UP_TO_DATE- Container is currentUPDATE_AVAILABLE- New image availableREBUILD_READY- Rebuild requiredUNKNOWN- Status could not be determined
DockerTailscaleService
File: docker-tailscale.service.ts
Detects and monitors Tailscale-enabled containers.
Detection Methods:
- Container labels indicating Tailscale
- Tailscale socket mount points
Status Information:
- Tailscale version and backend state
- Hostname and DNS name
- Exit node status
- Key expiry dates
Caching:
- Status cache: 30 seconds
- DERP map and versions: 24 hours
DockerTemplateScannerService
File: docker-template-scanner.service.ts
Maps containers to their template files for metadata resolution.
Bootstrap Process:
- Runs 5 seconds after app startup
- Scans XML templates from configured paths
- Parses container/image names from XML
- Matches against running containers
- Stores mappings in
docker.config.json
Template Metadata Resolved:
projectUrl,registryUrl,supportUrliconUrl,webUiUrl,shell- Template port mappings
Orphaned Containers:
Containers without matching templates are marked as "orphaned" in the API response.
DockerOrganizerService
File: organizer/docker-organizer.service.ts
Container organization system for UI views.
Features:
- Hierarchical folder structure
- Multiple views with different layouts
- Position-based organization
- View-specific preferences (sorting, filtering)
GraphQL API
Queries
type Query {
docker: Docker!
}
type Docker {
containers(skipCache: Boolean): [DockerContainer!]!
container(id: PrefixedID!): DockerContainer # Feature-flagged
networks(skipCache: Boolean): [DockerNetwork!]!
portConflicts(skipCache: Boolean): DockerPortConflicts!
logs(id: PrefixedID!, since: Int, tail: Int): DockerContainerLogs!
organizer(skipCache: Boolean): DockerOrganizer! # Feature-flagged
containerUpdateStatuses: [ContainerUpdateStatus!]! # Feature-flagged
}
Mutations
Container Lifecycle:
type Mutation {
start(id: PrefixedID!): DockerContainer!
stop(id: PrefixedID!): DockerContainer!
pause(id: PrefixedID!): DockerContainer!
unpause(id: PrefixedID!): DockerContainer!
removeContainer(id: PrefixedID!, withImage: Boolean): Boolean!
}
Container Updates:
type Mutation {
updateContainer(id: PrefixedID!): DockerContainer!
updateContainers(ids: [PrefixedID!]!): [DockerContainer!]!
updateAllContainers: [DockerContainer!]!
refreshDockerDigests: Boolean!
}
Configuration:
type Mutation {
updateAutostartConfiguration(
entries: [AutostartEntry!]!
persistUserPreferences: Boolean
): Boolean!
syncDockerTemplatePaths: Boolean!
resetDockerTemplateMappings: Boolean!
}
Organizer (Feature-flagged):
type Mutation {
createDockerFolder(name: String!, parentId: ID, childrenIds: [ID!]): DockerFolder!
createDockerFolderWithItems(
name: String!
parentId: ID
sourceEntryIds: [ID!]
position: Int
): DockerFolder!
setDockerFolderChildren(folderId: ID!, childrenIds: [ID!]!): DockerFolder!
deleteDockerEntries(entryIds: [ID!]!): Boolean!
moveDockerEntriesToFolder(sourceEntryIds: [ID!]!, destinationFolderId: ID!): Boolean!
moveDockerItemsToPosition(
sourceEntryIds: [ID!]!
destinationFolderId: ID!
position: Int!
): Boolean!
renameDockerFolder(folderId: ID!, newName: String!): DockerFolder!
updateDockerViewPreferences(viewId: ID!, prefs: ViewPreferencesInput!): Boolean!
}
Subscriptions
type Subscription {
dockerContainerStats: DockerContainerStats!
}
Real-time container statistics stream. Automatically starts when first client subscribes and stops when last client disconnects.
Data Models
DockerContainer
Primary container representation with 24+ fields:
{
id: PrefixedID
names: [String!]!
image: String!
imageId: String!
state: ContainerState!
status: String!
created: Float!
// Networking
ports: [ContainerPort!]!
lanIpPorts: [ContainerPort!]!
hostConfig: ContainerHostConfig
networkSettings: DockerNetworkSettings
// Storage
sizeRootFs: Float
sizeRw: Float
sizeLog: Float
mounts: [ContainerMount!]!
// Metadata
labels: JSON
// Auto-start
autoStart: Boolean!
autoStartOrder: Int
autoStartWait: Int
// Template Integration
templatePath: String
isOrphaned: Boolean!
projectUrl: String
registryUrl: String
supportUrl: String
iconUrl: String
webUiUrl: String
shell: String
templatePorts: [ContainerPort!]
// Tailscale
tailscaleEnabled: Boolean!
tailscaleStatus: TailscaleStatus
// Updates
isUpdateAvailable: Boolean
isRebuildReady: Boolean
}
ContainerState
enum ContainerState {
RUNNING
PAUSED
EXITED
}
ContainerPort
{
ip: String
privatePort: Int!
publicPort: Int
type: String! // "tcp" or "udp"
}
DockerPortConflicts
{
containerConflicts: [DockerContainerPortConflict!]!
lanConflicts: [DockerLanPortConflict!]!
}
Caching Strategy
The Docker feature uses cache-manager v7 for performance optimization.
Important: cache-manager v7 expects TTL values in milliseconds, not seconds.
| Cache Key | TTL | Invalidation |
|---|---|---|
docker_containers |
60s | On any container mutation |
docker_containers_with_size |
60s | On any container mutation |
docker_networks |
60s | On network changes |
| Tailscale status | 30s | Automatic |
| Tailscale DERP/versions | 24h | Automatic |
Cache Invalidation Triggers:
start(),stop(),pause(),unpause()updateContainer(),updateContainers(),updateAllContainers()removeContainer()updateAutostartConfiguration()
WebGUI Integration
File Modification
File: unraid-file-modifier/modifications/docker-containers-page.modification.ts
Target: /usr/local/emhttp/plugins/dynamix.docker.manager/DockerContainers.page
When ENABLE_NEXT_DOCKER_RELEASE is enabled and Unraid version is 7.3.0+, the modification:
- Replaces the legacy Docker containers page
- Injects the Vue web component:
<unraid-docker-container-overview> - Retains the
Nchan="docker_load"page attribute (an emhttp/WebGUI feature for real-time updates, not controlled by the API)
PHP Integration
The API integrates with legacy Unraid PHP scripts for certain operations:
- Digest refresh: Calls
DockerUpdate.phpto refresh container image digests - Update status: Reads from
DockerContainers.phpoutput
Permissions
All Docker operations are protected with permission checks:
| Operation | Resource | Action |
|---|---|---|
| Read containers/networks | Resource.DOCKER |
AuthAction.READ_ANY |
| Start/stop/pause/update | Resource.DOCKER |
AuthAction.UPDATE_ANY |
| Remove containers | Resource.DOCKER |
AuthAction.DELETE_ANY |
Configuration Files
| File | Purpose |
|---|---|
docker.config.json |
Template mappings, skip paths, cron schedule |
docker.organizer.json |
Container organization tree and views |
/var/lib/docker/unraid-update-status.json |
Cached container update statuses |
Development
Adding a New Docker Service
- Create service file in
src/unraid-api/graph/resolvers/docker/ - Add to
docker.module.tsproviders and exports - Inject into resolvers as needed
- Add GraphQL types to
docker.model.tsif needed
Testing
# Run Docker-related tests
pnpm --filter ./api test -- src/unraid-api/graph/resolvers/docker/
# Run specific test file
pnpm --filter ./api test -- src/unraid-api/graph/resolvers/docker/docker.service.spec.ts
Feature Flag Testing
To test next-generation Docker features locally:
ENABLE_NEXT_DOCKER_RELEASE=true unraid-api start
Or add to .env:
ENABLE_NEXT_DOCKER_RELEASE=true