Podman Integration for Azure DevOps and Azure Container Registry

The integration of Podman within Azure DevOps Pipelines represents a fundamental shift in container orchestration for CI/CD workflows. Podman, as a daemonless container engine, provides a robust alternative to Docker, specifically tailored for environments where security, rootless execution, and reduced overhead are paramount. In the context of Azure DevOps, Podman enables a streamlined pipeline that leverages Microsoft-hosted Ubuntu agents or custom self-hosted runners to build, test, and deploy container images directly to the Azure Container Registry (ACR). Because Podman adheres to OCI (Open Container Initiative) standards, it maintains full compatibility with ACR, allowing organizations to utilize a managed registry service while benefiting from the architectural advantages of a daemonless runtime.

The synergy between Podman and Azure Container Registry is characterized by standard registry authentication and seamless integration with Azure Kubernetes Service (AKS). By utilizing Podman, developers can execute container operations without the necessity of a persistent background process (daemon), which inherently reduces the attack surface of the build agent. This architecture is particularly effective when paired with Azure's ecosystem, where the registry acts as the centralized source of truth for container images, providing features such as geo-replication and vulnerability assessment via Microsoft Defender for Cloud.

Architectural Advantages of Podman over Docker in Azure Environments

The transition from Docker to Podman within Azure DevOps is often driven by the need for enhanced security and architectural flexibility. The primary differentiator is Podman's daemonless nature. Unlike Docker, which relies on a central daemon running with root privileges to manage containers, Podman interacts directly with the Linux kernel.

  • Security and Rootless Execution: Podman does not require a separate daemon to run containers with root privileges. This eliminates a common single point of failure and a significant security vulnerability, as the compromise of a daemon does not automatically grant root access to the host machine.
  • Ecosystem and Trust: Podman is backed by a vast ecosystem of container tools and offers advanced features such as Image Trust and Image Content source policy. These features allow organizations to define strict rules regarding which registries or repositories are permitted, effectively forcing the use of private ACR instances and blocking unauthorized external registries.
  • API Compatibility: Podman v4 and higher provide a Docker API compatibility layer. This ensures that existing pipelines and tasks designed for Docker can be redirected to Podman with minimal to no changes in the source code or Dockerfile.
  • Performance: Podman is designed to match or exceed Docker's build speeds, ensuring that the shift to a daemonless architecture does not introduce latency into the CI/CD lifecycle.

Azure Container Registry and Podman Compatibility

Azure Container Registry (ACR) serves as the managed destination for images created via Podman. As a managed service, ACR supports both Docker and OCI image formats, which makes it natively compatible with Podman's output.

  • Image Format Support: Since Podman produces OCI-compliant images, ACR can store, version, and serve these images without modification.
  • Integration with Azure Services: ACR integrates deeply with other Azure services, specifically Azure Kubernetes Service (AKS). Images pushed from a Podman-enabled pipeline to ACR can be pulled by AKS clusters for deployment.
  • Security Enhancements: ACR integrates with Microsoft Defender for Cloud, allowing for automated vulnerability assessments of the images pushed via Podman.
  • Global Distribution: Through geo-replication, ACR ensures that images are available in multiple regions, reducing latency for global deployments.

Implementing Podman in Azure DevOps Pipelines

Integrating Podman into an Azure DevOps pipeline involves configuring the agent to install the runtime and establishing a secure authentication path to the Azure Container Registry.

Agent Configuration and Installation

Microsoft-hosted agents based on Ubuntu support the installation of Podman via the standard package manager. For self-hosted agents, Podman can be pre-installed to reduce pipeline execution time.

The following pipeline configuration demonstrates the installation process on an ubuntu-latest image:

```yaml

azure-pipelines.yml

Pipeline that uses Podman for container operations

trigger:
branches:
include:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
# Azure Container Registry settings
acrName: 'myregistry'
acrLoginServer: 'myregistry.azurecr.io'
imageName: 'myapp'
imageTag: '$(Build.BuildId)'
steps:
# Install Podman on the agent
- script: |
sudo apt-get update
sudo apt-get install -y podman
podman --version
displayName: 'Install Podman'
```

In this configuration, the sudo apt-get install -y podman command ensures that the daemonless engine is available for subsequent steps. This approach is critical for Microsoft-hosted agents that do not come with Podman pre-installed.

