cd ../projects
2026-04-13·3 min read

Revolutionizing IoT Deployments: My Discovery of CI/CD Pipelines on Azure DevOps

Experience report on implementing CI/CD pipelines with Azure DevOps to deploy an application across a fleet of Raspberry Pi devices. Discover the architecture, Docker challenges, and lessons learned.

DevOps

Revolutionizing IoT Deployments: My Discovery of CI/CD Pipelines on Azure DevOps

If you manage infrastructure, you know how quickly manual deployment can become a logistical nightmare. Recently, I faced an interesting challenge: setting up and maintaining a management application deployed across a fleet of Raspberry Pi devices scattered across multiple physical sites of my company.

To solve this puzzle, I dove into the world of Continuous Integration and Continuous Deployment (CI/CD) with Azure DevOps. Here's my experience report on my research, architecture, and the technical challenges encountered (especially with Docker!).

What is a CI/CD Pipeline and Why Use It Here?

In simple terms, a CI/CD pipeline is a series of automated steps that execute whenever your code changes. It handles building (Build), testing (Test), and deploying (Deploy) your application.

Why is this essential in my case?

Imagine having to SSH into 10, 20, or 50 Raspberry Pi devices spread across different geographical sites every time you update the application... It's time-consuming, prone to human error, and simply unmanageable at scale.

The pipeline centralizes this process: I push my code, and the machine takes care of distributing it uniformly and reliably across the entire fleet.

The Chosen Approach: A Controlled End-to-End Workflow

To ensure system stability, here's the workflow I implemented:

1. Development (Feature Branch)

Each new feature or bug fix is developed on a dedicated branch (e.g., feature/new-interface).

2. Staging Phase (Pre-production)

Once the code is pushed, the pipeline triggers a deployment to a dedicated Raspberry Pi for testing. This allows verifying the application works correctly under real conditions (identical hardware) without impacting users.

3. Production Deployment

Once tests pass on the staging Raspberry Pi, the branch is merged into the main branch. The pipeline then automatically deploys the new version across all the company's Raspberry Pi devices.

The Magic of Docker and the "Container Registry" Challenge

To facilitate deployment and ensure "it works on my machine AND on the Raspberries," the application is containerized with Docker. My pipeline's job is to build a Docker image with each update.

But once this image is built, it must be stored somewhere so the Raspberry Pi devices can download it. That's where a Container Registry comes in.

Facing Costs: The Self-Hosting Decision

Initially, I looked at Azure's native registry (Azure Container Registry). While excellent, it comes with a price tag. Seeking a more economical solution for this project, I decided to set up my own registry using Docker's official image (registry:2).

This is where things get technically interesting:

Docker's Security Requirement (HTTPS): By default, Docker refuses to communicate with an insecure (HTTP) registry. For my setup, I implemented a self-signed certificate paired with a custom domain name.

Configuring the Raspberries: This registry had to be declared as a trusted source on the Raspberry Pi devices by adding the certificate.

The Bridge Between Azure and the Local Network: The Self-Hosted Agent

Network Security: How Does Azure DevOps Talk to My Local Registry?

My Docker registry is hosted internally on the company network. Opening it to the Internet (NAT/Port Forwarding) just for Azure DevOps to access it was out of the question!

Azure DevOps's elegant solution is deploying a Self-Hosted Agent.

Instead of Azure trying to "enter" my network, a small virtual machine (or container) located within my company network queries Azure's servers from the inside outward. This agent fetches pipeline tasks, builds the Docker image, and pushes it to my local registry safely and securely.

Conclusion and Next Steps

Implementing CI/CD pipelines for physical devices (Edge computing/IoT) requires some architectural planning, particularly around Docker image management and network security. However, the time savings and peace of mind during deployments are well worth this initial investment.

I'm currently finalizing the integration of this private registry. The next step will be optimizing how Raspberry Pi devices detect when a new image is available in the registry for updating (potentially using tools like Watchtower or polling scripts).

Feel free to share your own IoT experiences and architectures in the comments!