The benefits of running services on the edge — fast response times, low bandwidth, the ability to work offline — make this approach an attractive alternative to a fully cloud-based model. But there are some things to think about before moving to the edge:

  • How do you keep the development process simple, so you don't have to rewrite your code for devices with different operating systems or architectures?
  • How do you manage software updates, so that all devices in your fleet can easily and regularly get the latest code?
  • What should you do when you require more computing power than your local device can provide?
  • Where should you store important data to make it available to all devices?

Luckily, all of these concerns can be easily addressed with the right combination of services. We recently tested one such combination — and Microsoft Azure IoT Edge — and we're excited to share how easy it is to get cloud-backed edge intelligence onto the device of your choice:

The not-so-secret ingredient in our easy deployment solution is the Docker container platform. When you put resinOS on your device, you have the ability to run an application in a Docker container without having to do any heavy lifting. If you take a look at the Dockerfile for this deploy, you'll see it is very simple:

  • Specify a base image and update with the required libraries:
FROM resin/raspberrypi3-node


RUN apt-get update  
RUN apt-get install curl build-essential libcurl4-openssl-dev git cmake pkg-config libssl-dev uuid-dev valgrind jq libglib2.0-dev libtool autoconf autogen vim fbi imagemagick  
  • Collect and build the application:
WORKDIR /usr/src/app  
RUN git clone

WORKDIR /usr/src/app/iot-edge/tools  
RUN ./ --disable-native-remote-modules  
  • Run the application:
WORKDIR /usr/src/app  
COPY .  
COPY image.png .  

The script performs a few configurations tasks prior to launching the application. To understand what it does, know that for this demo we have the RaspberryPi acting as a gateway device passing data from two simulated devices to a central hub. Before the script can be run, these steps should be taken:

The first task of is to check for these device credentials. It also does some checks to make sure the display is properly configured:

if [ -z "$DEVICE1" ]  
  echo "Error: DEVICE1 not set!"
  exit 1

if [ -z "$DEVICE2" ]  
  echo "Error: DEVICE2 not set!"
  exit 1

if [ -z "$DEVICE1KEY" ]  
  echo "Error: DEVICE1KEY not set!"
  exit 1

if [ -z "$DEVICE2KEY" ]  
  echo "Error: DEVICE2KEY not set!"
  exit 1

if [ ! -c /dev/fb1 ]  
  modprobe fbtft_device name=pitft verbose=0 rotate=0
  sleep 1
  mknod /dev/fb1 c $(cat /sys/class/graphics/fb1/dev | tr ':' ' ')

convert image.png -rotate $ROTATE rotated.png  
fbi -d /dev/fb1 -T 1 -noverbose -a rotated.png

sleep infinity  

Next, updates the sample configuration file to include the IoT Hub name and simulated device credentials:

J_FILE=$(cat /usr/src/app/iot-edge/samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json)

# cd into sample dir
cd /usr/src/app/iot-edge/samples/simulated_device_cloud_upload/src/

# update settings based on env vars
echo "$J_FILE" | \  
  jq '.modules[0].args.IoTHubName="<IoTHubName>"' | \
  jq '.modules[0].args.IoTHubSuffix=""' | \
  jq '.modules[0].args.Transport="AMQP"' | \
  jq '.modules[1].args[0].deviceId="'$DEVICE1'"' | \
  jq '.modules[1].args[0].deviceKey="'$DEVICE1KEY'"' | \
  jq '.modules[1].args[1].deviceId="'$DEVICE2'"' | \
  jq '.modules[1].args[1].deviceKey="'$DEVICE2KEY'"' \
  > replaced.json

Then it's just a matter of kicking off the sample application, immediately sending simulated device data back to the IoT Hub:

# cd back up to build dir
cd /usr/src/app/iot-edge/build/

# run gateway with new config file
while true  
 ./samples/simulated_device_cloud_upload/simulated_device_cloud_upload_sample ../samples/simulated_device_cloud_upload/src/replaced.json

That's all it takes! Give it a try, and if you run into problems or want to share what you've built, please reach out on our forums.