Visual Studio 2017 Docker - change the target for multi stage builds
Asked Answered
R

6

16

If I have a docker file that has multiple stages (such as base and build), is there a way to change the docker command that visual studio uses when debugging the container - it seems to use the first build in the docker file, without invoking the subsequent stages.

Here is my docker file:

FROM microsoft/aspnetcore:2.0.3 AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0.3 AS build
WORKDIR /src
COPY *.sln ./
COPY Web/Web.csproj Web/
RUN dotnet restore
COPY . .
WORKDIR /src/Web
RUN dotnet build -c Release -o /app

FROM build AS publish
#RUN npm install
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
# Set the entry point of the application.
ENTRYPOINT ["dotnet", "Web.dll"]

When I hit f5, it will create the container with the base image, and subsequently result in error because the project needs the node install of the aspnetcore-build image; I can resolve this by changing the base image to be the aspnetcore-build.

However, is there a way to tell the project in visual studio that it is a multi-stage build and needs to use build?

I am very new to docker so perhaps I am missing something obvious.

Radiometer answered 27/12, 2017 at 22:50 Comment(2)
Microsoft’s documentation for multi stage builds is appalling. Take two minutes more and we’d all save days.Flitting
Some might find richard-banks.org/2018/07/debugging-core-in-docker.html has useful info, but it's not easy to findTufts
P
9

To use build target configuration from docker file, you need to add a docker-compose.vs.debug.yml file. In that file, just specify build target for the service and that's it.

Example:

version: '3.4'

services:
  my.api:
    build:
      target: build
Pym answered 13/6, 2018 at 9:37 Comment(2)
Key point I didn't see mentioned anywhere... For this to work, the docker-compose.dcproj has to be set as the startup project for Visual Studio to set the proper target.Valero
I wasted so much fricking time on this until I realized the auto generated docker-compose.vs.debug.g.yml file in the obj directory always seems to make the target to be built the first target in the docker file. I just made a copy of this auto generated debug file, moved it next to my docker-compose file, and manually changed the target to what I wanted it to be. Absolutely abysmal documentation from Microsoft on this subtle detail and now I need about 6 hours of my life back.Kendre
P
7

According to this blog post, Visual Studio builds only the first image when you hit F5. However, I observed that this happens when using the Debug configuration only (as correctly stated by Matheus' Answer).

I changed all solution configurations to use the Release configuration for the docker project (.dcproj) only. This will build all images and correctly executes the multi-stage build without setting --target to whatever.

EDIT

However, this configuration cannot be debugged from within Visual Studio. To allow for local debugging inside containers, you should have a separate Dockerfile that does not use a multistage build.

Pinnati answered 4/5, 2018 at 12:51 Comment(2)
It defeats the purpose to require a different Dockerifle for release and build, so I can't really say this is a solution, but a workaround.Tufts
Good call. This info was hard to find. In addition, I set the second image by naming it "runtime": FROM mcr.microsoft.com/dotnet/aspnet:3.1-alpine AS runtime. Then I configured the csproj to run that image when it's taking its debug shortcut: <DockerfileFastModeStage>runtime</DockerfileFastModeStage>.Rosauraroscius
S
3

When you are using a multistage Dockerfile on VS 2017, you can run it in debug and release mode.

In DEBUG mode, VS will set the docker build with the "base" target and tag "DEV", so docker will build an empty image, as you already pointed.

Then VS will start a container of your image, so as soon it is running will publish the code to the current WORKDIR inside the container, start the application and attach to debug.

UPDATE

Lather that week, I found out that VS generate a docker-compose file at the obj\docker folder, that is responsible for the build in DEV mode.

Selassie answered 16/1, 2018 at 14:22 Comment(1)
Do you know if this is officially documented anywhere? Is it just me or are the Visual Studio Docker tutorials completely incomplete?Flitting
F
1

If I understand what I read today clearly, the debug steps Visual Studio takes are (In debug mode):

  • Build the project files in visual studio
  • Build a special container based on the base from the Dockerfile (as others have mentioned)
  • launch the container, with the source all mapped in using volumes, executing the built dll.
  • proceed to debug

If this does what I think it does, you can add npm install into your csproj file as a pre-build step and then your required modules should be available in docker via the volume mount.

Something like:

<Target Name="DebugRunNpm" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('node_modules') ">
    <Message Importance="high" Text="Performing first-run npm install..." />
    <Exec Command="npm install" />
</Target>
Fanchet answered 18/5, 2018 at 16:10 Comment(0)
I
0

I gave up and changed the base image from aspnetcore to aspnetcore-build, like so:

FROM microsoft/aspnetcore-build:2.0 AS base

UPDATE: In vs2019, now we can set the state target for debug :) https://developercommunity.visualstudio.com/content/problem/274941/dockerfile-image-for-building-multistage-nodejs-mi.html

Indicia answered 18/2, 2018 at 0:37 Comment(0)
C
0

Unfortunately I also got snagged by this. The answer is in this documentation:

https://learn.microsoft.com/en-us/visualstudio/containers/docker-compose-properties?view=vs-2022

and the solution can be summarised by adding the following to your docker compose project in Visual Studio:

<DockerDevelopmentMode>Regular</DockerDevelopmentMode>

When running by default, it enters a "Fast" mode which uses the

...\obj\Docker\docker-compose.vs.debug.g.yml

file.

In this file, it defines target which sets it to build.

Whereas, if you define <DockerDevelopmentMode>Regular</DockerDevelopmentMode>, it will run the release file:

...\obj\Docker\docker-compose.vs.release.g.yml

which does not override the target.

Celestecelestia answered 2/7, 2024 at 16:1 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.