Skip to main content

Setting up Docker on your device

Overview#

Deploying docker containers on devices#

1. Create the release.

The way this will work is that a Release endpoint will be implemented where each release will contain the following information

  • Version

  • Which devices the release applies to

  • A number of containers each with the following information

    • Name
    • Which image+tag to run
    • Which tags should be present on the device
    • Startup parameters
    • If data directories should be purged on deploy.

    This endpoint will return success when the release is created.

2. The update will then be queued on each referenced device.

This will cause the device to retrieve the active release associated to it, and perform the following actions.

Docker state flow

Endpoints#

The CRUD endpoints all return “201 Created” or “200 OK” when an entity is created or modified, and the body of the response will contain the created or modified entity. The DELETE method will return “204 No content” on success.

Registry#

A registry should be created to allow the device to authenticate against a custom docker registry. The model contains the url and credentials for the custom docker registry. When added, devices will automatically log in to the registry if not already logged in, on startup, and thereby be ready to pull images.

If the image should be pulled through a custom registry, the registry needs to be referenced when creating the container.

Creating a registry is done using this endpoint https://api.autopi.io/#/docker/docker_registries_create

Project#

The project endpoint is a wrapper for releases, so to create any releases you must first create a project.

Creating a project is done using this endpoint

POST /docker/projects/

https://api.autopi.io/#/docker/docker_projects_create

Release#

The release endpoint is used to create new releases, and contains a list of containers each with metadata and runtime properties for that specific container.

Creating a project is done using this nested endpoint

POST /docker/projects/{project_pk}/releases/

https://api.autopi.io/#/docker/docker_projects_releases_create

Payload

{   "id": 1,   "version": "1.0.0",   "version_hash": "96a7191f",   "devices": [       "device_id"   ],   "containers": [       {           "name": "curveball",           "image": "curveball",           "tag": "delta-base-r0.0.0.1",           "required_tags": [               "base"           ],           "startup_parameters": {               "environment": "REQUESTS_CA_BUNDLE='/usr/local/share/ca-certificates/AdamCA.crt'",               "binds": [                   "/home/balenaEngine/data:/opt/RavenDB/Server/RavenData"               ],               "network_mode": "host",               "restart_policy": "always",               "privileged": true           },           "purge_data": false,           "registry": 1,           "fully_qualified_name": "deployment-curveball-1"       },       {           "name": "ravendb",           "image": "ravendb",           "tag": "base",           "required_tags": [],           "startup_parameters": {               "environment": "RAVEN_ARGS='--config-path /opt/RavenDB/Server/RavenData/settings.json'",               "binds": [                   "/home/balenaEngine/data:/opt/RavenDB/Server/RavenData"               ],               "network_mode": "host",               "restart_policy": "always",               "privileged": true           },           "purge_data": false,           "registry": 1,           "fully_qualified_name": "deployment-ravendb-1"       }   ],   "successful_deployments": [       "device_id"   ],   "remove_containers": [       "curveball",       "ravendb"   ]}

Special Fields#

NameRequiredDescription
remove_containersNoExplicitly names the containers which should be handled as ‘initial containers’. On release it will attempt to stop each container, run deployment, and if successful the containers will be removed, or on failure, they will be restarted.
version_hashReadonlyAlternative autogenerated field (readonly) only used for referencing a release by a generated version.
successful_deploymentsReadonlyWill include only devices which has successfully deployed the release.

After a release is created, each device associated to the release will receive the release information, and the release will be applied the next time the device is about to go to sleep, as the device in that situation is considered to be idle. Logging in to registries, removing images, pulling new images, starting containers etc.

The release can also be triggered by executing the following command via the execute endpoint on the devices you want to deploy to.

state.sls docker.release

Device#

The device endpoints can be used to retrieve either all devices, or some devices, and includes a new field called docker_releases which can be used to see if a specific release is deployed successfully on the device. The ID is the ID of the release.

