The DockerRuntime provides a containerized sandbox environment for executing agent commands and evaluating results. It wraps the local docker CLI to manage container lifecycles, ensuring that evaluations run in isolated environments without requiring host bind mounts or privileged access.
The DockerRuntime implements the Runtime interface internal/runtime/docker.go59-73 It follows a strict lifecycle managed by the evaluator:
docker create. It configures the image, entrypoint, network policy, and environment variables internal/runtime/docker.go109-154Create phase to ensure it is ready for subsequent Exec calls internal/runtime/docker.go133-142docker exec, and files are moved via docker cp internal/runtime/docker.go54-58docker rm -f. This is skipped if Config.Delete is set to false, allowing manual inspection internal/runtime/docker.go51-52The following diagram illustrates the sequence of CLI commands issued during the Create call.
Sequence: Docker Container Provisioning
Sources: internal/runtime/docker.go109-154 internal/runtime/docker.go159-181
The runtime defaults the workspace to /workspace inside the container internal/runtime/docker.go26
skill-up does not use -v host mounts. This ensures that the agent cannot accidentally modify the host filesystem internal/runtime/docker.go54-58docker cp. When UploadFile is called with a relative path, it is automatically joined with the container's workspace path internal/runtime/docker.go235-241 UploadDir and DownloadDir recursively copy trees between the host and container using the same mechanism internal/runtime/docker.go252-291The runtime supports strict network isolation via the network_policy field in Config:
--network none to the docker create command, completely severing external access internal/runtime/docker.go165-167Environment variables are managed at two levels:
docker create via --env flags internal/runtime/docker.go168-170Exec and applied to the specific docker exec invocation internal/runtime/docker.go312-315Variables are merged literally using mergeIntoEnvBaseline internal/runtime/runtime.go65-73 without shell expansion to maintain consistency across different runtime backends internal/runtime/docker.go394-396
The following diagram maps the logical runtime actions to the specific Go functions and Docker CLI subcommands they trigger.
Mapping: Runtime Interface to Docker CLI
Sources: internal/runtime/docker.go59-102 internal/runtime/docker.go109-154 internal/runtime/docker.go235-241 internal/runtime/docker.go303-345
The runtime uses dockerCLIErr to classify failures from the docker binary internal/runtime/docker.go440-456
Exec was not found inside the container.Close and rollbackRemove use a detached context with a 30-second dockerCleanupTimeout to ensure cleanup completes even if the parent evaluation context is cancelled internal/runtime/docker.go35-36 internal/runtime/docker.go192-201Every major operation is instrumented with OpenTelemetry (OTEL) spans using the internal/observability package internal/runtime/docker.go21-22:
runtime.type="docker", docker.container_id, and docker.image internal/runtime/docker.go420-425Exec method creates a span named runtime.exec and records the command and working directory internal/runtime/docker.go303-310| Feature | Implementation |
|---|---|
| CLI Wrapper | dockerCommandRunner func type internal/runtime/docker.go42 |
| Randomization | 6-byte hex suffix for container names internal/runtime/docker.go28 |
| Entrypoint | Defaults to sleep infinity to keep container alive internal/runtime/docker.go173-174 |
| Shell | Always returns linux POSIX shell internal/runtime/docker.go415-417 |
Sources: internal/runtime/docker.go1-456 internal/runtime/runtime.go1-216