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.
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.
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:
| Parameter | Type | Panel equivalent |
|---|---|---|
name | str | Name |
long_description | str | Description |
developer | str | Not directly shown in the New Application popup, but recorded against the application (visible via get/update) |
docker | bool | Application type: True selects Docker, matching every workflow in this guide |
short_description | Optional[str] | A shorter summary, not exposed in the basic New Application form but readable/settable via update |
icon_path | Optional[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:
| Parameter | Type | What to pass |
|---|---|---|
application_id | str | The id from the application you just registered; look it up with client.applications.list(search=...) if create didn't return it to you |
artifact_path | str | A 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 |
name | str | The 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 |
architectures | List[str] | The CPU architectures this build supports, matching the compatible platforms checkboxes in the New Version popup, for example ["amd64"] or ["amd64", "arm64"] |
release_notes | List[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.
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:
| Parameter | Type | What it is |
|---|---|---|
node_id | str | The target node's internal id, from client.nodes.resolve(node_name) |
app_version_id | str | The 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_id | str | The application's own id, the same one you passed to create_version |
run_docker | bool | Whether to start the container immediately after deployment, mirroring Run automatically after install in the Marketplace wizard's Advanced section |
force_pull | bool | Re-pulls the Docker image even if it's cached on the node, mirroring Force Docker image download |
enable_logs | bool | Whether the node collects logs for this workload from the start, mirroring Activate logs for this application |
config | Optional[Dict[str, Any]] | An inline JSON App Config document for this workload, read from /appconfig/appconfig.json inside the container |
config_id | Optional[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.