microsoft / DockerTools

Tools For Docker, including Visual Studio Provisioning and Publishing
Other
173 stars 26 forks source link

Dockerfile COPY with 'app' destination does nothing #429

Open jacob-winkler opened 1 month ago

jacob-winkler commented 1 month ago

I'm trying to copy some files into the app directory within my application's running docker container but they files never seem to persist when I run my container.

Here's my dockerfile:

#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
ADD ../AthleticClubAPI.Migrations/Scripts app/scripts
EXPOSE 8080
EXPOSE 8081

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["AthleticClubAPI/AthleticClubAPI.csproj", "AthleticClubAPI/"]
RUN dotnet restore "./AthleticClubAPI/./AthleticClubAPI.csproj"
COPY . .
WORKDIR "/src/AthleticClubAPI"
RUN dotnet build "./AthleticClubAPI.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./AthleticClubAPI.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AthleticClubAPI.dll"]

This line ADD ../AthleticClubAPI.Migrations/Scripts app/scripts is what's failing. I've successfully copied these files to directories that aren't the app directory. For instance ADD ../AthleticClubAPI.Migrations/Scripts scripts successfully creates a scripts folder in the container's root and populates it with the files from AthleticClubAPI.Migrations/Scripts.

My running theory right now is that this is a symptom of visual studio's fast mode docker build. I imagine that somewhere along the way the entire app directory is being overwritten by things happening in secret after the base build stage executes. However, thus far I've been unsuccessful in disabling the fast mode to test this (I've tried the ways mentioned in the article with clean and rebuild of my solution, etc. I've seen no indication in the build logs that any of the other stages run.)

Here's is my docker-compose that's being used by visual studio, in case that's relevant also.

version: '3.4'

services:
  athleticclubapi:
    image: ${DOCKER_REGISTRY-}athleticclubapi
    build:
      context: .
      dockerfile: AthleticClubAPI/Dockerfile
    ports:
      - "8080:8080"
      - "8081:8081"

  athleticclub.db:
    image: postgres:latest
    container_name: athleticclub.db
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: athletic-club
    volumes:
      - ./.containers/athleticclub-db:/var/lib/postgresql/data
    ports:
      - "5432:5432"

Hopefully someone can shed some light on what's happening here, and help me come up with a solution to solve this. I need to copy these files to the app directory, as fluent migrator seems to pre-pend the directory context that the app is running in to any scripts that I try to execute in my migrations. I'm also involved in a lengthy investigation there to see if there could be a workaround, but so far it doesn't look good.

Thanks for reading!

NCarlsonMSFT commented 1 month ago

I must admit I'm confused that your ADD command ever works. Per Docker's documentation "The <src> path must be inside the build context; you can't use ADD ../something /something" (https://docs.docker.com/reference/dockerfile/#add)

Putting that aside for the moment, you are correct that VS's fast mode is overwriting the app folder with a volume mount (docs) You can disable Fast mode by setting the msbuild property DockerDevelopmentMode to Regular (docs) in your .dcproj. Alternatively, I'd recommend using MSBuild to copy the file to the output directory, for instance adding:

<ItemGroup>
  <None Update="Scripts\CopyMe.txt">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </None>
</ItemGroup>

to your service project. This has the benefit of working in both Fast and Regular mode.

jacob-winkler commented 1 month ago

I must admit I'm confused that your ADD command ever works. Per Docker's documentation "The <src> path must be inside the build context; you can't use ADD ../something /something" (https://docs.docker.com/reference/dockerfile/#add)

I did not know that about the ADD command. Strangely this is working for me somehow. Here's a screenshot of my container's filesystem having used the ADD command specified above: image

Regarding your suggestion, I tried to modify it to copy an entire directory and all of its contents. I came across this answer on stackoverflow. Unfortunately, this didn't seem to work for me. I tried the variation in the article, along with a variation closer to what you suggested

<None Update="..\AthleticClubAPI.Migrations\Scripts\*.*">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

I tried adding this in two different locations. The .dcproj file and the .csproj file of the project that my dockerfile lives in (my app consists of multiple projects.)

Hopefully I've just missed something simple here. Cheers!

NCarlsonMSFT commented 1 month ago

If you're not getting the layout you like with the automatic copy, you may need to create a custom target as in this answer in the linked article: https://stackoverflow.com/a/44378406/12567640