docker
stableDocker utilities for generating Dockerfiles, Docker Compose YAML, container API request bodies, environment variable conversion, and Docker API path construction.
use plugin docker::{parse_image_ref, build_dockerfile, build_compose_yaml, …} Functions (12)
- parse_image_ref Parses a Docker image reference into components
- build_dockerfile Builds a Dockerfile string from an instructions table
- build_compose_yaml Builds a docker-compose.yml string from a services table
- container_name Creates a sanitized container name from prefix and ID
- format_port_binding Formats a port binding string
- env_to_table Parses KEY=VALUE env lines into a table
- table_to_env Serializes a table into KEY=VALUE env lines
- parse_log_line Parses a Docker JSON log line
- api_path Returns the Docker API v1.41 path for an operation
- create_container_body Builds a JSON body for container creation
- build_volume_mount Formats a volume mount string
- build_exec_body Builds a JSON body for container exec
Overview
The docker plugin is a pure, dependency-free toolkit for assembling Docker artifacts and Docker Engine API requests from Zolo code. It does not talk to a daemon itself; instead it builds the strings, tables, and JSON bodies you feed to an HTTP client or write to disk — Dockerfiles, docker-compose.yml documents, container/exec request bodies, and /v1.41/... API paths. Every function is stateless and side-effect free, so you can compose them freely to script container workflows. Reach for it when you are generating container configuration, parsing image references and log output, or driving the Docker Engine API over a socket.
Common patterns
Parse an image reference, derive a stable container name, and build the create-container request body:
use plugin docker::{parse_image_ref, container_name, create_container_body, api_path}
let ref = parse_image_ref("registry.example.com/team/api:v3")
let name = container_name(ref["repository"], "prod")
let body = create_container_body(
"{ref["repository"]}:{ref["tag"]}",
name,
#{"NODE_ENV": "production"},
["node", "server.js"],
#{"8080": "8080"}
)
print(api_path("create_container")) // "/v1.41/containers/create"
print(body)
Round-trip environment variables between a table and the KEY=VALUE wire format:
use plugin docker::{table_to_env, env_to_table}
let env_str = table_to_env(#{"DB_HOST": "db", "DB_PORT": "5432"})
let parsed = env_to_table(env_str)
print(parsed["DB_HOST"]) // "db"
Build a Dockerfile and a matching Compose service in one pass:
use plugin docker::{build_dockerfile, build_compose_yaml, format_port_binding}
let dockerfile = build_dockerfile([
#{"instruction": "FROM", "value": "python:3.12-slim"},
#{"instruction": "WORKDIR", "value": "/srv"},
#{"instruction": "CMD", "value": "[\"python\", \"app.py\"]"}
])
print(dockerfile)
print(format_port_binding("8000", "8000")) // "8000:8000/tcp"
let compose = build_compose_yaml(#{
api: #{"image": "myorg/api:latest", "ports": ["8000:8000"]}
})
print(compose)
Parses a Docker image reference into components
Parses a Docker image reference string into a table with registry, repository, tag, and digest. Defaults registry to "docker.io" and tag to "latest" when not specified.
use plugin docker::{parse_image_ref}
let ref = parse_image_ref("gcr.io/my-project/app:v2.1")
print(ref["registry"]) // "gcr.io"
print(ref["repository"]) // "my-project/app"
print(ref["tag"]) // "v2.1"
let simple = parse_image_ref("nginx")
print(simple["registry"]) // "docker.io"
print(simple["tag"]) // "latest"
Digests are surfaced too, so you can pin an image immutably:
use plugin docker::{parse_image_ref}
let pinned = parse_image_ref("alpine@sha256:abc123")
print(pinned["repository"]) // "alpine"
print(pinned["digest"]) // "sha256:abc123"
Builds a Dockerfile string from an instructions table
Builds a Dockerfile string from a table of instruction entries. Each entry is either a table with instruction and value keys, or a raw string line.
use plugin docker::{build_dockerfile}
let df = build_dockerfile([
#{"instruction": "FROM", "value": "node:20-alpine"},
#{"instruction": "WORKDIR", "value": "/app"},
#{"instruction": "COPY", "value": ". ."},
#{"instruction": "RUN", "value": "npm install"},
#{"instruction": "CMD", "value": "[\"node\", \"server.js\"]"}
])
print(df)
Raw string entries are passed through verbatim, letting you mix comments or pre-formatted lines:
use plugin docker::{build_dockerfile}
let df = build_dockerfile([
"# multi-stage build",
#{"instruction": "FROM", "value": "golang:1.22 AS build"},
#{"instruction": "RUN", "value": "go build -o /bin/app"}
])
print(df)
Builds a docker-compose.yml string from a services table
Generates a docker-compose.yml-style string from a services table. Each key is a service name; each value is a table with image, ports (array), and environment (table).
use plugin docker::{build_compose_yaml}
let yaml = build_compose_yaml(#{
web: #{"image": "nginx:latest", "ports": ["8080:80"]},
db: #{"image": "postgres:15", "environment": #{"POSTGRES_DB": "mydb"}}
})
print(yaml)
Creates a sanitized container name from prefix and ID
Creates a sanitized, lowercase container name from a prefix and ID. Non-alphanumeric characters (except - and _) are replaced with -.
use plugin docker::{container_name}
print(container_name("myapp", "worker-1")) // "myapp-worker-1"
print(container_name("svc", "Job #42")) // "svc-job--42"
Formats a port binding string
Formats a port binding in host:container/protocol notation. protocol defaults to "tcp".
use plugin docker::{format_port_binding}
print(format_port_binding("8080", "80")) // "8080:80/tcp"
print(format_port_binding("5353", "53", "udp")) // "5353:53/udp"
Parses KEY=VALUE env lines into a table
Parses a newline-delimited string of KEY=VALUE pairs (as returned by docker inspect) into a table. Lines starting with # and blank lines are ignored.
use plugin docker::{env_to_table}
let env = env_to_table("DB_HOST=localhost\nDB_PORT=5432\n# comment\nDEBUG=true")
print(env["DB_HOST"]) // "localhost"
print(env["DEBUG"]) // "true"
Serializes a table into KEY=VALUE env lines
Serializes a table of key-value pairs into a newline-delimited KEY=VALUE string suitable for use in .env files or Docker API calls.
use plugin docker::{table_to_env}
let env_str = table_to_env(#{"NODE_ENV": "production", "PORT": "3000"})
print(env_str)
// "NODE_ENV=production\nPORT=3000"
Parses a Docker JSON log line
Parses a Docker JSON log line (e.g. from the logs API) into a table with stream ("stdout" or "stderr") and message. Falls back gracefully if the line is not JSON.
use plugin docker::{parse_log_line}
let entry = parse_log_line("{\"log\":\"Server started\\n\",\"stream\":\"stdout\"}")
print(entry["stream"]) // "stdout"
print(entry["message"]) // "Server started"
Non-JSON lines are returned as-is on the stdout stream, so you can handle mixed log sources uniformly:
use plugin docker::{parse_log_line}
let plain = parse_log_line("listening on :3000")
print(plain["stream"]) // "stdout"
print(plain["message"]) // "listening on :3000"
Returns the Docker API v1.41 path for an operation
Returns the Docker Engine API v1.41 URL path for a given operation. Operations without an ID: "list_containers", "create_container", "list_images", "pull_image", "list_networks", "create_network", "list_volumes", "create_volume", "info", "version". Operations requiring an ID: "start", "stop", "restart", "remove", "inspect", "logs", "exec", "kill", "pause", "unpause", "wait", "inspect_image", "remove_image", "inspect_network", "remove_network".
use plugin docker::{api_path}
print(api_path("list_containers")) // "/v1.41/containers/json"
print(api_path("start", "abc123")) // "/v1.41/containers/abc123/start"
print(api_path("logs", "abc123")) // "/v1.41/containers/abc123/logs?stdout=true&stderr=true"
Image, network, and volume operations follow the same convention:
use plugin docker::{api_path}
print(api_path("list_images")) // "/v1.41/images/json"
print(api_path("inspect_network", "bridge")) // "/v1.41/networks/bridge"
print(api_path("create_volume")) // "/v1.41/volumes/create"
Builds a JSON body for container creation
Builds a JSON request body for the Docker POST /containers/create endpoint. env is a table of KEY: VALUE pairs, cmd is an array table of strings, ports is a table of "host_port": "container_port" pairs.
use plugin docker::{create_container_body}
let body = create_container_body(
"node:20",
"my-app",
#{"NODE_ENV": "production"},
["node", "server.js"],
#{"3000": "3000"}
)
print(body)
Formats a volume mount string
Formats a Docker volume mount string as host_path:container_path:mode. mode defaults to "rw".
use plugin docker::{build_volume_mount}
print(build_volume_mount("/data/db", "/var/lib/postgresql/data"))
// "/data/db:/var/lib/postgresql/data:rw"
print(build_volume_mount("/config", "/etc/app", "ro"))
// "/config:/etc/app:ro"
Builds a JSON body for container exec
Builds a JSON request body for the Docker POST /containers/{id}/exec endpoint. cmd is a table (array) of command strings. Both attach flags default to true.
use plugin docker::{build_exec_body}
let body = build_exec_body(["sh", "-c", "echo hello"], true, true)
print(body)