Container Build and Unit Testing

Once Podman is installed, the pipeline can proceed to build the container image and execute tests within that image.

The build process utilizes the podman build command to create tagged images for both the specific build ID and the latest version:

```yaml

Build the container image

  • script: |
    podman build \
    -t $(acrLoginServer)/$(imageName):$(imageTag) \
    -t $(acrLoginServer)/$(imageName):latest \
    .
    displayName: 'Build Container Image'
    ```

Following the build, the pipeline can perform unit tests by running the newly created image. Using the --rm flag ensures that the container is removed after the test execution, keeping the agent clean:

```yaml

Run unit tests inside the container

  • script: |
    podman run --rm \
    $(acrLoginServer)/$(imageName):$(imageTag) \
    npm test
    displayName: 'Run Unit Tests'
    ```

Authentication and Image Deployment to ACR

Authentication is a critical step when pushing images to a private Azure Container Registry. Podman uses standard registry authentication, which can be achieved through several methods depending on the required level of security and automation.

Using Azure CLI for Token-Based Authentication

The most direct method for pipeline authentication is using the AzureCLI@2 task to retrieve an access token. This method allows the pipeline to authenticate using a service connection.

```yaml

Use Azure CLI task to get ACR credentials

  • task: AzureCLI@2
    displayName: 'Login to ACR with Podman'
    inputs:
    azureSubscription: 'my-azure-subscription'
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
    # Get ACR access token using Azure CLI
    ACRTOKEN=$(az acr login --name $(acrName) --expose-token --query accessToken -o tsv)
    # Login to ACR using Podman
    echo "$ACR
    TOKEN" | podman login \
    $(acrLoginServer) \
    -u 00000000-0000-0000-0000-000000000000 \
    --password-stdin
    ```

Once authenticated, the images can be pushed to the registry using the podman push command:

```yaml

Push the images to ACR

podman push $(acrLoginServer)/$(imageName):$(imageTag)
podman push $(acrLoginServer)/$(imageName):latest
```

Utilizing Service Principals for Non-Interactive Access

For production-grade CI/CD, Service Principals provide a secure, non-interactive way to manage ACR access. This involves creating a principal with the acrpush role.

The process for creating and using a Service Principal is as follows:

  1. Identify the ACR ID:
    bash ACR_ID=$(az acr show --name myacrregistry --query id --output tsv)

  2. Create the Service Principal with appropriate scopes and roles:
    bash SP_CREDENTIALS=$(az ad sp create-for-rbac \ --name acr-podman-sp \ --scopes "$ACR_ID" \ --role acrpush \ --query "{appId: appId, password: password}" \ --output json)

  3. Extract the Application ID and Password:
    bash SP_APP_ID=$(echo "$SP_CREDENTIALS" | python3 -c "import sys,json; print(json.load(sys.stdin)['appId'])") SP_PASSWORD=$(echo "$SP_CREDENTIALS" | python3 -c "import sys,json; print(json.load(sys.stdin)['password'])")

  4. Authenticate Podman using the extracted credentials:
    bash echo "$SP_PASSWORD" | podman login myacrregistry.azurecr.io \ --username "$SP_APP_ID" \ --password-stdin

Administrator Account Authentication

In scenarios where admin accounts are enabled, credentials can be retrieved and passed directly to Podman. This is typically used for simpler setups or testing.

  1. Enable admin access:
    bash myacrregistry --admin-enabled true

  2. Retrieve the password:
    bash ACR_PASSWORD=$(az acr credential show --name myacrregistry --query "passwords[0].value" -o tsv)

  3. Login to the registry:
    bash podman login myacrregistry.azurecr.io \ --username myacrregistry \ --password-stdin <<< "$ACR_PASSWORD"

Multi-Stage Pipeline Architectures with Podman

Complex workflows require a multi-stage approach to separate the build, test, and deployment phases. Podman supports this by allowing images to be saved as artifacts and transferred between stages.

Build Stage and Image Archiving

In the build stage, the image is created and then exported as a tarball. This prevents the need to re-build the image in subsequent stages, ensuring that the exact same binary is tested and deployed.

