Deploy and manage balena multi container applications on edge devices

Usage no npm install needed!

<script type="module">
  import balenaCompose from 'https://cdn.skypack.dev/@balena/compose';


Balena Compose

Balena compose is a Node.js library (and CLI tool) to define, run and update multi-container applications on Docker enabled devices. It is specially targeted for managing the lifecycle Balena applications on edge devices. This means it adds some features to docker-compose that make it more compatible with edge devices.

Balena compose is (will be) used by Balena Supervisor, Balena's on-device agent for managing a single application lifecycle.

This library is still in a highly experimental state and will be until v1.x is reached. Do not use


  • git clone https://github.com/balena-io-playground/balena-compose
  • npm i
  • npm run build

Using the CLI

# Updates the application with the given name on the device.
# Configuration is obtained fom config.json and state info
# is obtained from the state endpoint on the cloud
$ npm run compose -- up -a <appName>

Using the library

import { Composer } from '@balena/compose';

// Construct a new composer for app id (soon to be changed to app uuid)
const composer = new Composer('12345', { 
  uuid: 'deadbeef',
  deviceApiKey: 'abcdef',

// Returns the current container state and version of the app
// with version 12345 (it looks for containers with `io.balena.app=12345`
// if no app exists, it will return
// {status: "Idle", services: {}, networks: {}, volumes: {}}
await composer.state();

// Set the target state for commit 'deafbeef' of the app (soon to be replaced by release-version), 
// see format of a single app in the target state endpoint
// this will throw if the composer cannot reach the target state (there is a lock, cannot fetch images, etc.)
// while this process is taking place, composer.state() should return the state of the application
// install
await composer.update('deadbeef', {services: {main: {...}}, volumes: {}, networks: {}})

// If everything went well this should return the new state of the composer
await composer.state();

Hack week

The main goal of the hack week project is to get to an agreement on what functionality this library and CLI should provide.

Although most of the code that will provide the functionalityof this library is already in the current supervisor codebase, (see compose/), a secondary goal is to simplify and adapt this code to the requirements defined for this library.

Tasks (non-exhaustive)

  • Setup typescript repo
  • [ x] Extract and review typescript types for Composer, Service, Volume and Network from supervisor codebase
  • Define public APIs for the libraries
  • [-] Write tests to specify API behavior
  • Write/adapt modules for
    • Composer
    • Services
    • Volumes
    • Networks
    • Logging
    • Contract validation
    • Delta management
    • Update locks
  • Write CLI

Code Improvement goals

  • Improve test coverage
  • Remove code for legacy use cases, e.g. v2 deltas, legacy labels.
  • Reduce the need for additional storage for current state, which forces to synchronize multiple sources of truth. Whenever possible, application meta data should be stored on docker labels.
  • Improve code typing, avoid using as any as much as possible.
  • Improve module isolation and external state manipulation
  • Reduce the need for external dependencies whenever possible.
  • Look for ways to make code more declarative

Future goals

Support compose the compose specification https://compose-spec.io/