Portal Community

Example 1: Pull a Docker Image and Start a Container with Port Mapping

Scenario: A deployment workflow receives a new image tag from a CI system. Pull the image from the registry, create a container with environment variables and a port mapping, then start it.

Step 1 — image/pull
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "image",
  "operation": "pull",
  "Image": "myregistry.io/webapp:{{ vars.image_tag }}",
  "Tag": "{{ vars.image_tag }}"
}
Step 2 — container/create
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "container",
  "operation": "create",
  "Image": "myregistry.io/webapp:{{ vars.image_tag }}",
  "Name": "webapp-{{ vars.deploy_id }}",
  "Env": "APP_ENV={{ vars.environment }}\nDB_HOST={{ vars.db_host }}\nDB_PORT=5432\nSECRET_KEY={{ vars.app_secret_key }}",
  "PortBindings": "{\"8080/tcp\":[{\"HostPort\":\"{{ vars.host_port }}\"}]}"
}
Step 3 — container/start
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "container",
  "operation": "start",
  "ContainerId": "{{ nodes.createContainer.output.containerId }}"
}
Expected outcome: The latest image is pulled from the registry, a new named container is created with injected environment variables, and the container starts with host port mapping active. The container ID is available for subsequent health check or exec steps.

Example 2: Execute a Database Migration Script Inside a Running Container

Scenario: After a new application container is started, run the database migration command inside it. Capture the exit code and route to an error notification node if migrations fail.

Step 1 — container/exec (run migrations)
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "container",
  "operation": "exec",
  "ContainerId": "{{ vars.app_container_id }}",
  "Command": "python manage.py migrate --no-input",
  "Privileged": false
}
Step 2 — IfCondition node (check exit code)
Condition: {{ nodes.runMigrations.output.exitCode }} == 0
True port  → continue deployment workflow
False port → alert node with vars.stderr = {{ nodes.runMigrations.output.stderr }}
Step 3 — container/logs (capture migration output on success)
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "container",
  "operation": "logs",
  "ContainerId": "{{ vars.app_container_id }}",
  "Tail": 50,
  "Timestamps": true
}
Expected outcome: The migration command runs inside the already-running application container. A non-zero exit code routes the workflow to an alert node with the stderr output as the error message. On success, the last 50 timestamped log lines are stored for audit logging.

Example 3: Clean Up Stopped Containers and Dangling Images (Maintenance Pipeline)

Scenario: A scheduled maintenance workflow runs nightly. It lists all containers, removes stopped ones, lists dangling images, and removes them to recover disk space.

Step 1 — container/list (all containers)
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "container",
  "operation": "list",
  "All": true
}
Step 2 — Loop node (iterate over stopped containers)
Collection: {{ nodes.listContainers.output }}
Filter:     {{ item.State }} == "exited"

  Step 2a — container/remove
  {
    "resource": "container",
    "operation": "remove",
    "ContainerId": "{{ item.Id }}",
    "Force": false,
    "RemoveVolumes": false
  }
Step 3 — image/list (dangling images)
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "image",
  "operation": "list",
  "All": true
}
Step 4 — Loop node (remove dangling images)
Collection: {{ nodes.listImages.output }}
Filter:     {{ item.RepoTags }} == null

  Step 4a — image/remove
  {
    "resource": "image",
    "operation": "remove",
    "ImageId": "{{ item.Id }}",
    "Force": false,
    "PruneChildren": true
  }
Expected outcome: All stopped containers are removed, and all untagged (dangling) images are pruned. The workflow logs counts of removed containers and images for the nightly operations digest email.

Example 4: Create an Isolated Network and Connect Microservice Containers

Scenario: An ephemeral integration test run needs an isolated bridge network. Create the network, start an API container and a database container, connect both to the network with DNS aliases, run the tests, then tear down.

