Search code examples
dockervisual-studiodocker-composeenvironmentvisual-studio-2022

Setup multiple docker-compose envs in Visual Studio


I want to run 2 docker-compose profiles.

  • Development
  • Test

The Development profile will use appsettings.Development.json, the Test profile will use appsettings.Test.json.

The difference being that Development uses a real DB, and Test uses an InMemoryDB. enter image description here

I added two profiles: Docker Test and the default Docker Compose.

The file are the same with a small difference in the naming and environment & ports properties.

docker-compose.yml:

version: '3.9'

services:
  api:
    image: ${DOCKER_REGISTRY-}api
    build:
      context: .
      dockerfile: API/Dockerfile
    ports:
        - 80:80
    environment:
      - ASPNETCORE_ENVIRONMENT=Development

docker-compose.test.yml:

version: '3.9'

services:
  api:
    image: ${DOCKER_REGISTRY-}api-test
    build:
      context: .
      dockerfile: API/Dockerfile
    ports:
        - 80:91
    environment:
      - ASPNETCORE_ENVIRONMENT=Test

I just can't seem to find where to configure which docker-compose file to use. launchSettings.json

{
  "profiles": {
    "Docker Compose": {
      "commandName": "DockerCompose",
      "commandVersion": "1.0",
      "serviceActions": {
        "api": "StartDebugging"
      }
    },
    "Docker Test": {
      "commandName": "DockerCompose",
      "commandVersion": "1.0",
      "serviceActions": {
        "api": "StartDebugging"
      }
    }
  }
}

docker-compose.dcproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
  <PropertyGroup Label="Globals">
    <ProjectVersion>2.1</ProjectVersion>
    <DockerTargetOS>Linux</DockerTargetOS>
    <ProjectGuid>5790d2ae-ce9b-446c-aef7-6d0ecb0e9654</ProjectGuid>
    <DockerLaunchAction>LaunchBrowser</DockerLaunchAction>
    <DockerServiceUrl>{Scheme}://localhost:{ServicePort}/swagger</DockerServiceUrl>
    <DockerServiceName>api</DockerServiceName>
  </PropertyGroup>
  <ItemGroup>
    <None Include="docker-compose.override.yml">
      <DependentUpon>docker-compose.yml</DependentUpon>
      <DependentUpon>docker-compose.test.yml</DependentUpon>
    </None>
    <None Include="docker-compose.yml" />
    <None Include="docker-compose.test.yml" />
    <None Include=".dockerignore" />
  </ItemGroup>
</Project>

Solution

  • I also had the same problem and managed to find a solution by creating an issue on GitHub.

    For instance if you want to support three environments:

    • Debug: Local debugging environment, where ASPNETCORE_ENVIRONMENT would be Development
    • Dev: Dev instance running somewhere for the customer to test the latest changes, ASPNETCORE_ENVIRONMENT would be Dev
    • Staging: Staging instance with changes for the next release, ASPNETCORE_ENVIRONMENT would be Staging in this case

    Your docker-compose.dcproj would need to look something like this:

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
      <PropertyGroup Label="Globals">
        <ProjectVersion>2.1</ProjectVersion>
        <ProjectGuid>3665ba0b-49be-4e79-9c48-a1657281978a</ProjectGuid>
      </PropertyGroup>
      <ItemGroup>
        <None Include=".dockerignore" />
        <None Include="docker-compose.base.yml">
          <DependentUpon>docker-compose.yml</DependentUpon>
        </None>
        <None Include="docker-compose.staging.yml">
          <DependentUpon>docker-compose.yml</DependentUpon>
        </None>
        <None Include="docker-compose.debug.yml">
          <DependentUpon>docker-compose.yml</DependentUpon>
        </None>
        <None Include="docker-compose.dev.yml">
          <DependentUpon>docker-compose.yml</DependentUpon>
        </None>
        <None Include="docker-compose.yml" />
      </ItemGroup>
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
        <AdditionalComposeFilePaths>docker-compose.base.yml;docker-compose.debug.yml</AdditionalComposeFilePaths>
        <DockerTargetOS>Linux</DockerTargetOS>
        <DockerLaunchAction>None</DockerLaunchAction>
        <DockerServiceUrl>{Scheme}://localhost:{ServicePort}/{Scheme}://{ServiceHost}:{ServicePort}</DockerServiceUrl>
        <DockerServiceName>gateway</DockerServiceName>
        <DockerDevelopmentMode>Fast</DockerDevelopmentMode>
      </PropertyGroup>
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Dev|AnyCPU'">
        <AdditionalComposeFilePaths>docker-compose.base.yml;docker-compose.dev.yml</AdditionalComposeFilePaths>
        <DockerTargetOS>Linux</DockerTargetOS>
        <DockerLaunchAction>None</DockerLaunchAction>
        <DockerServiceUrl>{Scheme}://localhost:{ServicePort}/{Scheme}://{ServiceHost}:{ServicePort}</DockerServiceUrl>
        <DockerServiceName>gateway</DockerServiceName>
        <DockerDevelopmentMode>Fast</DockerDevelopmentMode>
      </PropertyGroup>
      <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Staging|AnyCPU'">
        <AdditionalComposeFilePaths>docker-compose.base.yml;docker-compose.staging.yml</AdditionalComposeFilePaths>
        <DockerTargetOS>Linux</DockerTargetOS>
        <DockerLaunchAction>None</DockerLaunchAction>
        <DockerServiceUrl>{Scheme}://localhost:{ServicePort}/{Scheme}://{ServiceHost}:{ServicePort}</DockerServiceUrl>
        <DockerServiceName>gateway</DockerServiceName>
        <DockerDevelopmentMode>Fast</DockerDevelopmentMode>
      </PropertyGroup>
    </Project>
    

    The docker-compose.base.yml is for general configurations which should affect all environments. Those environment-based additional compose files only set the ASPNETCORE_ENVIRONMENT env-variable, in your case this could be any ports definition or whatever you like.

    docker-compose.base.yml

    ...
    services:
      gateway:
        environment:
          - ASPNETCORE_URLS=https://+:443;http://+:80
          - DAPR_HTTP_PORT=3500
        ports:
          - "7000:80"
          - "7001:443"
          - "50001:50001"
        volumes:
          - ..
    ...
    

    docker-compose.debug.yml

    ...
    services:
      gateway:
        environment:
          - ASPNETCORE_ENVIRONMENT=Development
    ...
    

    docker-compose.dev.yml

    ...
    services:
      gateway:
        environment:
          - ASPNETCORE_ENVIRONMENT=Dev
    ...
    

    docker-compose.staging.yml

    ...
    services:
      gateway:
        environment:
          - ASPNETCORE_ENVIRONMENT=Staging
    ...
    

    Sometimes it helps to unload the docker-compose-Project and Reload it, afterwards your Configurations should also be saved in the Configuration-Manager.

    The Github-Isses which helped me understand and fix the problem: https://github.com/microsoft/DockerTools/issues/361

    Kind regards, Alex