Introduction
On this publish, we will likely be discussing find out how to handle Docker container lifecycle utilizing an AWS IoT Greengrass customized part. There are 5 phases in a Docker container lifecycle: create, run, pause/unpause, cease, and kill. The customized part interacts with the Docker Engine through the Docker SDK for Python to handle processes primarily based in your use case, reminiscent of consumer initiated instructions or an software sending instructions.
AWS IoT Greengrass is an open supply Web of Issues (IoT) edge runtime and cloud service that helps you construct, deploy and handle IoT purposes in your gadgets. You should utilize AWS IoT Greengrass to construct edge purposes utilizing pre-built software program modules, known as parts, that may join your edge gadgets to AWS companies or third-party companies.
AWS IoT Greengrass parts can signify purposes, runtime installers, libraries, or any code that you’d run on a tool. You may configure AWS IoT Greengrass parts to run a Docker container from photographs saved within the following places:
Whereas Greengrass parts have lifecycles of their very own that you could be work together with, these lifecycles don’t help containerized processes. To start out, cease, pause and resume a Docker container operating on AWS IoT Greengrass, you should use instructions reminiscent of Docker pause and Docker unpause through a Greengrass part operating on a Greengrass core gadget. The customized lifecycle part, which we’ll check with because the ‘lifecycle part’, consists of a Python script that subscribes to an AWS IoT Core MQTT subject and interacts with the Docker Engine.
Answer Overview
Beneath is an instance workflow and structure for one potential implementation. With these constructing blocks in hand you’ll be able to additional develop to suit your particular use case.
- A consumer deploys a Docker container part and the lifecycle part to the Greengrass core gadget.
- The applying publishes a MQTT message to an AWS IoT Core subject. The MQTT message specifies the container identify and desired motion to be carried out. On this instance, we ship a begin command to the container named
env
. - The customized lifecycle part is subscribed to the subject.
- The lifecycle part receives the message after which interacts with the Docker Engine through the Docker SDK for Python and executes the specified command on the container identify specified.
- Primarily based on the command acquired from the lifecycle part, the Docker Engine will pause, unpause, begin, or cease the desired container.
Answer Diagram
Implementation Directions
Conditions
- The AWS CLI is put in and configured.
- AWS Greengrass Core put in in your gadget.
- Docker Engine is put in and operating.
Deploy a Docker container to a Greengrass Core gadget
Observe the directions on find out how to run a Docker container with AWS Greengrass or optionally create and run a container with the Docker Engine itself. You’ll want to present a reputation for the container, on this instance we use the identify of env
.
Confirm you could have a operating Docker container and that it has the specified identify:
docker container ls
Create the customized lifecycle part
To create a Greengrass part we have to create the Python script that may include our code and in addition a Greengrass recipe which can specify the deployment particulars when the part is deployed to a Greengrass Core gadget.
- Create an empty folder and script file named
customlifecycle.py
.mkdir -p ~/artifacts && contact ~/artifacts/customlifecycle.py
- In your favourite Built-in Improvement Surroundings (IDE), open
customlifecycle.py
and paste the next code. You’ll want to save the file. Notice: the code snippet beneath is beneath an MIT-0 license and is on the market on Github.#Imports import time import json import traceback import docker import subprocess import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.consumer as consumer from awsiot.greengrasscoreipc.mannequin import ( IoTCoreMessage, QOS, SubscribeToIoTCoreRequest ) TIMEOUT = 10 ipc_client = awsiot.greengrasscoreipc.join() subject = "docker" qos = QOS.AT_MOST_ONCE #IPC Stream Handler class StreamHandler(consumer.SubscribeToIoTCoreStreamHandler): def __init__(self): tremendous().__init__() def on_stream_event(self, occasion: IoTCoreMessage) -> None: message = json.masses(occasion.message.payload.decode()) strive: consumer = docker.from_env() identify = message["name"] command = message["command"] if command == "begin": container = consumer.containers.get(identify) container.begin() print("Beginning container: " + identify) elif command == "pause": container = consumer.containers.get(identify) consequence = json.masses(container.pause()) print(consequence) print("Pausing container: " + identify) elif command == "unpause": container = consumer.containers.get(identify) print(container.unpause()) print("Unpausing container: " + identify) elif command == "cease": container = consumer.containers.get(identify) container.cease() print("Stopping container: " + identify) else: print("Error") besides: with tempfile.TemporaryFile() as tmp: tmp.write("Docker Error") def on_stream_error(self, error: Exception) -> bool: message_string = "Error!" return True def on_stream_closed(self) -> None: move #Provoke Subscription request = SubscribeToIoTCoreRequest() request.topic_name = subject request.qos = qos handler = StreamHandler() operation = ipc_client.new_subscribe_to_iot_core(handler) future = operation.activate(request) future_response = operation.get_response() future_response.consequence(TIMEOUT) whereas True: time.sleep(1) operation.shut()
- Create a bucket and retrieve your bucket identify utilizing the next command.
EPOCH_TIME=$(date +"%s") && S3_BUCKET=lifecycle-component-$EPOCH_TIME && aws s3 mb s3://$S3_BUCKET
- Execute the next command to create a folder and a file to place the recipe into.
mkdir -p ~/recipes && contact ~/recipes/customlifecycle-1.0.0.json
- Open the created recipe file
customlifecycle-1.0.0.json
and paste the next contents. Substitute [YOUR BUCKET NAME] with the bucket identify retrieved within the step 3.{ "RecipeFormatVersion": "2020-01-25", "ComponentName": "Docker-lifecycle-component", "ComponentVersion": "1.0.0", "ComponentType": "aws.greengrass.generic", "ComponentDescription": "A part that interacts with Docker daemon.", "ComponentPublisher": "Amazon", "ComponentConfiguration": { "DefaultConfiguration": { "accessControl": { "aws.greengrass.ipc.mqttproxy": { "docker_lifecycle:mqttproxy:1": { "policyDescription": "Permits entry to subscribe to all matters.", "operations": [ "aws.greengrass#SubscribeToIoTCore" ], "sources": [ "*" ] } } } } }, "Manifests": [ { "Lifecycle": { "Install": "pip3 install awsiotsdk", "Run": "python3 -u {artifacts:path}/customlifecycle.py" }, "Artifacts": [ { "Uri": "s3://[YOUR BUCKET NAME]/customlifecycle.py" } ] } ] }
- Add the part artifacts to Amazon Easy Storage Service.
aws s3 cp --recursive ~/artifacts/ s3://$S3_BUCKET/
- Subsequent, we’ll publish the Greengrass part by operating the next command.
cd ~/recipes && aws greengrassv2 create-component-version --inline-recipe fileb://customlifecycle-1.0.0.json
- Now you can see this has been added to your AWS IoT Console -> Greengrass -> Parts -> My Parts.
Deploy the customized lifecycle part
Now we’ll deploy the customized lifecycle part to your Greengrass Core gadget utilizing the AWS CLI. Deployments could also be utilized to Issues or Factor Teams. On this case, we’ll apply the deployment on to the Greengrass Core factor entity.
- Create a deployment manifest folder and file utilizing the command beneath.
mkdir -p ~/deployments && contact ~/deployments/gg_deployment.json
- In your IDE, copy and paste the beneath into the
gg_deployment.json
file. Replace the [targetARN] together with your Factor ARN. It’s possible you’ll retrieve your Factor ARN from the AWS IoT Core console. You’ll want to save the file.{ "targetArn": "[targetArn]", "deploymentName": "Deployment for Customized Docker Lifecycle", "parts": { "Docker-lifecycle-component": { "componentVersion": "1.0.0" } } }
- Create the deployment with the next command.
cd ~/deployments && aws greengrassv2 create-deployment --cli-input-json file://gg_deployment.json
- Confirm that the part is now operating in your Greengrass Core gadget. It could take a number of minutes for it to instantiate.
sudo /greengrass/v2/bin/greengrass-cli part checklist
Take a look at the Customized Lifecycle part
- Go to  AWS IoT Core console, choose the MQTT take a look at consumer.
- Choose Publish to subject.
- Within the Matter identify, enter
docker
- Within the Message payload, copy within the message beneath. The command syntax will depend upon the identify and present state of your container.
{ "command":"begin", "identify":"env" }
- Confirm that the state of your container has modified.
docker container ls
Conclusion
On this weblog publish, we explored find out how to use AWS IoT Greengrass to manage a Docker container’s lifecycle. This was achieved utilizing a customized part that subscribes to an AWS IoT Core MQTT subject and makes use of the message contents to execute instructions in opposition to the Docker daemon with the Docker SDK for Python.
To take a deeper dive with AWS IoT Greengrass, together with constructing Greengrass parts, take a look at our AWS IoT Greengrass V2 Workshop!