Container manifest¶
A container is normally declared as part of a cell's spec.containers, not as a top-level resource. The standalone shape still exists for CLI-level operations (kuke get container …).
apiVersion: v1beta1
kind: Container
metadata:
name: web
labels: {}
spec:
id: web
realmId: main
spaceId: default
stackId: default
cellId: hello-world
root: true
image: docker.io/library/nginx:alpine
command: /bin/sh
args:
- -c
- "exec nginx -g 'daemon off;'"
env:
- "NGINX_HOST=example.com"
ports: []
volumes:
- source: /srv/html
target: /usr/share/nginx/html
readOnly: true
networks: []
networksAliases: []
privileged: false
cniConfigPath: ""
restartPolicy: ""
status:
state: Ready
startTime: "2026-04-21T12:00:00Z"
finishTime: "0001-01-01T00:00:00Z"
exitCode: 0
restartCount: 0
...
See Concepts → Container for what a container is.
spec¶
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Container identifier (matches metadata.name) |
containerdId |
string | no | Populated by Kukeon with the containerd-level container id |
realmId |
string | yes | Realm that owns the container |
spaceId |
string | yes | Space that owns the container |
stackId |
string | yes | Stack that owns the container |
cellId |
string | yes | Cell that owns the container |
root |
bool | no | Mark this as the cell's root container (owns the network namespace) |
image |
string | yes | OCI image reference. Kukeon passes this to containerd's image pull. |
command |
string | no | Command to run. If omitted, the image's ENTRYPOINT is used. |
args |
array of string | no | Arguments. Combined with command. |
env |
array of string | no | KEY=VALUE environment variables |
ports |
array of string | no | Reserved — port mapping semantics are not finalized |
volumes |
array of VolumeMount |
no | Bind-mount host paths into the container (see VolumeMount) |
networks |
array of string | no | Additional CNI networks to join beyond the cell's default |
networksAliases |
array of string | no | DNS aliases for the container within its CNI networks |
privileged |
bool | no | Run privileged (full capabilities, access to /dev, etc.) |
hostCgroup |
bool | no | Opt the container into its parent's cgroup namespace (see Host cgroup mode) |
secrets |
array of ContainerSecret |
no | Inject credentials resolved by the daemon — never written to status or YAML (see ContainerSecret) |
cniConfigPath |
string | no | Override the CNI config directory for this container |
restartPolicy |
string | no | Restart policy. Reserved — restart semantics are not finalized. |
Fields marked reserved
ports and restartPolicy are accepted by the schema today but their semantics are still being designed. Values round-trip (you can read back what you applied), but the controller does not act on them. See GitHub Issues for the backlog.
VolumeMount¶
Each entry in spec.volumes is a mount attached to the container. The kind discriminator selects which OCI mount type the runtime emits.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
bind|tmpfs |
no | Mount type. Empty means bind for back-compat with YAML authored before the discriminator existed. |
source |
string | yes for bind |
Absolute host path. Must exist at apply time. Named / managed volumes are not supported. Must be empty for kind: tmpfs. |
target |
string | yes | Absolute path inside the container |
readOnly |
bool | no | Mount read-only when true (writes fail with EROFS). Defaults to false. |
sizeBytes |
int | no (tmpfs only) |
Tmpfs size in bytes. When non-zero, the standard tmpfs size= option is set. Ignored for bind. |
mode |
uint | no (tmpfs only) |
Tmpfs root-directory mode (e.g. 0755). When non-zero, the standard tmpfs mode= option is set. Ignored for bind. |
volumes:
- source: /srv/html
target: /usr/share/nginx/html
readOnly: true
- kind: tmpfs
target: /tmp
sizeBytes: 268435456 # 256 MiB
mode: 0755
ContainerSecret¶
Each entry in spec.secrets references a credential the daemon resolves at apply time. Only the reference is persisted — the resolved value never appears in kuke get -o yaml, in object status, or in daemon logs.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Environment-variable name (default mode) or basename of the mounted secret file when mountPath is set |
fromFile |
string | one of required | Absolute host path the daemon reads at apply time. Missing files produce a clear error. |
fromEnv |
string | one of required | Name of an environment variable set on the daemon host. Missing env vars produce a clear error. |
mountPath |
string | no | Absolute path inside the container. When set, the secret is staged with mode 0400 and bind-mounted read-only instead of being injected as an env var. |
Exactly one of fromFile / fromEnv must be set. Example:
secrets:
- name: ANTHROPIC_API_KEY
fromFile: /etc/kukeon/secrets/anthropic.key
- name: GITHUB_TOKEN
fromEnv: GITHUB_TOKEN_SCOPED
- name: tls.crt
fromFile: /etc/kukeon/secrets/tls.crt
mountPath: /run/secrets/tls.crt
File-mount mode stages secrets under /run/kukeon/secrets/<containerdId>/<name> on the host, with owner-only read perms, then bind-mounts them read-only into the container. Because containerd persists resolved env vars in its own runtime spec, env-injection mode leaves the value in containerd's state; file-mount mode keeps it only in the tmpfs staging file.
Managed /etc/hosts and /etc/hostname¶
Every container in a cell sees a managed /etc/hostname and (unless its cell's root container runs with hostNetwork: true) a managed /etc/hosts, bind-mounted in by kukeond.
/etc/hostnamecontains the cell's name plus a trailing newline. All containers in the same cell agree on the hostname./etc/hostscarries the standard localhost block plus a<cellIP>\t<cellName>line once CNI ADD has assigned the cell's address. The cell IP line is filled in once the cell is reachable; before that, only the localhost block is present.
Host-network cells (cells whose root container is declared with hostNetwork: true — the kukeond carve-out) inherit the host's /etc/hosts directly; kukeond does not overlay one.
KUKEON_* identity environment variables¶
Kukeon exports the container's location in the realm/space/stack/cell hierarchy as environment variables visible to the process at startup:
| Variable | Value |
|---|---|
KUKEON_REALM |
The container's realm name |
KUKEON_SPACE |
The container's space name |
KUKEON_STACK |
The container's stack name |
KUKEON_CELL_NAME |
The container's cell name |
KUKEON_CONTAINER_ID |
The container's spec.id |
KUKEON_CGROUP_PATH |
Absolute cgroup path of the cell |
KUKEON_CELL_PROFILE_NAME |
Name of the cell profile that materialized the cell, when applicable |
These pairs are appended to the container's effective environment so user-declared spec.env entries still take precedence on collision.
Host cgroup mode¶
spec.hostCgroup: true opts the container into its parent's cgroup namespace — the runtime omits the cgroup LinuxNamespace from the OCI spec, and the container sees the host cgroup tree directly instead of seeing its own cgroup as /.
Set this only for cells that hosts a nested runtime (containerd, runc, dockerd, an inner kuke init) that needs to write cgroups outside its own subtree. For ordinary workload containers, leave it false (the default). The canonical use case is the kukeond cell in dev-init phase 2.
status¶
| Field | Type | Description |
|---|---|---|
name |
string | Matches metadata.name |
id |
string | Containerd container id |
state |
Pending, Ready, Stopped, Paused, Pausing, Failed, Unknown |
Lifecycle state |
restartCount |
int | Times the container has restarted |
restartTime |
RFC3339 timestamp | Last restart |
startTime |
RFC3339 timestamp | Current (or last) start |
finishTime |
RFC3339 timestamp | When the task exited (zero-value if still running) |
exitCode |
int | Exit code of the last run (0 if still running) |
exitSignal |
string | Signal that terminated the task, if any |
Minimal (embedded in a cell)¶
containers:
- id: web
image: docker.io/library/busybox:latest
command: /bin/sh
args:
- -c
- "echo hello && sleep 3600"
Only id and image are strictly required when embedded inside a cell — the realmId, spaceId, stackId, and cellId are inherited from the parent cell's spec.