Skip to main content
Core sitectl compose up performs a command-scoped reconcile for local contexts owned by an installed plugin. The contract belongs to core sitectl, not to an individual app template. The goal is a smooth first start for setup-only checkouts:
sitectl create app/default --setup-only --path ./app --type local --checkout-source template
sitectl compose up
The first compose up can initialize missing files, build missing local images, and start the stack. A fresh sitectl create --setup-only may already run clone-time init; reconcile checks artifacts before deciding what is still needed. Later calls use a local cache unless the plugin create metadata or image override file changes. Cache entries expire after 7 days so long-lived local checkouts are rechecked periodically.

Flow

For local plugin-owned contexts, core sitectl compose up:
  1. Loads the active context and the plugin’s default create definition, or the first create definition when none is marked default.
  2. Checks the local reconcile cache. The cache key includes host, user, plugin, canonical project directory, docker-compose.override.yml fingerprint, and create spec fingerprint. Entries older than 7 days are ignored.
  3. If there is no cache hit, inspects desired state:
    • missing or empty InitArtifacts make Initialized=False
    • missing InitVolumes make Initialized=False
    • missing local images or build-arg overrides make ImagesAvailable=False
    • when explicit metadata is absent, core falls back to docker compose config --format json and checks file-backed secrets, named service volumes, and buildable services
  4. Runs DockerComposeInit when init is needed.
  5. Runs DockerComposeBuild when images are needed.
  6. Runs DockerComposeUp.
  7. Marks the current host, user, project, override fingerprint, and create-spec fingerprint as checked after the commands succeed.
The cache is marked only after the selected commands complete successfully. If a command fails, the next sitectl compose up inspects and retries instead of assuming the project is reconciled.

Operator Commands

Run reconcile directly when you want to inspect or repair the init/build/up workflow without relying on the automatic compose up hook:
sitectl compose reconcile
sitectl compose reconcile --force
sitectl compose reconcile --reset-init
--force bypasses the cache and reruns build/up. It only reruns init when the declared init state is missing. --reset-init removes plugin-declared init artifacts and init volumes first, then runs reconcile. Use sitectl compose clean when local runtime state should be destroyed:
sitectl compose clean
clean runs docker compose down -v, removes plugin-declared init artifacts, and clears the reconcile cache entry. It requires typed confirmation because database volumes, uploaded files stored in named volumes, generated secrets, certificates, and declared env files can be lost.

Conditions

Reconcile status uses Kubernetes-style condition vocabulary for local facts:
ConditionMeaning
InitializedRequired init files and volumes are present, or fallback Compose checks pass.
ImagesAvailableRequired local images exist, no build policy requires a build, and build-arg overrides have been applied.
ReconciledNo init or build work is needed for this project/spec/override state.
Condition status values are True or False. ObservedGeneration records the create-spec fingerprint that was inspected.

Kubernetes Analogy Boundary

The vocabulary is deliberately familiar to contributors who have used Kubernetes controllers:
  • “reconcile” means compare desired metadata with observed local project state, then run the missing lifecycle steps
  • conditions report current facts rather than command history
  • ObservedGeneration records which desired create-spec fingerprint was checked
The analogy stops there. This is not a Kubernetes controller, background control loop, scheduler, or distributed reconciler. It is a synchronous CLI workflow for one local project. There is no API server, watch stream, lease, work queue, leader election, multi-worker retry contract, or Kubernetes-style eventual consistency guarantee. That boundary is important for plugin authors. Lifecycle commands must be safe to retry because users can rerun sitectl compose up after a failure, but core does not provide a persistent controller that will eventually converge the project without another CLI invocation.

Plugin Authoring Contract

Create definitions that participate in reconcile should follow these rules:
  1. Keep DockerComposeInit, DockerComposeBuild, and DockerComposeUp idempotent enough to rerun after partial failure.
  2. Make InitArtifacts explicit and deterministic. Prefer files such as .env and secret files over probing container state.
  3. Use ValueFrom: plugin.InitArtifactValueFromHostUID when a generated marker file must match the local host user.
  4. List named Compose volumes that prove first-start state in InitVolumes. Core resolves the actual Docker volume name through docker compose config.
  5. List locally built images in Images with the Compose service name, image reference, and build policy.
  6. Use BuildPolicyIfNotPresent for normal local images, BuildPolicyAlways only when every compose up should rebuild, and BuildPolicyNever for images that should not trigger the build phase.
  7. Avoid global mutable state in lifecycle commands. The same project path, create spec, and override file should produce the same result.
  8. Do not make init destructive. Existing application data must survive a repeated init command.
  9. Declare app services that require MariaDB with depends_on: {mariadb: {condition: service_healthy}} so startup and healthcheck behavior match the template contract.
  10. Keep plugin namespace commands app-specific. Shared lifecycle belongs to core sitectl compose.

Image Overrides

Core sitectl image set writes docker-compose.override.yml for local contexts:
sitectl image set --tag wp=nginx-1.30.3-php84
sitectl image set --image app=ghcr.io/example/app:pr-123
sitectl image set --build-arg app.BASE_IMAGE=libops/app:php84
Image overrides affect reconcile:
  • an explicit image override for a service means core does not require the plugin’s default image to exist locally
  • a build-arg override triggers the build phase so the new arguments are applied
  • the override file fingerprint is part of the reconcile cache key
Use --image or --build-arg for app-specific services that are not known to the shared --tag map. Use sitectl image clear [SERVICE...] to remove image/build-arg override keys while preserving unrelated local override content such as dev-mode bind mounts or port remaps.