Skip to main content

Deploying your own Docker apps

This article refers to SDK version v0.5.0. The current SDK version is N/A.

Overview

A Docker app in the product is one you author yourself, packaged the same way described in Docker apps: a zip file with a docker-compose.yaml at its root, as opposed to a Marketplace app published in Barbara's marketplace (see Marketplace workload deployment). The SDK's method names follow this same split: create_docker_workload for this guide, create_marketplace_workload for the other. Getting a Docker app running takes three steps: register the application, upload a version, deploy it. This guide walks each step field by field, using the SDK in place of the App Library UI.

Concept

App Library. The catalog in Barbara Panel of every application, Docker or Marketplace, an organization has registered and can deploy to its nodes, the same registry client.applications manages through the SDK.

Learn more

Register the application

client.applications.create(
"edge-app", "Long description", "Barbara", docker=True, icon_path="./icon.png"
)

create(name, long_description, developer, *, docker, short_description=None, icon_path=None) on client.applications mirrors the fields of the New Application popup in the App Library:

ParameterTypePanel equivalent
namestrName
long_descriptionstrDescription
developerstrNot directly shown in the New Application popup, but recorded against the application (visible via get/update)
dockerboolApplication type: True selects Docker, matching every workflow in this guide
short_descriptionOptional[str]A shorter summary, not exposed in the basic New Application form but readable/settable via update
icon_pathOptional[str]The icon you'd otherwise upload by clicking the grey square in the popup

icon_path is a local file path, not a URL or bytes: pass the path to a PNG on disk (for example "./icon.png"), and the SDK reads the file and uploads it as multipart/form-data for you. The method returns None, so call client.applications.list(search="edge-app") afterwards if you need the new application's id, since create doesn't hand it back directly.

Upload a version

client.applications.create_version(
"<application-id>", "./app-v1.tar", "1.0.0", ["amd64"], ["Initial release"]
)

create_version(application_id, artifact_path, name, architectures, release_notes) is positional, unlike most other create methods in the SDK:

ParameterTypeWhat to pass
application_idstrThe id from the application you just registered; look it up with client.applications.list(search=...) if create didn't return it to you
artifact_pathstrA local file path to the zip containing your docker-compose.yaml and, conventionally, a ./persist/ folder, exactly what you'd otherwise drag into the UPLOAD FILE dialog of the New Version popup
namestrThe version string. Panel suggests the x.y.z convention; the SDK doesn't enforce it, but sticking to it keeps this application consistent with every other one in your Library
architecturesList[str]The CPU architectures this build supports, matching the compatible platforms checkboxes in the New Version popup, for example ["amd64"] or ["amd64", "arm64"]
release_notesList[str]One string per bullet point of release notes; pass an empty list [] if you have none

Like create, artifact_path and icon_path are read from local disk and uploaded as multipart/form-data, so the SDK builds the whole upload request for you from a plain file path. Both create and create_version also accept a keyword-only timeout, overriding the client's default request timeout for this call only, useful since the artifact upload is often the slowest call an application makes.

No separate upload call

create and create_version upload files (icon, installable artifact) as multipart/form-data. Pass a local file path, the SDK reads the file from disk and builds the request for you. There is no separate "upload" call to make first.

Deploy it to a node

client.nodes.workloads.create_docker_workload(
node.id,
app_version_id="<app-version-id>",
application_id="<application-id>",
)

create_docker_workload(node_id, *, app_version_id, application_id, run_docker=True, force_pull=False, enable_logs=True, config=None, config_id=None) on client.nodes.workloads:

ParameterTypeWhat it is
node_idstrThe target node's internal id, from client.nodes.resolve(node_name)
app_version_idstrThe id of the version you just uploaded; read it from client.applications.list_versions(application_id), since create_version doesn't return it directly
application_idstrThe application's own id, the same one you passed to create_version
run_dockerboolWhether to start the container immediately after deployment, mirroring Run automatically after install in the Marketplace wizard's Advanced section
force_pullboolRe-pulls the Docker image even if it's cached on the node, mirroring Force Docker image download
enable_logsboolWhether the node collects logs for this workload from the start, mirroring Activate logs for this application
configOptional[Dict[str, Any]]An inline JSON App Config document for this workload, read from /appconfig/appconfig.json inside the container
config_idOptional[str]The id of a reusable client.configs entry to attach instead of an inline config

Unlike Marketplace or Model workloads, a Docker workload doesn't take a compose_config parameter: your docker-compose.yaml already defines the container's ports, volumes, and env vars, so there's no service template for the API to reconcile against. The method returns None; call client.nodes.workloads.get(node_id, workload_id) afterwards if you need to inspect the deployed workload, since the create call doesn't echo it back.

Update the application or the deployment

client.applications.update(
"<application-id>",
name="edge-app",
developer="Barbara",
long_description="Updated description",
short_description="Short",
docker=True,
)

client.nodes.workloads.update_docker_workload(
node.id, "<workload-id>", app_version_id="<new-app-version-id>", application_id="<application-id>",
)

update on client.applications takes every metadata field as a required keyword, even the ones you aren't changing. There's no partial-update shorthand, so re-send the current values for fields you want to keep. update_docker_workload on client.nodes.workloads takes the same keyword parameters as create_docker_workload above, plus the workload_id (from client.nodes.workloads.get(...) or the workload's id as returned when it was created) as a required positional argument after node_id. Point app_version_id at a newer version's id to roll the deployment forward, the SDK equivalent of clicking New Version on a workload card.

Retire a version or the application

client.applications.delete_version("<application-id>", "<app-version-id>")
client.applications.delete("<application-id>")

delete_version(application_id, app_version_id) removes a single version, the equivalent of the delete icon on a version's row in the Application view; it fails if the version is currently deployed on any node, so stop or update the workload first. delete(application_id) removes the whole application and every version under it, the equivalent of the delete icon in the Library view's Actions column. There is no separate "are you sure" confirmation at the SDK level the way there is in Panel, so double-check the application_id before calling it.

Summary

You registered an application, published a version, and deployed it, the same three-step shape you'll reuse every time you ship a new build.

See Workload lifecycle for starting, stopping, and reading logs once it's running, and Clusters & cluster workloads to deploy the same way across a whole cluster with create_docker_workload on client.clusters.workloads.

For the full method list, see client.applications and client.nodes.workloads in the Reference.