Running containers with the Docker CLI

3 min read · Intermediate


protect-dockerd speaks the Docker Engine HTTP API over a Unix socket and translates each request into Edera Protect zone and workload operations. Point the standard docker CLI, or any Docker-SDK-speaking tool at it, and you get Protect isolation without installing Docker or containerd on the host.

What’s supported

The supported Docker Engine API version is v1.45.

protect-dockerd implements the container, image, and exec surface everyday docker usage needs: create, start, stop, kill, wait, attach, exec, logs, rm.

The following is not supported:

  • Legacy docker build (see Building images with Docker Buildx for the supported path)
  • docker volume *
  • docker network *, beyond the implicit default network
  • docker stats
  • docker events
  • docker pause/unpause
  • docker cp, docker commit, docker save/load/export
  • Restart policies
  • Port mapping enforcement—no iptables/portmap rules are installed
  • Swarm, plugin, and distribution endpoints

How it works

Each Docker container maps 1-to-1 onto a Protect zone + workload pair: protect-dockerd creates the zone, launches the workload inside it, and tracks the mapping in its local state (container name, config, status, log path, zone/workload UUIDs). The Protect daemon’s gRPC socket is the only runtime dependency—no Docker, no containerd, no CNI plugins.

docker CLI / SDK
        │  Docker Engine API (HTTP/1.1 over Unix Domain Socket)
        │  /var/run/edera-docker.sock
protect-dockerd
        │  Protect control service (gRPC)
        │  /var/lib/edera/protect/daemon.socket
protect-daemon
        └── Zone ── Workload (OCI image, process, mounts)

IP addressing is entirely daemon-managed—protect-dockerd doesn’t run a CNI plugin pipeline or manage network namespaces itself.

Prerequisites

  • A host running protect-daemon
  • protect-dockerd installed
  • The docker CLI (or a Docker SDK client)

Start protect-dockerd

protect-dockerd \
  [DAEMON_PATH]   # default: /var/lib/edera/protect/daemon.socket
  [LISTEN_PATH]   # default: /var/run/edera-docker.sock
  [DATA_PATH]     # default: /var/lib/edera/protect/docker

protect-dockerd needs root, or at least enough privilege to reach the Protect daemon socket and write to /var/run.

Point the Docker CLI at it

export DOCKER_HOST=unix:///var/run/edera-docker.sock
docker run --rm alpine:latest echo hello

Or target the socket per-command without exporting DOCKER_HOST:

docker -H unix:///var/run/edera-docker.sock run -d --name web nginx:latest

Container lifecycle

Each docker command drives the Protect zone and workload lifecycle underneath:

Docker commandWhat happens
docker createThe daemon records the container in its local state (no zone yet)
docker startA zone is created, with a workload started in it; a log watcher streams logs to disk
docker stopThe workload is stopped gracefully, with a default timeout of 10 seconds
docker killA KILL signal maps to an immediate stop, any other signal to the same graceful path as docker stop
docker rmThe workload and zone are deleted, as well as the the container recorded in the local state
docker run --rmAll of the above; the container is auto-removed on exit

Zone and workload UUIDs live in the ContainerRecord, so docker rm (or a crash-recovery pass) can always find the right resources to tear down.

Logs

Each container’s stdout/stderr is captured to Docker’s standard json-file format:

{DATA_PATH}/containers/{container-id}/{container-id}-json.log
{"log":"hello\n","stream":"stdout","time":"2026-01-31T07:00:00.000000000Z"}

docker logs reads this file from disk. Add --follow on a running container, and protect-dockerd also opens a live console stream and tails it after the on-disk history.

Exec into a container

docker exec -it mycontainer sh

docker exec tunnels stdin/stdout/stderr over a bidirectional gRPC stream to the workload, the same way docker attach and docker logs --follow do.

Current limitations

protect-dockerd doesn’t currently reconcile its local state against live daemon zones and workloads on startup. A container recorded as Running that the Protect daemon no longer knows about stays in that state until you remove it with docker rm -f.

Further reading

Last updated on