Background

We have a few non-critical systems running as single instance Docker containers hosted on Azure WebApps. On these systems we have started to see the warning

Your app is configured with Docker Compose, which is set to retire on March 31, 2027. For multi-container support, please update your app to support sidecar containers.

So, best to get ahead of the game I looked into how to update them, factoring in that ours are all BICEP defined and deployed with Azure DevOps Pipelines

The Process

The process I followed in the end was as follows

  1. I checked the DOCKERCOMPOSE.YML file. They were very simple, just defining the container images, an optional startup command, a port and the volumes used
   version: "3"

services:
  sonarqube:
    image: sonarqube:__SonarQubeVersion__
    command: "-Dsonar.search.javaAdditionalOpts=-Dnode.store.allow_mmap=false"
    ports:
      - "9000:9000"
    volumes:
      - sonarqube-conf:/opt/sonarqube/conf
      - sonarqube-data:/opt/sonarqube/data
      - sonarqube-extensions:/opt/sonarqube/extensions
      - sonarqube-bundled-plugins:/opt/sonarqube/lib/bundled-plugins

volumes:
  sonarqube-conf:
    external: true
  sonarqube-data:
    external: true
  sonarqube-extensions:
    external: true
  sonarqube-bundled-plugins:
    external: true
  1. In the Azure Portal I selected our pre-prod instance of the WebApp and press the button to do the migration to Sidecar containers. I was presented with a dialog and entered the following
    • The we use a public registry https://index.docker.io
    • The image name, this case sonarqube:2.6.1-developer
    • The startup command -Dsonar.search.javaAdditionalOpts=-Dnode.store.allow_mmap=false
    • The port 9000
  2. I did not need to enter the volumes as these are already defined via environment variables in the WebApp (configured via BICEP)

And that was it, the WebApp was migrated!

However, I needed to update what I had under source control, so I then exported the WebApps BICEP template and compared it to what we had under source control.

Other than resource version updates, which I updated, the only change was to add a new sitecontainers block to site that defined the Sidecar container. This where I could inject the ${SonarQubeVersion} parameter that I could now pass into the template deployment from the Azure DevOps Pipeline.

resource SonarQubeWebSite 'Microsoft.Web/sites@2024-11-01' = {
  name: SonarQubeWebsite_name
  ...

    resource SonarQubeWebsiteConfigSiteContainer 'sitecontainers@2024-11-01' = {
    name: SonarQubeWebsite_name
    properties: {
        image: 'index.docker.io/sonarqube:${SonarQubeVersion}'
        targetPort: '9000'
        isMain: true
        startUpCommand: '-Dsonar.search.javaAdditionalOpts=-Dnode.store.allow_mmap=false'
        authType: 'Anonymous'
        volumeMounts: []
        environmentVariables: []
        inheritAppSettingsAndConnectionStrings: true
    }
}

Next I deleted my DOCKCOMPOSE.YML file, as this was no longer needed, and altered my Azure DevOps pipeline to inject the required container version into the BICEP task deployment as opposed to doing a string replacement in the DOCKCOMPOSE.YML file.

I then redeployed the pre-prod WebApp using the updated Azure DevOps Pipeline and BICEP to make sure everything was working as expected.

Once this was confirmed, I was able to upgrade our Prod instance using just the Azure DevOps/Bicep redeployment.