Cannot connect to container using its alias in a multi-stage pipeline in Azure DevOps

Viewed 529

I am struggling to understand service containers and have some simple scenario working. The documentation here: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/service-containers?view=azure-devops&tabs=yaml is not very clear to me, and the examples are not even valid (see https://github.com/MicrosoftDocs/vsts-docs/issues/4187

I'd like to have DevOps CI/CD work with my tests with a container running and accessible at certain Uri so that my tests can run in DevOps as they run locally.

For this example I am using Azurite docker image. If I run the container locally with the following:

version: '3'
services:
    sqlserver:
        image: mcr.microsoft.com/azure-storage/azurite:3.6.0
        restart: always
        ports:
            - 10000:10000
            - 10001:10001
# Run
# docker-compose -f azurite.yml up -d 

I can connect from my integration tests to this container to run the tests against, by using the following Uri: http://127.0.0.1:10000/devstoreaccount1/landing

In other words, my tests work well locally when accessing 127.0.0.1:10000 because there's a container listening on that address.

I need my tests to work also in Azure DevOps CI/CD so I have the following multi-stage pipelines:

trigger:
- master

pool:
  vmImage: ubuntu-18.04

variables:
  - group: nuget-variables
  - name: NUGET_FOLDER_NAME
    value: nupkgs
  - name: PIPELINE_ARTIFACT_NAME
    value: $(Build.BuildNumber)
  - name: PATH_PIPELINE_ARTIFACT_NAME
    value: $(Pipeline.Workspace)/$(PIPELINE_ARTIFACT_NAME)
  - name: NUGET_API_KEY
    value: $(nuget-api-key)
  - name: NUGET_FEED
    value: $(nuget-feed)
  - name: PRERELEASE_SUFFIX
    value: $(nuget-prerelease-suffix)

resources:
  containers:
    - container: azurite
      image: mcr.microsoft.com/azure-storage/azurite:3.6.0
      ports:
      - 10000:10000
      - 10001:10001

stages:
  - stage:
    displayName: 'Build'
    jobs:
      - job: 'Build'
        displayName: 'Build & Create nuGet Package'
        services:
            azurite: azurite
        steps:
          - task: UseDotNet@2
            displayName: 'Use .NET Core sdk 3.1'
            inputs:
              packageType: sdk
              version: 3.1.x
              includePreviewVersions: false
              installationPath: $(Agent.ToolsDirectory)/dotnet
          - task: NuGetAuthenticate@0
            displayName: 'Authenticate in NuGet feed'
          - script: dotnet restore --no-cache --force
            displayName: 'Restore dependencies'
          - script: dotnet build --configuration Release --no-restore
            displayName: 'Build with Release Configuration'
          - script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll
            displayName: 'Run unit tests'
          - script: dotnet vstest test/*IntegrationTests/bin/Release/**/*IntegrationTests.dll
            displayName: 'Run integration tests'
          - script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME) --include-symbols -p:SymbolPackageFormat=snupkg
            condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
            displayName: 'Create release nuGet'
          - publish: $(System.DefaultWorkingDirectory)/$(NUGET_FOLDER_NAME)
            artifact: $(PIPELINE_ARTIFACT_NAME)
            displayName: 'Publish pipeline artifact'
  - stage:
    displayName: 'Release'
    condition: succeeded()
    jobs:
      - job: 'Publish'
        displayName: 'Publish nuGet Package'
        steps:
          - download: current
            artifact: $(PIPELINE_ARTIFACT_NAME)
            displayName: 'Download pipeline artifact'
          - script: echo More irrelevant things here

As you can see, I specify the image for Azurite, do the mapping ports, etc. but my tests fail because they cannot connect to http://127.0.0.1:10000/devstoreaccount1/landing

I've tried naming the container and replacing the Uri in my tests to try to connect to http://azurite:10000/devstoreaccount1/landing

If I place the services section outsite a job just before stages it fails as invalid YML.

I don't really understand how to achieve the equivalent to my docker-compose with Azure DevOps to have my tests pass in CI/CD. Hopefully you spot the problem or provide an understandable explanation on how this works. Also, if anybody knows how could I "debug" this locally, I'd be more than happy to learn some tricks.


UPDATE 1: I don't know why, but now it worked with 127.0.0.1 Uri and the above yml (services defined at the job where integration tests run). The question remains though, and any good explanation on why this works and referring with the name azurite didn't would be the valid answer.

1 Answers

In your comment, you asked "why the 127.0.0.1 Uri is available but not the hostname azurite". That's because you're not running the job inside a container. Refer to the documentation.

This pipeline starts the latest nginx and redis containers, and then publishes the specified ports to the host. Since the job is not running in a container, there's no automatic name resolution. This example shows how you can instead reach services by using localhost. In the above example we provide the port explicitly (for example, 8080:80).

You need to run your tests inside of a container if you want host name resolution to work.

Related