How to run a docker container in azure devops? - azure

I'm currently playing around with docker containers and azure devops with the goal to run a couple of tests from it.
This is what I currently do:
I have created a dockerfile in my repo
I have created a pipline that build and push an image to container registry
I have checked that the image exist in container registry
I have started on a new release pipline with the following task:
A login task:
steps:
- task: Docker#2
displayName: Login
inputs:
containerRegistry: nameOfMyRegistry
command: login
A run task:
steps:
- task: Docker#2
displayName: 'Run tests'
inputs:
containerRegistry: nameOfRegistry
repository: nameOfRepository
command: run
arguments: 'nameOfImage -p 8089:8089 -f tests.py --run-time 30s -u 1 -r 1'
But after I run this I get the following error:
2021-04-26T11:39:38.9204965Z ##[error]Unable to find image 'nameOfMyImage:latest' locally
2021-04-26T11:39:38.9228444Z ##[error]docker: Error response from daemon: manifest for nameOfMyImage:latest not found: manifest unknown: manifest tagged by "latest" is not found.
So I'm not sure if I'm missing something? I put in all information to my azure container registry so I thought it would just get the image from it but it seems like it can't find it.

I know I got answer that say you can't use run with the Docker#2 task but I actually managed to get it to run now. The problem was that I used the wrong name of the image. I had to write it like this:
nameOfRegistry.azurecr.io/nameOfRepository:tag
So just bad from me but I will leave this here if someone manage to do the same mistake.

Nothing complex, looks like task input command supports only buildAndPush, build, push, login, logout and it doesn't support run reference
Something like this with script should work. reference
resources:
containers:
- container: builder
image: ubuntu:18.04
steps:
- script: echo "I can run inside the container (it starts by default)"
target:
container: builder

There is no option run in specification
https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/build/docker?view=azure-devops#task-inputs
To build an application and run tests right after the build you can use following commands:
steps:
- task: Docker#2
displayName: Login to ACR
inputs:
command: login
containerRegistry: dockerRegistryServiceConnection1
- task: Docker#2
displayName: Build
inputs:
command: build
repository: contosoRepository
tags: tag1
If you want to run tests in Docker container, you should use
Container Structure Tests
https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/test/container-structure-test-task?view=azure-devops&tabs=yaml
Azure Container Instances https://marketplace.visualstudio.com/items?itemName=DanielMeixner.de-danielmeixner-anycode&targetId=5467da56-2ffa-43cd-87b7-0b2c6da5b5af

Related

Running a docker container pulled from Azure Container Registry in Azure DevOps pipeline

I would like to run a docker container, which i pull from Azure Container Registry. All of this i would like to do in Azure DevOps pipeline.
Firstly i created sample Node.js app and Dockerized it with this tutorial: https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
Then i did my Azure Pipeline which firstly do build&push and then pull and run.
My pipeline:
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)
- task: Docker#2
displayName: Docker pull
inputs:
command: pull
containerRegistry: $(dockerRegistryServiceConnection)
arguments: container01.azurecr.io/devopsnodejs:latest
- task: Docker#2
displayName: Login to ACR
inputs:
command: login
containerRegistry: $(dockerRegistryServiceConnection)
- script: |
docker run -p 49160:8080 -d container01.azurecr.io/devopsnodejs:latest
The pipelines runs every step sucessfully, the last script with docker run prints this to Azure DevOps console
Generating script.
Script contents:
docker run -p 49160:8080 -d ***/devopsnodejs:latest
========================== Starting Command Output ===========================
/usr/bin/bash --noprofile --norc /home/vsts/work/_temp/b117892d-e34c-484c-ad8c-f99cd0a97e18.sh
7c6c9d548c4be3e4568e56ffc87cca27e698fc53b5ec15a1595cd45fe72dd143
And now the problem is that, I cannot acces the app which should return simply get request saying 'Hello World'
Im trying to go to localhost:49160, to curl -i localhost:49160 but there is only curl: (7) Failed to connect to localhost port 49160 after 2258 ms: Connection refused
Also, if i do it locally, not in azure pipelines, so I simply run docker pull container01.azurecr.io/devopsnodejs:latest and docker run -p 49160:8080 -d container01.azurecr.io/devopsnodejs:latest in powershell, the docker ps will show me this container, as well as the curl -i localhost:49160 will work. Am I able to access this locally, or if i run it in Azure Pipelines it will work only there?
Have you seen this question already, which is I think your scenario?
Cannot conect to Docker container running in VSTS
You could use a bash script with ssh to logon to the target machine and perform docker commands on the machine. The following is just an example. I have something like this in one of my pipelines.
- task: Bash#3
displayName: "Deploy image $(imageName)"
inputs:
targetType: 'inline'
failOnStderr: false
script: |
sshpass -p '$(localroot-userpassword)' ssh -o StrictHostKeyChecking=no $(localroot-username)#$(remoteHost) "{ sudo docker stop $(imageName) ; sudo docker rm $(imageName) ; sudo docker pull $(imageName) ; sudo docker run ...#add other commands separated by semicolon}"

How to run a docker container in Azure pipeline?

