Skip to main content
A service is a named application component within a project. Each replica runs a container from an OCI (Open Container Initiative) image, which supplies the application and its runtime dependencies. The image can be supplied directly or built from a Dockerfile. Uniac adds no SDK or runtime dependency to the application.

Definitions and deployments

A service definition supplies reusable image and runtime configuration. A deployment declaration instantiates it as a service in the target project, named by the declaration. Several declarations can instantiate one definition, each as its own service. Deploying the project includes the service of every deployment declaration. A service’s replicas are its running containers. Its identity persists across replica replacements and deployment versions. Stateless services can run multiple container replicas behind the same service identity. A singleton service runs at most one replica at a time: during replacement, the previous replica stops before its successor starts. Data that must outlive a replica is written to an attached volume.

Required and optional configuration

A start command is split into arguments with shell-style quoting, and its first argument is executed directly.

Build source

A build source identifies the source tree, build context, Dockerfile, and target stage. Each setting has a default: Paths are relative and checked lexically: root must stay within the defining package directory, and context and dockerfile within the root. In a workspace, each included manifest keeps its own source directory, and its build context stays within that package.

Networking and endpoints

Services are addressable as <service>.internal within their project, and internal communication needs no port declarations. A service is private to its project until it declares a public endpoint. The application chooses its listen port, and each public endpoint names that port. An application that reads PORT gets it from a declared environment variable.

Public endpoints

A public endpoint forwards incoming traffic to the application’s listen port. Endpoints are declared with the service’s deployment declaration, independently of its reusable definition. Public exposure is optional. Each requested endpoint specifies: Each service can have one http and one tcp endpoint, on ports 1–65535.

Environment and references

Environment variables provide runtime configuration to a service’s containers. Their values can refer to the service’s own configuration or to another service declared in the same package. The platform resolves declared values when the deployment is created and injects them at container start. Other environment defaults are the image’s own. Environment configuration is optional. Each declared variable requires a name and a plaintext string value, optionally containing references. Names match ^[A-Za-z_][A-Za-z0-9_]*$; host is reserved for the builtin reference. A service accepts at most 64 declared variables, with names up to 128 characters and values up to 4096 characters. Declared values are stored with the deployment, and the dashboard shows the serving deployment’s values. Changing a value deploys a new version.

References

A reference’s scope names a service, independently of its definition name. ${{self.VAR}} names a variable on the declaring service. The one builtin, host, is the referenced service’s internal hostname. References have this grammar:
Chains resolve transitively. Across a chain, self remains bound to the service that declared each value. Every ${{ opener must form a valid reference.

Resolution

References to self must name a builtin or a declared variable. Composition checks references to the other services declared in the package against their declared variables and builtins. Unknown names, cross-package references, and ungrounded value-reference cycles fail locally. Remote references use services with a serving deployment. For those services, host supplies the internal hostname without requiring a running replica; a custom-variable reference requires that variable in the service’s resolved environment. A reference resolves when the declaring service’s deployment is created, against the services serving at that moment, and the resolved values stay with that deployment. A service picks up a new or changed value from another service on its own next deployment. A variable whose referenced service starts serving later is omitted with a warning and filled in by that next deployment.

YAML composition example

In YAML composition, type: service selects stateless execution and type: singleton selects singleton execution. Exactly one of image or build supplies the container source; image: "" counts as absent. Optional configuration uses env, the start_command string, and the volumes list. env maps variable names to string values. build accepts a string naming the build root or an object containing the build fields above. An empty string selects the default root; build: null is invalid. Each build root is relative to the directory containing its definition’s uniac.yaml. A deployment declaration’s optional replicas is an integer. Omitted or null, the service keeps its current count on deployment. A deployment declaration’s public_ports is an optional list of mappings, each with port and type. Its presence has three meanings on deployment: The web-code and cache-code resources are definitions, and the web and cache deployment declarations instantiate them as the services web and cache. The from field connects each declaration to its definition in this package. The stateless web service runs two replicas and receives the URL declared by cache, which uses cache’s own internal hostname. The web service’s port 8080 is exposed through HTTPS and a separately allocated raw TCP endpoint. The singleton cache service starts Redis with append-only persistence on a 1 GB volume mounted at /data.
The generated description uses container.source.ref for image and container.source.build for build. type: singleton adds kind: singleton, while type: service omits kind. Build paths are normalized and omitted at their defaults; an all-defaults build is {}.

Runtime and deployment versions

In live state, a deployment is a version of one service, with its own lifecycle and running containers. Redeploying a declaration updates its service, and a service keeps its execution type across versions; a deployment that changes the type is rejected. Each uniac deploy creates a new version of every declared service. The new version runs the declaration’s replicas count. Without one, it keeps the requested count of the serving version, or of the newest active version when none is serving, including zero; a service with neither starts with one replica. The new version replaces the running replicas; a singleton’s previous replica stops first. The platform observes container-process liveness and restarts a container whose process exits. After five consecutive restarts that each ran for less than a minute, the container stays stopped.

Observed state

Dashboard and removal

A service’s dashboard page shows its state, public endpoints, deployment activity and resource usage. It sets the replica count (0 to 4 for a stateless service, 0 or 1 for a singleton), which later deployments keep unless their declaration sets replicas. It also changes public endpoints and offers Delete service, confirmed by typing the service’s name. Deleting a service stops its replicas and removes its deployments, images and public endpoints. The service reports terminating until the removal completes, and is then gone. Its volume is detached and keeps its data; the volume lifecycle governs its retention and deletion.