Portal Community

When to Use

  Logs are retrieved from the Docker daemon's log buffer, not from files inside the container. For very high-volume containers, consider using a tail parameter in the Docker API to limit the response size. This node returns the full log buffer by default.

Configuration

Connection Fields

FieldTypeDefaultDescription
dockerHoststringunix:///var/run/docker.sockDocker socket path or TCP endpoint
connectionTypestringunixsocketunixsocket | tcp | tcptls
tlsCertPathstringTLS certificate directory. Required for tcptls. optional
timeoutSecondsint30Operation timeout. Increase for containers with large log buffers. optional

Operation Fields

FieldTypeRequiredDescription
resourcestringrequiredMust be container
operationstringrequiredMust be logs
ContainerIdstringrequiredContainer ID (full or short) or container name

Sample Configuration

{
  "resource": "container",
  "operation": "logs",
  "ContainerId": "batch-job-20240101",
  "connection": {
    "dockerHost": "unix:///var/run/docker.sock",
    "connectionType": "unixsocket",
    "timeoutSeconds": 60
  }
}

Validation Errors

Error CodeTriggerResolution
MISSING_INPUTContainerId is emptyProvide the container name or ID.
NOT_FOUNDContainer does not existContainer may have already been removed. Always collect logs before calling container/remove.
DOCKER_API_ERRORDaemon error retrieving logsCheck daemon logs. May occur if the container's log driver does not support log retrieval (e.g. none log driver).
CONFIG_ERRORConnection settings invalidVerify dockerHost and connectionType values.

Output

Success Port

FieldTypeDescription
logsstringCombined stdout and stderr output
stdoutstringStandard output only
stderrstringStandard error only
statusstringsuccess
resourcestringcontainer
operationstringlogs

Error Port

On failure, the error port receives errorCode, message, resource, and operation. If logs retrieval is part of a cleanup sequence, ensure the error port continues the workflow rather than halting (e.g. proceed to container removal even if logs are unavailable).

Sample Output

{
  "logs": "[2024-01-01T08:00:05Z] INFO  Starting batch processor\n[2024-01-01T08:00:06Z] INFO  Processing 1,542 records\n[2024-01-01T08:02:31Z] INFO  Batch complete. Processed: 1542, Errors: 0\n[2024-01-01T08:02:31Z] INFO  Output written to /app/output/results.json",
  "stdout": "[2024-01-01T08:00:05Z] INFO  Starting batch processor\n[2024-01-01T08:00:06Z] INFO  Processing 1,542 records\n[2024-01-01T08:02:31Z] INFO  Batch complete. Processed: 1542, Errors: 0\n[2024-01-01T08:02:31Z] INFO  Output written to /app/output/results.json",
  "stderr": "",
  "status": "success",
  "resource": "container",
  "operation": "logs"
}

Expression Reference

ExpressionReturns
{{ $output.logs }}Full combined log output string
{{ $output.stdout }}Standard output stream only
{{ $output.stderr }}Standard error stream only
{{ $output.stderr.length > 0 }}Boolean — true if there is any stderr output
{{ $output.logs.split('\n').length }}Number of log lines
{{ $output.logs.includes('ERROR') }}Boolean — true if any error lines appear in combined logs
{{ $output.logs.split('\n').slice(-10).join('\n') }}Last 10 lines of combined log output

Node Policies & GuardRails

PolicyDetail
Collect logs before removeAlways place container/logs before container/remove in cleanup workflows. Post-removal log retrieval is not possible.
Do not log sensitive outputContainer logs may contain credential values printed at startup. Avoid writing raw logs output to workflow execution history without redaction.
Handle large log buffersLong-running containers may produce megabytes of logs. Increase timeoutSeconds and consider adding a Function node to trim logs to the last N lines before forwarding.
No remote TCP without TLSUse tcptls for remote Docker hosts.
Read-only operationcontainer/logs is non-destructive. It does not affect container state and can be called on running or stopped containers.

Examples

Example 1: Retrieve and parse CI test results

// Node 1: container/logs
{ "resource": "container", "operation": "logs", "ContainerId": "test-runner-{{ $trigger.buildId }}" }

// Node 2: Function node — parse test output
const lines = $input.stdout.split('\n');
const passed = lines.filter(l => l.includes('✓') || l.includes('PASS')).length;
const failed = lines.filter(l => l.includes('✗') || l.includes('FAIL')).length;
return { passed, failed, totalTests: passed + failed, raw: $input.stdout };

Example 2: Send last 50 lines of logs to Slack on container failure

// Node 1: container/logs (after inspect reveals exit code != 0)
{ "resource": "container", "operation": "logs", "ContainerId": "{{ $trigger.containerName }}" }

// Node 2: Function node — trim to last 50 lines
const lastLines = $input.logs.split('\n').slice(-50).join('\n');
return { excerpt: lastLines };

// Node 3: Slack node
// message: "Container {{ $trigger.containerName }} crashed.\n```{{ $nodes.trimLogs.output.excerpt }}```"

Example 3: Archive logs to S3 before container removal

// Node 1: container/logs
{ "resource": "container", "operation": "logs", "ContainerId": "job-{{ $trigger.jobId }}" }

// Node 2: S3 node — put object
{
  "bucket": "bizfirst-container-logs",
  "key": "jobs/{{ $trigger.jobId }}/{{ $now | date('YYYY-MM-DD') }}/stdout.log",
  "body": "{{ $output.logs }}"
}

// Node 3: container/remove (logs safely archived)