```yaml

Multi-stage pipeline using Podman

trigger:
- main
variables:
acrName: 'myregistry'
acrLoginServer: 'myregistry.azurecr.io'
imageName: 'myapp'
imageTag: '$(Build.BuildId)'
stages:
- stage: Build
displayName: 'Build Image'
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- script: sudo apt-get update && sudo apt-get install -y podman
displayName: 'Install Podman'
- script: |
podman build \
-t $(acrLoginServer)/$(imageName):$(imageTag) .
displayName: 'Build Image'
- script: |
podman save \
-o $(Build.ArtifactStagingDirectory)/image.tar \
$(acrLoginServer)/$(imageName):$(imageTag)
displayName: 'Save Image'
- publish: $(Build.ArtifactStagingDirectory)/image.tar
artifact: container-image
displayName: 'Publish Image Artifact'
```

Test Stage and Pod Management

The test stage involves loading the image from the artifact and running integration tests. Podman's ability to manage pods allows for complex testing scenarios involving multiple containers.

```yaml

Run integration tests

  • script: |
    podman run --rm \
    $(acrLoginServer)/$(imageName):$(imageTag) \
    myapp:test npm run test:integration
    displayName: 'Run Integration Tests'

Cleanup Pods

  • script: |
    podman pod rm -f az-test-pod || true
    displayName: 'Cleanup'
    condition: always()
    ```

Operationalizing Podman in Azure Runners

For organizations seeking to replace Docker entirely within their Azure runners, several technical requirements must be met to ensure a seamless transition.

Requirements for Full Docker Replacement

To successfully replace Docker with Podman in an Azure DevOps environment, the following configuration targets must be achieved:

  • Agent Customization: The Azure DevOps agent runner must be configured to support Podman natively.
  • Command Redirection: Pipelines utilizing Docker commands must be redirected to Podman. This is possible because Podman provides a Docker API compatibility layer, allowing the use of Podman with all original arguments without modifying the Dockerfile.
  • Socket Emulation: For templates that expect a Docker socket, the Podman socket/service must be started automatically for the Azure DevOps user.
  • Registry Control: Request forwarding must be configured to ensure all container registry requests are directed to the private ACR.
  • Whitelisting: To prevent the pull of unauthorized images, a whitelist of allowed registries, repositories, and tags must be implemented, with all other requests denied.
  • Performance Validation: Build speeds must be benchmarked to ensure that Podman's performance is equal to or greater than that of Docker.

Image Management Operations

Once the environment is configured, standard image management tasks can be performed.

Pulling images from ACR:
```bash
ACR_REGISTRY="myacrregistry.azurecr.io"

Pull an image

podman pull ${ACR_REGISTRY}/myapp:latest

Pull a specific version

podman pull ${ACR_REGISTRY}/myapp:v2.0

List pulled ACR images

podman images | grep azurecr
```

Building and tagging images for ACR:
```bash
ACR_REGISTRY="myacrregistry.azurecr.io"

Build a local image

podman build -t myapp:latest .

Tag the image for ACR

podman tag myapp:latest ${ACR_REGISTRY}/myapp:latest
```

Summary Analysis of Podman and Azure Integration

The integration of Podman into Azure DevOps Pipelines and its interaction with Azure Container Registry provides a sophisticated alternative to the traditional Docker-based workflow. The transition is not merely a change in tooling but a shift toward a more secure, daemonless architecture. By removing the requirement for a root-privileged daemon, Podman mitigates significant security risks associated with container escape and host compromise.

The technical viability of this approach is supported by the OCI compliance of both Podman and ACR. The ability to use Service Principals for non-interactive authentication ensures that the security posture is maintained throughout the CI/CD pipeline. Furthermore, the implementation of multi-stage pipelines allows for the rigorous testing of images via artifacts, ensuring consistency from the build stage to production.

While Podman is a newer entrant compared to Docker and may require more manual customization within Azure DevOps (such as the explicit installation on hosted agents), the benefits—namely Image Trust, content source policies, and rootless execution—outweigh the initial configuration overhead. The Docker API compatibility layer further lowers the barrier to entry, allowing organizations to migrate existing pipelines with minimal disruption. Ultimately, Podman equips Azure users with a high-performance, secure, and flexible container runtime that integrates natively with the broader Azure cloud ecosystem.

Sources

  1. Podman Azure DevOps Pipelines
  2. Azure Container Registry and Podman
  3. Using Podman instead of Docker in Azure Runners

Related Posts