Get a specific device https://api.autopi.io/#/dongle/dongle_devices_read

Get all devices https://api.autopi.io/#/dongle/dongle_devices_list

Both endpoints returns device object(s)

{  "id": "734c361a-ba56-472a-a891-ee2af1a8057v",  "unit_id": "4e633880-ef6e-4c20-77ed-5761b3de5d4c",  ...  "docker_releases": [    103  ]}

Modules#

Highlighted modules for performing various actions on a running device docker instance.

Executing module commands#

Module commands is executed on the device through the execute endpoint. See documentation here: https://api.autopi.io/#/dongle/dongle_devices_execute_command

When executing commands remotely, you must execute the command async via the execute endpoint, and then use the https://api.autopi.io/#/dongle/dongle_devices_retrieve_command_result endpoint to poll for the result from the device.

Example payloads for REST API are included below.

Executing commands locally on the device#

The above commands can also be executed directly on the device with the following endpoint

POST localhost:9000/dongle/<uuid:unit_id>/execute/

The body should be the same as the above remote command endpoint.

The unit_id can be retrieved one of the following ways

A. Calling the root route

GET localhost:9000

B. Reading it from the file

/etc/salt/minion_id

The reason that you need the unit_id is because we need to make sure that the request is actually meant for that specific device when using the endpoint from another connected device, like when using the local configuration tool.

Container Logs#

Logs are retrieved from the containers by using the docker module.

docker.logs CONTAINER_NAME

Example payload for executing via REST API

{  "command": "docker.logs",  "arg": [    "CONTAINER_NAME"  ],  "kwarg": {}}

5.3. Device Logs Logs are retrieved from the device by using the minionutil module.

minionutil.last_logs

See documentation site for all parameters minionutil.last_logs

Example payload for executing via REST API

{  "command": "minionutil.last_logs",  "arg": [],  "kwarg": {}}

Production environment#

The production environment is located at: my.autopi.io

REST API#

The API can be accessed here api.autopi.io along with the API documentation.

Authenticate using API token#

Authentication should be done with the API tokens. These tokens can be generated in the account page. The expire date is optional. The tokens can then be used in external systems to authenticate the requests. To use the token, you simply set the Authorization header to the following value, when sending HTTP requests to the API.

Authorization: APIToken ******

Telemetry Data Examples#

Accessing data from a device is done by calling the logbook endpoint.

Logbook Storage Read Parameters#

device_id: ID of the device you want to retrieve data from. field: Name of the field you want to retrieve the value from. field_type: type of the field from_utc: ISO Datetime string to_utc: ISO Datetime string aggregation: Aggregation method (AVG, MIN, MAX, SUM) interval: Data is aggregated based on the aggregation method specified, the interval specifies how many groups the data is grouped into. For example, getting data for a 10 hour period, with the interval set to 1h, you will get back 10 values, one value per hour.

Getting positions

GET /logbook/storage/read/?device_id=DEVICE_ID&field=track.pos.loc&field_type=geo_point&from_utc=2020-01-01T00:00:00.000Z&to_utc=2020-01-01T01:00:00.000Z

Example response

[    {            "ts": "2020-07-09T10:11:53.811839Z",            "location": {                    "lat": 57.04699,                    "lon": 9.93909            }    },    {            "ts": "2020-07-09T10:11:59.248421Z",            "location": {                    "lat": 57.04697,                    "lon": 9.93808            }    }]

Battery Voltage readings

GET /logbook/storage/read/?device_id=DEVICE_ID&field=obd.bat.voltage&field_type=float&aggregation=avg&from_utc=2020-01-01T00:00:00.000Z&to_utc=2020-01-01T01:00:00.000Z&interval=10m

Example response

[    {            "max_ts": 1594289021415,            "ts": "2020-07-09T10:03:37.566Z",            "value": 13.5    },    {            "max_ts": 1594289026525,            "ts": "2020-07-09T10:13:45.378Z",            "value": 13.600000381469727    }]