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’sCOPY agentd /agentdinto 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_timeoutgives. - A port of 0, or a workdir that is not one absolute path. A relative
WORKDIRresolves against whatever the task left, whitespace splitsRUN mkdir -pinto several directories, and a line break writes an instruction the caller never saw. inherit_workdirwith noWORKDIRanywhere, for the reasonrequire_workdirgives.
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.