dockerdocker-composeazure-devopsazure-web-app-for-containers

How do I setup Azure Pipelines to release to Azure App Service with multiple docker containers?


I am in the early stages of a development project -- and trying to nail down the CI/CD pipeline. I am running into some confusion while trying to deploy multiple docker containers into a single Azure App Service. Here is the outline of what I am trying to achieve, with as much detail along the way. Any guidance on where I am going wrong would be very appreciated. I've put checkmarks next to the items I believe I already have configured correctly.

  1. Merge code to the master branch of a Github repository ✔
  2. Have an Azure DevOps Pipeline automatically trigger✔
    • Build all of my services by running the docker-compose.yml file (this file was autogenerated by Visual Studio), tagging them with the current build id
    • Push all of the images into my azure container registry
    • Copy my docker-compose.yml to the artifact staging folder
    • Publish the artifact staging folder
    • YML that achieves:
    • trigger:
      - main
      
      pool:
        vmImage: 'ubuntu-latest'
      
      steps:
      - task: DockerCompose@0
        inputs:
          containerregistrytype: 'Azure Container Registry'
          azureSubscription: 'MYSUB'
          azureContainerRegistry: 'MYACR'
          dockerComposeFile: '**/docker-compose.yml'
          action: 'Build services'
          additionalImageTags: $(Build.BuildId)
      - task: DockerCompose@0
        inputs:
          containerregistrytype: 'Azure Container Registry'
          azureSubscription: 'MYSUB'
          azureContainerRegistry: 'MYACR'
          dockerComposeFile: '**/docker-compose.yml'
          action: 'Push services'
          includeSourceTags: true
          includeLatestTag: true
          additionalImageTags: $(Build.BuildId)
      - task: CopyFiles@2
        inputs:
          Contents: '**/docker-compose.yml'
          TargetFolder: '$(Build.ArtifactStagingDirectory)'
          OverWrite: true
      
      - task: PublishBuildArtifacts@1
        inputs:
          PathtoPublish: '$(Build.ArtifactStagingDirectory)'
          ArtifactName: 'drop'
          publishLocation: 'Container'
      
    • docker-compose.yml (names generalized)
      version: '3.4'
      
      services:
        service1:
          image: ${DOCKER_REGISTRY-}service1
          build:
            context: .
            dockerfile: src/PROJECTNAMEHERE/Dockerfile
      
        api1:
          image: ${DOCKER_REGISTRY-}api1
          build:
            context: .
            dockerfile: src/PROJECTNAMEHERE/Dockerfile
      
      
        service2:
          image: ${DOCKER_REGISTRY-}service2
          build:
            context: .
            dockerfile: src/PROJECTNAMEHERE/Dockerfile
      
  3. Have an Azure DevOps Release Pipeline with multiple stages for release to QA/Prod environments ❌
    • Add a variable to be set at Release Creation for which BuildId (from the pipeline laid out above) I'm looking to target
    • Add the artifact from above
    • Have 2 stages, QA and Prod
    • Each stage simply runs a "Azure Web App on Container Deploy" task
      • I set "Image name" equal to my 3 services from the ACR
        myacrrepo.azurecr.io/service1:$(BuildId)
        myacrrepo.azurecr.io/api1:$(BuildId)
        myacrrepo.azurecr.io/service2:$(BuildId)
        
      • I set "Configuration File" to the docker-compose.yml in the artifact
        $(System.DefaultWorkingDirectory)/_david#####.#####/drop/docker-compose.yml
        
      • YML for this step
        steps:
        - task: AzureWebAppContainer@1
          displayName: 'Azure Web App on Container Deploy'
          inputs:
            azureSubscription: 'MYSUB'
            appName: myapname
            containers: |
              myacrrepo.azurecr.io/service1:$(BuildId)
              myacrrepo.azurecr.io/api1:$(BuildId)
              myacrrepo.azurecr.io/service2:$(BuildId)
            multicontainerConfigFile: '$(System.DefaultWorkingDirectory)/_david#####.#####/drop/docker-compose.yml'
        

When all is said and done, and this release pipeline runs -- my App Service ends up being configured to grab its images from Docker Hub -- and the container images fail to pull because there are no docker hub credentials filled and the image names on my docker-compose.yml file aren't valid (e.g., "${DOCKER_REGISTRY-}api1")

I've never used docker before, so I'm struggling to get through this properly. I've tried to include as much info as possible, if there is something else you'd need please let me know -- again any help is much appreciated.


Solution

  • As I know, Azure Web App does not support to use the custom variables in the docker-compose file and only the support options can be used in the docker-compose file. You can see the support options. So you need to use the image option without build and set the image with the real image name such as myacrrepo.azurecr.io/service1:tag. When you use the Azure Container Registry, it's a private registry, so you need to set the credential of the ACR in the appSettings. See the environment variables for ACR.

    So the web app for containers task should be like this in the YAML file:

    steps:
    - task: AzureWebAppContainer@1
      displayName: Azure Web App on Container Deploy
      inputs:
        appName: myapname
        azureSubscription: $(azureSubscription)
        appSettings:
          -DOCKER_REGISTRY_SERVER_USERNAME myacrrepo
          -DOCKER_REGISTRY_SERVER_URL myacrrepo.azurecr.io
          -DOCKER_REGISTRY_SERVER_PASSWORD xxxxxxxx
        multicontainerConfigFile: $(System.DefaultWorkingDirectory)/docker-compose.yaml