Search code examples
c#azuredockerazure-pipelines

Is it possible to use the artifact generated by my Azure Pipeline to build a Docker image?


I have an Azure pipeline that does a dotnet restore, a dotnet build, and a dotnet publish.

Originally, we published the artifact to an Azure App Service.

We would like to switch to Docker. Therefore, we started creating a Dockerfile and a Docker@2 task in our pipeline that builds the image and pushes it to our Azure Container Registry.

In most examples I find, within the Dockerfile, you have to do a dotnet restore, a dotnet build, and a dotnet publish.

But if I’m already doing this in my Azure pipeline, can’t I just copy-paste my artifact from the pipeline to the Docker image?

Similar to this question: Pass artifact to Docker task in Azure DevOps And this one: Build Docker with artifacts in Azure DevOps Pipeline

I tried to do it this way at the end of my pipeline:

- task: Docker@2
  inputs:
    containerRegistry: '$(containerRegistry)'
    repository: '$(imageRepository)'
    command: 'buildAndPush'
    Dockerfile: '**/Dockerfile'
    buildContext: '$(Build.ArtifactStagingDirectory)'
    tags: |
      $(Build.BuildId)

And, my Dockerfile, which is at the root of my project:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
COPY . App/
WORKDIR /App
EXPOSE 80
EXPOSE 443
ENTRYPOINT ["dotnet", "MyApplication.dll"]

The image is correctly created and published to my Azure Container Registry, but when I try to run the image on Docker Desktop, it tells me that the SDK is not available on the machine. Here is the error :

The command could not be loaded, possibly because:

  • You intended to execute a .NET application: The application 'MyApplication.dll' does not exist.
  • You intended to execute a .NET SDK command: No .NET SDKs were found.

When I'm in a local env, under the /bin/Debug... I have a MyApplication.dll. So I tried to generate the image from the sdk instead:

FROM mcr.microsoft.com/dotnet/sdk:8.0

But now the error is even stranger:

Could not execute because the specified command or file was not found. Possible reasons for this include:

  • You misspelled a built-in dotnet command.
  • You intended to execute a .NET program, but dotnet-MyApplication.dll does not exist.
  • You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.

I think that I should stick to the aspnet image.

I have two questions then: did I simply not copy (COPY . App/) to the right place in the Dockerfile, or is there something missing in my Dockerfile to import the SDK?

Is it possible to use the artifact generated by my Azure Pipeline to build a Docker image?


Solution

  • Below is the sample I attempt on my side, and it can work as expected. You can reference it to try to re-configure your pipeline and ensure all the required artifact files have been copied into the container.

    1. The Dockerfile.
    FROM mcr.microsoft.com/dotnet/aspnet:8.0
    WORKDIR /app
    EXPOSE 80
    EXPOSE 443
    
    COPY . .
    RUN dotnet myApp.dll
    ENTRYPOINT ["dotnet", "myApp.dll"]
    
    1. The pipeline YAML.
    # azure-pipelines.yml
    
    pool:
      vmImage: ubuntu-latest
    
    steps:
    - task: DotNetCoreCLI@2
      displayName: 'dotnet restore'
      inputs:
        command: restore
        projects: myApp.sln
        vstsFeed: 'myFeed'
    
    - task: DotNetCoreCLI@2
      displayName: 'dotnet build'
      inputs:
        projects: myApp.sln
        arguments: '--no-restore -c Release'
    
    - task: DotNetCoreCLI@2
      displayName: 'dotnet publish'
      inputs:
        command: publish
        publishWebProjects: false
        projects: myApp.sln
        arguments: '--no-build -c Release -o "$(Build.ArtifactStagingDirectory)"'
        zipAfterPublish: false
        modifyOutputPath: false
    
    - task: CopyFiles@2
      displayName: 'Copy Dockerfile'
      inputs:
        SourceFolder: '$(Build.SourcesDirectory)'
        Contents: '**/Dockerfile'
        TargetFolder: '$(Build.ArtifactStagingDirectory)'
    
    - task: Docker@2
      displayName: 'Build and Push image'
      inputs:
        containerRegistry: myDockerConnection
        repository: myApp
        Dockerfile: '**/Dockerfile'
        buildContext: '$(Build.ArtifactStagingDirectory)'
        tags: |
         $(Build.BuildId)
         latest