This tutorial uses an Azure Container Registry, for more details about it, check out my previous post.
Azure DevOps Organization #
-
Create a new Azure DevOps Organization and open it’s dasjboard: https://dev.azure.com/jueklu/
-
My Organization is called
jueklu
Add SSH Key #
Add your public SSH key:
# List (default) public SSH key (Windows)
C:\Users\username\.ssh\id_rsa.pub
# Add your public SSH key to Azure DevOps
https://dev.azure.com/jueklu/_usersSettings/keys
Create Project #
Create a new Azure DevOps Project, mine is called Project1
.
Create Repository #
Create a new repository in the project:
-
Open the “Settings” > “Repositories” section of the project: https://dev.azure.com/jueklu/Project1/_settings/repositories
-
Click “Create”
-
Define a repository name, for example
azure-devops-container-example
-
Click “Create”
Switch to new Repository #
Open the newly created repository:
-
Go to:
Project1
> “Repos” -
Click jueklu / Project1 / Repos / Files /
Project1 ˇ
and selectazure-devops-container-example
Clone Repository #
Clone the azure-devops-container-example
repository to a local client:
# Clone the repository
git clone git@ssh.dev.azure.com:v3/jueklu/Project1/azure-devops-container-example
Repository Components #
Overview #
Add the following Dockerfile
and HTML/index.html
file to the repository,
the file and folderstructure should look like this:
├── Dockerfile
├── HTML
│ └── index.html
└── README.md
Dockerfile #
# Dockerfile
FROM httpd:latest
COPY HTML/index.html /usr/local/apache2/htdocs/
EXPOSE 80
HTML file #
HTML/index.html
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>Azure DevOps Example</h1>
<p>Build Container</p>
</body>
</html>
Parallel Jobs #
# Open the your Azure DevOps Organization page: URL Syntax
https://dev.azure.com/my-organization-name
# Open the your Azure DevOps Organization page: Example
https://dev.azure.com/jueklu/
- Go to “Organization Settings”
- Select the (Pipelines) “Parallel jobs” tab
- Configure a Parallel Job (Necessary to run the pipeline, similar to a GitLab Runner)
Pipeline #
Add Service Connection #
-
Go to: (Project) > “Project Settings”
-
Select “Pipelines” > “Service connections”
-
Click “Create service connection”
Note: An Azure authentication window will pop up. If it does not show up, try again until it shows up, otherwise the “Resource group” can not be selected.
- Select “Azure Resource Manager” and click “Next”
- Authentication Method:
-
Service principal (automatic): Azure DevOps will handle the creation and management of the service principal.
-
Service principal (manual): You provide the details of an existing service principal.
- Click “Next”
-
Scope Level: Select your subscription ID and the resource group where the Azure container registry is deployed
-
Define a service connection name, like
Azure Container Registry
-
Click “Save”
- Verify the new service connection:
Create Pipeline #
-
Go to: (Project) “Pipelines”
-
Click “Create Pipeline”
- Select “Azure Repos Git”
- Select the repository
azure-devops-container-example
-
Select your Azure subscription (and login again - another popup)
-
Select “Build and push an image to Azure Container Registry”
-
Select your Azure Container Registry
-
Define a image name (defaults to repository name)
-
Click validate and configure
- Click “Build and run”
Pipeline Manifest #
The pipeline is automatically created and looks as follows:
# Docker
# Build and push an image to Azure Container Registry
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker
trigger:
- main
resources:
- repo: self
variables:
# Container registry service connection established during pipeline creation
dockerRegistryServiceConnection: '875a58dd-registry-service-connection'
imageRepository: 'azuredevopscontainerexample'
containerRegistry: 'jkwregistry.azurecr.io'
dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
tag: '$(Build.BuildId)'
# Agent VM image name
vmImageName: 'ubuntu-latest'
stages:
- stage: Build
displayName: Build and push stage
jobs:
- job: Build
displayName: Build
pool:
vmImage: $(vmImageName)
steps:
- task: Docker@2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository)
dockerfile: $(dockerfilePath)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag)
Verify the Pipeline Run #
Verify the pipeline run through:
Verify the Image in the Registry #
Azure CLI #
# List images in the Azure Container Registry
az acr repository list --name jkwregistry --output table
# Shell output:
Result
---------------------------
azuredevopscontainerexample
# List available tags of the container image
az acr repository show-tags --name jkwregistry --repository azuredevopscontainerexample --output table
# Shell output:
Result
--------
2
Pull Image & Run Container #
Create a new service principal for the container registry #
# Create service principal
az ad sp create-for-rbac \
--name jkwuser \
--scopes /subscriptions/0176a19a-some-subscription-id.../resourceGroups/container-playground/providers/Microsoft.ContainerRegistry/registries/jkwregistry \
--role acrpush
# Shell output:
{
"appId": "2ec0b720-some-app-id",
"displayName": "jkwuser",
"password": "9wA8Q~some-password...",
"tenant": "30d87815-some-tenant..."
}
Login to Azure Container Registry #
# Login to Azure Container Registry
docker login jkwregistry.azurecr.io --username 2ec0b720-some-app-id --password 9wA8Q~some-password...
Pull the Image & Run the Container #
User Docker to pull and run the image:
# Run container
docker run -d --name azuredevopscontainerexample -p 8080:80 jkwregistry.azurecr.io/azuredevopscontainerexample:2
# Verify the container
curl localhost:8080
# Shell output:
<!DOCTYPE html>
<html>
<head>
<title>jklug.work</title>
</head>
<body>
<h1>Azure DevOps Example</h1>
<p>Build Container</p>
</body>
Links #
https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/containers/build-image?view=azure-devops