Step 1 — network/create
{
  "DockerHost": "unix:///var/run/docker.sock",
  "ConnectionType": "UnixSocket",
  "resource": "network",
  "operation": "create",
  "Name": "test-net-{{ vars.run_id }}",
  "Driver": "bridge",
  "Internal": true,
  "LabelsJson": "{\"run_id\":\"{{ vars.run_id }}\",\"env\":\"test\"}"
}
Step 2 — container/create + container/start (database)
{
  "resource": "container",
  "operation": "create",
  "Image": "postgres:15",
  "Name": "db-{{ vars.run_id }}",
  "Env": "POSTGRES_DB=testdb\nPOSTGRES_USER=testuser\nPOSTGRES_PASSWORD={{ vars.db_password }}"
}
Step 3 — network/connect (database)
{
  "resource": "network",
  "operation": "connect",
  "NetworkId": "{{ nodes.createNetwork.output.networkId }}",
  "ContainerId": "{{ nodes.createDb.output.containerId }}",
  "Aliases": "db,postgres"
}
Step 4 — container/create + container/start + network/connect (API)
{
  "resource": "container",
  "operation": "create",
  "Image": "myrepo/api:{{ vars.image_tag }}",
  "Name": "api-{{ vars.run_id }}",
  "Env": "DATABASE_URL=postgresql://testuser:{{ vars.db_password }}@db:5432/testdb"
}

network/connect:
{
  "NetworkId": "{{ nodes.createNetwork.output.networkId }}",
  "ContainerId": "{{ nodes.createApi.output.containerId }}",
  "Aliases": "api,backend"
}
Step 5 — Teardown: container/remove + network/remove
// Remove API container
{ "resource": "container", "operation": "remove", "ContainerId": "{{ nodes.createApi.output.containerId }}", "Force": true }

// Remove DB container
{ "resource": "container", "operation": "remove", "ContainerId": "{{ nodes.createDb.output.containerId }}", "Force": true }

// Remove network
{ "resource": "network", "operation": "remove", "NetworkId": "{{ nodes.createNetwork.output.networkId }}" }
Expected outcome: Both containers communicate on the isolated internal network using DNS aliases (db, api). No internet access is available. After the test run completes (or fails), all containers and the network are removed — leaving no orphaned resources on the host.

Example 5: Container Health Check Loop — Stop and Restart if Unhealthy Stats

Scenario: A watchdog workflow runs every 5 minutes. It checks the CPU and memory stats for a critical container. If memory usage exceeds 90% of the limit, it restarts the container and sends an alert.

Step 1 — system/ping (verify daemon is reachable)
{
  "DockerHost": "tcp://prod-docker-host:2376",
  "ConnectionType": "TcpTls",
  "TlsCertPath": "/etc/bizfirst/docker-certs/prod",
  "TimeoutSeconds": 10,
  "resource": "system",
  "operation": "ping"
}
Step 2 — container/stats (collect snapshot)
{
  "DockerHost": "tcp://prod-docker-host:2376",
  "ConnectionType": "TcpTls",
  "TlsCertPath": "/etc/bizfirst/docker-certs/prod",
  "resource": "container",
  "operation": "stats",
  "ContainerId": "{{ vars.monitored_container_id }}",
  "Stream": false
}
Step 3 — IfCondition node (memory threshold check)
Condition: {{ nodes.getStats.output.memoryUsageMB }} / {{ nodes.getStats.output.memoryLimitMB }} > 0.9
True port  → Step 4 (restart)
False port → workflow ends (healthy)
Step 4 — container/restart (graceful restart with timeout)
{
  "DockerHost": "tcp://prod-docker-host:2376",
  "ConnectionType": "TcpTls",
  "TlsCertPath": "/etc/bizfirst/docker-certs/prod",
  "resource": "container",
  "operation": "restart",
  "ContainerId": "{{ vars.monitored_container_id }}",
  "Timeout": 30
}
Step 5 — container/logs (capture last 100 lines before restart for audit)
{
  "resource": "container",
  "operation": "logs",
  "ContainerId": "{{ vars.monitored_container_id }}",
  "Tail": 100,
  "Timestamps": true
}
Expected outcome: The daemon reachability is verified before any operation. If the container's memory consumption exceeds 90% of its configured limit, it is restarted with a 30-second graceful stop window. The last 100 log lines are captured before restart and stored in a workflow variable for inclusion in an alert notification.
Production watchdog note: For watchdog workflows targeting a remote Docker host, always use ConnectionType: TcpTls with certificates stored in a secure, access-controlled path. Begin every watchdog run with system/ping to fail fast if the host is unreachable before attempting stat collection or restarts.