Container Components
Container components are stack-scoped, persistent containers. One component is one service. Atmos owns the image artifact (build/push/pull) and an optional long-running named container lifecycle, discovered by labels derived from the canonical component instance address — not from local state files. You declare them with the same stack-based configuration used for Terraform, Helmfile, Packer, and Ansible.
For the conceptual overview and command walkthrough, see Using Containers. This page is the stack-manifest configuration reference.
Available Configuration Sections
Container components are declared under components.container and use first-class sections (siblings of metadata — not nested under vars):
image- The image reference to run (and the default push/pull target). May be set directly or produced by
build. build- How to build the image —
context,dockerfile,tags,build_args,target,no_cache,pull, and more. Reuses the same shape as thetype: containerworkflow step. run- How to run the long-lived container —
command,ports,mounts,user,run_args,pull,restart, andhealthcheck. env- Container application environment, resolved with secrets. Injected into the running container — not read from
run. composition- Optional composition membership — groups this service into a larger system.
metadata- Component behavior and inheritance (e.g.
metadata.type: abstractfor catalog base components). hooks- Lifecycle event handlers.
Component Structure
A typical container component configuration:
components:
container:
api:
composition: storefront # composition membership (optional)
image: localhost:5001/api:latest
build: # build the image
context: app
dockerfile: Dockerfile
tags:
- localhost:5001/api:latest
run: # run configuration
command: ./api
ports:
- host: 8080
container: 80
mounts:
- source: .
target: /workspace
restart:
policy: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/health"]
interval: 30s
retries: 3
env: # component env (resolved with secrets)
PORT: "8080"
Inheritance (metadata.inherits), catalogs, mixins, and deep-merge work exactly like other component kinds — define an abstract base component with shared run/build defaults and inherit it.
Port Bindings
Use run.ports to publish container ports. host accepts a port number or a
quoted IP:port string. container is the container port, and protocol
defaults to tcp.
components:
container:
portal:
image: my-portal:local
run:
ports:
- host: "127.0.0.1:3000"
container: 3000
A numeric host: 3000 preserves the container runtime's default interface
binding. Use host: "127.0.0.1:3000" for IPv4 loopback or
host: "0.0.0.0:3000" for all IPv4 interfaces. IPv6 requires brackets, for
example host: "[::1]:3000" for loopback or host: "[::]:3000" for all IPv6
interfaces. The address must be an IP literal, not a hostname or interface name.
Loopback binding narrows where the runtime listens, but it is not a firewall. Docker Engine versions before 28.0.0 may expose localhost-published ports to hosts on the same network segment. See Docker's port publishing documentation for details.
Omitting host or setting it to 0 requests an automatically assigned host
port. To request one on a specific address, use host: "127.0.0.1:0" or
host: "[::1]:0". Host ports must be between 0 and 65535; quoted port numbers
such as host: "3000" are also accepted. The same syntax works in container
workflow steps, workflow sandboxes, background container services, and emulators.
Changes to port bindings require removing and recreating the container with
atmos container down followed by atmos container up.
Component-Type Defaults
Define defaults for all container components:
# Apply to all container components
container:
run:
restart:
policy: unless-stopped
# Individual components
components:
container:
api:
image: localhost:5001/api:latest
Complete Example
Running Container Commands
Atmos provides commands that wrap the container lifecycle:
atmos container build api -s dev # build the image from `build`
atmos container up api -s dev # create/start the long-running container (build-on-missing)
atmos container list # all container components + running state
atmos container ps api -s dev # show running state
atmos container logs api -s dev # stream logs
atmos container exec api -s dev -- sh # run a command inside the container
atmos container down api -s dev # stop + rm
atmos container exec allocates a TTY only when stdin is a terminal. It also
works in scripts and pipelines, preserving piped stdin without requesting a TTY.
Additional Runtime Arguments
run.run_args forwards additional arguments to Docker or Podman for both
atmos container up and atmos container run, for example run_args: [--init].
An explicit --network or --net argument takes precedence over Atmos's automatic
shared stack network.
Changes to runtime arguments require removing and recreating
the container with atmos container down followed by atmos container up.
Each instance is named and labeled from its canonical address <stack>/container/<component> (e.g., atmos-dev-container-api), so lifecycle commands discover it by label — there are no local state files.
Containers in the same stack automatically join a shared network and can resolve each other by a <stack>-<component> DNS alias, with no configuration required — see Networking.
CI Reporting
When CI is enabled, atmos container build and atmos container push write a summary for each image to the job summary: the tag, digest, image ID, runtime settings, environment variables, labels, and layers. The job summary always keeps the full report, and every pushed reference gets its own section.
Pull request comments
The same summary can also be posted as a pull request comment. Atmos posts a comment only when all of these are true:
ci.enabledandci.summary.enabledare on, and Atmos runs under a detected CI provider, so the summary reached the provider.ci.comments.enabledistrue. Comments are off by default because they write to the pull request.- A pull request number is known. When none is known, for example on a push to a branch, the comment is posted as a commit comment on the run's commit instead.
- The job token can write comments. On GitHub Actions, grant
pull-requests: write, andcontents: writefor commit comments.
Atmos keeps one comment per image, not one per tag. The comment key is container:image:<registry/repository> with the tag and digest removed, so ghcr.io/acme/api:sha-1a2b3c and ghcr.io/acme/api:latest update the same comment. A build or push replaces the body in place, and a push of several tags lists every reference pushed in that run. Images with different repositories, for example one pushed to two registries, get separate comments.
GitHub rejects comment bodies over 65,536 characters. Atmos truncates the comment body at 65,000 characters and ends it with a note that points to the job summary, which keeps the full report. A comment that cannot be posted logs a warning that names the image and never fails the build or push.
When comments are off, Atmos does not post a comment and does not print a preview of one to the log. Outside CI, the summary is rendered locally as before.
To change the Markdown, point ci.templates.container.image at a template file under ci.templates.base_path:
See CI templates for the template syntax and the data available to the image template.
Related
- Using Containers — Conceptual overview and command walkthrough
- atmos container — Command reference
- Emulator Components — Built on the same container lifecycle
- Component Types Overview
- Configure Environment