Azure documentation (https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/build/docker?view=azure-devops) does not specify how to run a docker container in Azure pipeline.
We can use the Docker#2 task to build / push docker images but it does not have a command to run a container. By looking at source code of older versions of Docker task I can see there has been a run command, but those are now deprecated and there is no documentation to be found.
I also followed the doc: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/container-phases?view=azure-devops
With following yaml I was able to pull a docker image which was previously pushed to ACR.
(my-acr is a service connection I added via project settings)
pool:
vmImage: 'ubuntu-16.04'
container:
image: somerepo/rnd-hello:latest
endpoint: my-acr
steps:
- script: printenv
But I cannot get the container to run.
Apparently the configuration mentioned in the question will pull the image and run the step (in this case printenv command in the script) inside the container. A temporary working directory will be mounted automatically and it will run inside that dir.
However this will not run the container itself. (CMD command defined in the Dockerfile will not be executed)
In order to run the container itself we have to login to docker registry with Docker#2 inbuilt task and then manually execute the docker run as a script. Here is an example,
trigger: none
jobs:
- job: RunTest
workspace:
clean: all
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker#2
displayName: Login to ACR
inputs:
command: login
containerRegistry: my-acr
- script: |
docker run my-registry.azurecr.io/somerepo/rnd-hello:latest
If you want, you can simply use a shell command to execute docker run and simply rely on that for all the further steps in your pipeline. You don't need to use Docker tasks in Pipelines to be able to communicate with the daemon.
Another solution would be using Azure Container Registry for running a container, but that seems like the last resort in case something went wrong with Pipelines.

Can't see container

I'm trying to push a built docker image in a release pipeline.
My docker build task yaml is:
steps:
- task: Docker#2
displayName: Build
inputs:
containerRegistry: MyRegistry
repository: myrepo/containername
command: build
Dockerfile: '$(System.DefaultWorkingDirectory)/My.dockerfile'
buildContext: '$(System.DefaultWorkingDirectory)'
arguments: '--build-arg FILE_NAME=myfile.zip'
My docker push task yaml is:
steps:
- task: Docker#2
displayName: Push
inputs:
containerRegistry: MyRegistry
repository: myrepo/containername
command: push
The log says it runs this command:
/usr/bin/docker push ***/myrepo/containername:tag
The tasks reports success, but I can't see the resulting image in dockerhub.
I wonder if the *** has anything to do with this?
I ended up not using the Azure DevOps tasks and writing the commands via a python script. It was important to docker login inside the python script also.

Building multiple images from a monorepo where each service has its own Dockerfile

I'm attempting to learn Azure DevOps Pipelines and AKS. The ultimate goal would to Build and deploy to Azure Kubernetes Service, but I'm breaking this into smaller parts so understand what is going on at each stage.
Thus, my current goal is to Build and push to Azure Container Registry.
I'm working with a pretty basic monorepo which has this simplified structure:
acr-test/
client/
Dockerfile
db/
Dockerfile
server/
Dockerfile
I'd like to generate an image for each part of the application so that a arc-test-client and arc-test-server is generated.
What is currently happening when I "Create Pipeline" in Azure DevOps and let it build the azure-pipelines.yml is it just finds the first Dockerfile and bases all the parameters on it, ignoring the other ones.
Some I'm curious:
Is it possible to create multiple images from a single azure-pipelines.yml?
Do I need multiple .yml for each Dockerfile?
Do I need to write a separate .sh to build and push these separately (example)?
Or is this simply not possible with a mono-repo?
yes, you'd need to modify the azure-pipelines.yml for that.
no. one for all or one for each dockerfile is okay
not necessary, you could use a .sh script, but probably easier to just have docker tasks in the azure-pipelines.yml
it is.
you would need to do something like this:
steps:
- task: Docker#2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository1)
dockerfile: $(dockerfilePath1)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag1)
- task: Docker#2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository2)
dockerfile: $(dockerfilePath2)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag2)
- task: Docker#2
displayName: Build and push an image to container registry
inputs:
command: buildAndPush
repository: $(imageRepository3)
dockerfile: $(dockerfilePath3)
containerRegistry: $(dockerRegistryServiceConnection)
tags: |
$(tag3)
or can have multiple something.yml in the repo and have individual builds for each component (makes a lot more sense, tbh)
alternatively, with your file structure you can just reuse the same yaml file as a template and just feed it parameters. that would reduce code duplication and allow for easier management of your builds

Fail to rename docker image at Azure pipelines

I try to rename the build image, using this task:
steps:
- task: Docker#0
displayName: 'Run a Docker TAG rename'
inputs:
containerregistrytype: 'Container Registry'
dockerRegistryConnection: 'docker hub'
action: 'Run a Docker command'
customCommand: 'tag azuretp:latest (my docker hub account)/dockerhub:myfirstpush'
but fails with the error:
"C:\Program Files\Docker\docker.exe" tag azuretp:latest ***/dockerhub:myfirstpush
Error response from daemon: No such image: azuretp:latest
Running locally i am able to rename it, using the command:
docker tag trfoutwsrv:dev (my docker hub account)/dockerhub:myfirstpush
At Azure Pipeline Services, the image name changes with build. I already try azuretp:{Build.BuildNumber} but that variable doesn't exist at the task run time.
The goal is to rename the image so it can be pushed after to my docker hub repository.
I already split the original task to rename and then push, but now i am stuck on renaming it.
in this case the solution was to use azuretp:$(Build.BuilNumber)

Resources