Skip to main content

wrap_dockerfile

Function wrap_dockerfile 

Source
pub fn wrap_dockerfile(task: &str, opts: &WrapOptions) -> Result<String, Error>
Expand description

A task Dockerfile with the agentd stanza appended: the one call a harness needs to go from the Dockerfile a task brings to one this client can build (#220).

The result is the task text verbatim, a newline if it lacked one, USER root when the task’s last USER is anyone else, and then default_dockerfile’s stanza for opts.port and opts.workdir — the same function, so the two cannot drift (IMAGE-1). The stanza’s ENTRYPOINT [] and CMD ["/agentd"] are the result’s last instructions, so whatever entrypoint, command, or port the task set, the daemon is the container’s process and listens where the hooks are called (IMAGE-2). Pair it with BaseImage::from_dockerfile for the create call’s FROM guard (IMAGE-4).

§USER root, only when the task changed user

The daemon demotes each exec to the user it names, which takes root; a task that ends on USER app would otherwise start the daemon as app. The line is written only when the last USER is not root, so a task that never changes user wraps to exactly the default stanza — writing it unconditionally would make the default Dockerfile and the wrap of a bare FROM two different texts (crates/model/src/wrap.rs, AlwaysUserRoot).

§What is refused, and why each is a refusal (IMAGE-3)

Each is a Dockerfile the build would accept and the guest would then fail on, one build cycle later and naming none of the cause:

  • No FROM. Nothing to append to, and no base to derive.
  • An unfinished last instruction. A trailing line continuation — in the escape character the # escape= directive selects, across the blank and comment lines Docker skips inside one — joins the stanza’s COPY agentd /agentd into the task’s last instruction; an unterminated heredoc swallows the whole stanza as its body. Either way the image has no daemon and the build fails as a run-hook timeout.
  • A keepalive at or over the client’s stream idle timeout, for the reason require_keepalive_under_idle_timeout gives.
  • A port of 0, or a workdir that is not one absolute path. A relative WORKDIR resolves against whatever the task left, whitespace splits RUN mkdir -p into several directories, and a line break writes an instruction the caller never saw.
  • inherit_workdir with no WORKDIR anywhere, for the reason require_workdir gives.

The scan reads instructions the way the Dockerfile parser does for these questions — escape directive, continuations, comments, heredoc bodies — and no further: it finds a Dockerfile that cannot take the stanza, it does not validate one.