Introduction
Containers, and especially docker as the management tool are seeing an ever increasing interest and demand also in embedded Linux. Taking the next step from there are orchestrated containers, for example in a microservice architecture.
In the cloud world, docker compose is one of the most prominent tools for orchestration and management of such solutions. Transferring cloud native methods to IoT/edge use cases can provide great value, and to facilitate the usage in device fleets, Mender is providing an Application Update Module for docker compose.
As an extension to the tutorial on using the module on a Debian-based platform, this article explains how to set up a GitHub Actions based pipeline that builds an Application Update Module artifact upon pushing to the repository and deploys it through a Mender backend upon publishing a release.
This is meant to serve as a template to implement GitOps to OTA in your own project.
mender-app-update-pipeline
The example pipeline consists of the following parts:
build_dind.yml: the actual pipeline. It can be used as a template, where you adjust the environment variable declarations near the top to your requirements.docker-compose.yml: the Docker Compose-style manifest of containers which you want to deploy. It is based on the tutorial on application updates in the Mender documentation, and showcases a simpletraefik+whoamisetup.
version: "3.3"
services:
gateway:
image: "traefik:v2.9"
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "8080:80"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami:
image: "traefik/whoami"
labels:
- "traefik.enable=true"
- 'traefik.http.routers.whoami.rule=Path("/whoami")'
- "traefik.http.routers.whoami.entrypoints=web"
Requisites:
- A compatible device to deploy to. The example pipeline uses a Raspberry Pi 4 64bit, running an image built with this tutorial
- a Hosted Mender account, to create a personal access token (PAT) and store it as a GitHub Actions secret. The example expects it under the name
MENDER_SERVER_ACCESS_TOKEN.
Implementation details
workflow:
the build_dind.yml file sets up an Ubuntu-22.04 based container, and installs the required packages:
dockermender-artifactapp-genscript
Additionally, it enablesdockerinside by requesting the service from the host, therefore the name “dind”, short for “Docker-in-Docker”. This is required for theapp-genscript, which needs to run docker for obtaining the containers to package.
jobs:
deploy_application_update:
runs-on: ubuntu-22.04
services:
docker:
image: docker:dind
options: --privileged --shm-size=2g
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
container:
image: ubuntu:22.04
steps:
# step implementations removed for clarity of explanation
- name: Checkout
- name: update APT
- name: install prerequisites
- name: prepare Mender APT repos
- name: prepare Docker APT repos
- name: update APT
- name: install Docker
- name: install mender-artifact
- name: install app-update-module generation script
- name: create artifact
triggers:
the example has three triggers configured.
name: build_dind_explicit
on:
workflow_dispatch:
release:
types: [published]
push:
branches:
- main
workflow_dispatch: so the workflow can be interactively started through the GitHub Actions Web user interface.push: the workflow runs to build the artifact upon each push to themainbranch, so you have a quick feedback loop if the process is still functionalrelease: this trigger is limited to thepublishedtype. The flow is similar to thepush/workflow_dispatchone, but extends it by uploading the artifact to the configured Mender Server and creates a deployment for the devices listed in theMENDER_DEVICES_LISTenvironment variable.
# Only releases upload and deploy through Mender server
- name: Upload Mender Artifacts to Mender server
if: ${{ github.event_name == 'release' }}
uses: mendersoftware/mender-gh-action-upload-artifact@master
with:
mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
mender_artifact: ${{ env.MENDER_ARTIFACT_NAME }}.mender
mender_uri: ${{ env.MENDER_SERVER_URL }}
- name: Create deployment on Mender server
if: ${{ github.event_name == 'release' }}
uses: mendersoftware/mender-gh-action-create-deployment@master
with:
mender_pat: ${{ secrets.MENDER_SERVER_ACCESS_TOKEN }}
mender_uri: ${{ env.MENDER_SERVER_URL }}
mender_deployment_name: ${{ env.MENDER_DEPLOYMENT_NAME }}
mender_release_name: ${{ env.MENDER_RELEASE_NAME }}-${{ env.MENDER_RELEASE_VERSION }}
mender_devices_list: ${{ env.MENDER_DEVICES_LIST }}
Usage
The repository is meant as a template for your own project. These are the minimal modifications for getting started:
- set up a target device with
docker-composeand the Application Update Module plus dependencies, and accept it to your Hosted Mender account. Note down the device ide. - create a personal access token (PAT) as described at Using the APIs | Mender documentation and store it in a safe place for reference
- set the
MENDER_SERVER_ACCESS_TOKENsecret. In your GitHub settings, go to the “Actions”->“Secrets” section and create a new one with the nameMENDER_SERVER_ACCESS_TOKENand the above created PAT as value - change the following in
.github/workflows/build-dind.yml:
MENDER_ARTIFACT_NAME,MENDER_RELEASE_NAME,MENDER_RELEASE_VERSION,MENDER_DEPLOYMENT_NAME: to the desired artifact and application names and versionMENDER_DEVICES_LIST: to an array ([..]) of device ids that you want to deploy to, usually the one that you just noted down in the first stepDEVICE_TYPE: to thedevice_typeof the devices you want to deploy toPLATFORM: to the docker architecture identification string of your target device(s).
- change
docker-compose.ymlaccording to your application, and push to GitHub. This will trigger the artifact build - publish a release through the GitHub UI. This will build the artifact, and deploy it to the configured device(s).
Conclusion
This tutorial respectively template provides a starting point for easily deploying a docker-compose based application through Mender, by automating artifact creation, uplaoding and deploying to a defined set of devices through GitHub Actions.
If this tutorial was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!
