Containers
In this guide we will use Airbotics to deploy Docker containers to our robot.
Goals
- Upload your first
docker-compose
. - Connect your robot to a private container registry.
- Deploy the
docker-compose
to your robot to start the containers. - Upload and deploy a second
docker-compose
to stop the old containers and start the new ones.
Prerequisites
- An account with Airbotics.
- A valid API key with the
compose-files:read
andcompose-files:write
permissions. - Device running Ubuntu 22.04 with:
- ROS 2 installed
- Airbotics agent installed
- Docker engine installed
- Physical or SSH access to your device.
Prepare environment
Ensure you have the following two environment variables set before you get started:
export AIR_API_KEY=<your_api_key>
export AIR_ROBOT_ID=<your_robot_id>
export COMPOSE_ID="demo-compose-app-v1"
Run the agent
airbotics
Prepare a docker-compose
The first step in a new deployment is to prepare a new docker-compose
file. In this guide, the docker-compose
starts two containers, one from a public registry and another from a private Dockerhub registry.
Take note of the json
representation of the compose file, we will use this in the next step.
If you’re using your own docker-compose
file that’s written in yaml you can convert it to json with the following:
docker compose -f <path-to-docker-compose.yaml> convert --format json
version: "3.8"
services:
demo_public:
image: alpine:latest
container_name: air_public
command: ["tail", "-f", "/dev/null"]
demo_private:
image: airboticsdev/test:v1
container_name: air_private
command: ["tail", "-f", "/dev/null"]
Create the docker-compose
Before we deploy the compose file to a robot, an API call must be made to create the compose file. Provide an id
and name
and set the content
to the json serialized compose file:
curl --request POST https://api.airbotics.io/compose-files \
--header 'content-type: application/json' \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"id": "'$COMPOSE_ID'",
"name": "Robot application v1",
"content": {
"services": {
"demo_public": {
"command": [
"tail",
"-f",
"/dev/null"
],
"container_name": "air_public",
"image": "alpine:latest"
},
"demo_private": {
"command": [
"tail",
"-f",
"/dev/null"
],
"container_name": "air_private",
"image": "airboticsdev/test:v1"
}
}
}
}'
Authenticate with private container registry
Our docker-compose
contains the image airboticsdev/test:v1
which is stored in a private Dockerhub registry.
If your compose file contains images from a private registry, you must ensure the Agent can authenticate with the
private registry otherwise the deployment will fail.
The following process may vary slightly depending on the container registry you are using (Dockerhub, ECR, GHCR etc.)
Log in Dockerhub and go to account settings > security > New Access Token, create a token with read permissions.

You will be presented with the personal access token, now you must set the following environment variables on your robot.
# This is the base URL for Dockerhub, change this if you are using another registry provider
export AIR_CONTAINER_REGISTRY_URL="https://index.docker.io/v1/"
# Your Dockerhub username
export AIR_CONTAINER_REGISTRY_USERNAME="airboticsdev"
# The personal access token you just created
export AIR_CONTAINER_REGISTRY_PASSWORD="dckr_pat_*******************"
Deploy the docker-compose
Now We are ready to deploy the compose file we created earlier (with id=$COMPOSE_ID
) to a robot (with id=$AIR_ROBOT_ID
).
Make another API call, make sure you set the correct robot id in the url and the correct compose file id in the request body.
curl --request POST https://api.airbotics.io/robots/$AIR_ROBOT_ID/compose-file \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"id": "'$COMPOSE_ID'"
}'
Verifying the state
You can verify the state of deployed docker-compose
with the following API request:
curl --request GET https://api.airbotics.io/robots/$AIR_ROBOT_ID/compose-file \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY"
If the agent is running and network connected and the compose file has finished pulling and starting the containers,
you should see the status has been set to up
.
If the agent is not running or is not network connected the status should be sent to pending_up
. As soon as the agent starts
or re-connects to the network, it will receive the compose file and attempt to start the containers.
If the status is error
, something went wrong trying to execute the compose file, check the log output for more information.
You can also confirm the if the containers are running on your robot by running:
docker container ls --format 'table {{.Names}}\t {{.Image}} \t {{.Status}}'
Which should produce the output:
NAMES IMAGE STATUS
air_private airboticsdev/test:v1 Up 15 seconds
air_public alpine:latest Up 15 seconds
Upload and deploy a second docker-compose
Create a second compose file that contains two updated containers with a new id demo-compose-app-v2
.
curl --request POST https://api.airbotics.io/compose-files \
--header 'content-type: application/json' \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"id": "demo-compose-app-v2",
"name": "Robot application v2",
"content": {
"services": {
"demo_public_two": {
"command": [
"tail",
"-f",
"/dev/null"
],
"container_name": "air_public",
"image": "alpine:3.16"
},
"demo_private_two": {
"command": [
"tail",
"-f",
"/dev/null"
],
"container_name": "air_private",
"entrypoint": null,
"image": "airboticsdev/test:v2"
}
}
}
}'
Now deploy the demo-compose-app-v1
compose file to the robot:
curl --request POST https://api.airbotics.io/robots/$AIR_ROBOT_ID/compose-file \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY" \
--data '{
"id": "demo-compose-app-v2"
}'
On the robot you can verify that the old containers were stopped the new ones were started:
docker container ls --format 'table {{.Names}}\t {{.Image}} \t {{.Status}}'
Which should produce the output:
NAMES IMAGE STATUS
air_private airboticsdev/test:v2 Up 5 seconds
air_public alpine:3.16 Up 5 seconds
Wrapping up
In this guide you have created and deployed multiple docker-compose
files to your robot to orchestrate which containers should be running.
You can use the same ideas and API to create customer portals, internal tools, applications and control panels using whatever tools you like to work with.
Cleaning up
To stop all containers running on your robot make the following API call:
curl --request DELETE https://api.airbotics.io/robots/$AIR_ROBOT_ID/compose-file \
--header "content-type: application/json" \
--header "air-api-key: $AIR_API_KEY"
To stop delete the 2 docker-compose
files we created make the following API calls:
curl --request DELETE https://api.airbotics.io/compose-files/$COMPOSE_ID \
--header 'content-type: application/json' \
--header "air-api-key: $AIR_API_KEY"
curl --request DELETE https://api.airbotics.io/compose-files/demo-compose-app-v1 \
--header 'content-type: application/json' \
--header "air-api-key: $AIR_API_KEY"