docs(docker): correct the container quick start for the private image - #57
Conversation
The published `ghcr.io/apodexai/frontieragent` package is private by org policy, so an anonymous pull fails with `unauthorized`. README.md, docs/install/docker.md and the chooser table all promised a build-free `docker compose run --rm agent`, which sends anyone outside the org to that error on their first command. docs/install/global-install.md and the comment in the publish workflow already state the privacy, so this only aligns the pages a new user lands on first. Because compose.yaml sets `pull_policy: always`, the local-build path has to keep the `compose.dev.yaml` override on every command β its `pull_policy: build` is what keeps the built image in use instead of retrying the registry. That is now spelled out in each quick start. Closes ApodexAI#47 tests/test_container_image_docs.py pins this: 5 of its 8 cases fail on the pre-fix tree. The other 3 are guard rails (a dev override exists, and no block builds locally then runs without the override).
|
Thanks for catching this and putting together the fix! Our org currently doesnβt allow us to make the GHCR image public, so documenting the private image and giving users a local-build path makes sense. I also appreciate you keeping the dev override on the run commands β thatβs an easy detail to miss. I reviewed the changes and thereβs one thing I think we should fix before merging: in βPin a release or another imageβ, the new text says users can use a locally built tag, but the command above still uses FRONTIER_AGENT_IMAGE=frontier-agent:local \
docker compose run --pull never --rm agentOne tiny wording fix too: the βDirect docker runβ section says the image below is the private published image, but the example now uses Otherwise, this looks good to me. I ran the new docs tests and the deployment-config tests locally; all 25 passed. Thanks again for making the setup clearer for people outside the org! |
Two follow-ups to the review on ApodexAI#57. "Pin a release or another image" says any image name works, including one you built and tagged yourself, but the command above it still runs against compose.yaml, which sets pull_policy: always. A tag that exists only on the machine would still be resolved against a registry. That section now has its own example that opts out: FRONTIER_AGENT_IMAGE=frontier-agent:local \ docker compose run --pull never --rm agent The "Direct docker run" section called the reference below the private published image while the command had been changed to frontier-agent:local. It now says which tag the command runs, and points at the published image for the registry case instead. Adds test_documented_local_tag_opts_out_of_the_registry, which fails if a compose run of a local tag loses --pull never. Confirmed by removing the flag and watching that one test fail. python -m pytest tests/test_container_image_docs.py β 9 passed.
|
Both fixed in 1. Local tag in "Pin a release or another image". You're right that the text and the FRONTIER_AGENT_IMAGE=frontier-agent:local \
docker compose run --pull never --rm agentI left the 2. "Direct docker run" wording. It called the reference below the private published image while the command runs On the new test. One detail that bit me and would bite the next person:
PR body updated to mention both. |
Closes #47
Problem
ghcr.io/apodexai/frontieragentis private by org policy β.github/workflows/docker-publish.ymlsays so explicitly:docs/install/global-install.mdsays so too. But the pages a new user lands on first promise a build-free pull. On a clean machine with noghcr.iologin:I confirmed the package is still private against the live registry (not just taking the report's word for it):
Three places carried the wrong promise:
README.mdβ "Containers and local models" told you to rundocker compose run --rm agentdocs/install/docker.mdβ "does not build the repository locally", "Pull and launch the pre-built container"docs/install/README.mdβ the chooser row advertised the "published agent container"What this changes
Docs only. Each quick start now names the two ways to start:
docker login ghcr.ioif your account is authorized for the package, or build this checkout.The build path keeps the
compose.dev.yamloverride on every command, not just the build. That detail is load-bearing:compose.yamlsetspull_policy: alwaysandcompose.dev.yamlsetspull_policy: build, so running without the override makes Compose re-fetch the private registry and fail again even though the image is right there.docker/run.shinvokescompose.yamlalone, so it now says so explicitly.The same wart shows up in "Pin a release or another image": that section says any image name works, including one you built locally, but
compose.yamlstill setspull_policy: always, so a local-only tag would be resolved against a registry. That section now carries its own example that opts out with--pull never, so a locally built tag is usable without editing the compose files.I also dropped
pull_policy: alwaysβmissingoncompose.yamlin a first pass, then reverted it:apodex/tests/test_deployment_config.py::test_default_compose_pulls_release_image_and_preserves_cli_stateassertspull_policy == "always"deliberately, and that looks like an intentional contract rather than an oversight. It is a real wart βmissingwould make a local build usable without the override on every command β so if maintainers want that behaviour change, I'd rather it be a separate PR against a deliberate decision. Happy to split it out on request.Test
tests/test_container_image_docs.pypins the fix, following the existing deployment-config test idiom:--pull neverVerified it fails before and passes after:
Testing
pytest tests/test_container_image_docs.pyβ 8 passedruff check+ruff format --checkon the new file β cleanpytest apodex/tests/test_deployment_config.pyβ 17 passed (the compose contract is untouched)ModuleNotFoundError: agent_core / textual / pypdf, andOSErrorfrom the 99%-full disk); I diffed the failure lists with and without this branch to confirm.I did not run the container itself β no Docker daemon in my sandbox, so
docker compose build/runare unexercised. The compose invocation shapes are copied from the commands already documented indocs/install/docker.mdand pinned by the existing dev-override tests.