Home > database >  Referencing a project in a parent directory from my Dockerfile
Referencing a project in a parent directory from my Dockerfile

Time:02-22

So I have a .NET 6 solution structured like so:

MySolution
|
 -- RecipeManagement
|
 ---- src
|
 ------ RecipeManagement
|
 -------- RecipeManagement.csproj
|
 -------- Dockerfile
|
 ---- tests
|
 ------ RecipeManagement.IntegrationTests
|
 -------- RecipeManagement.IntegrationTests.csproj
|
 ------ RecipeManagement.UnitTests
|
 -------- RecipeManagement.UnitTests.csproj
|
 -- SharedKernel
|
 ---- SharedKernel.csproj
|
 -- dockercompose.yaml

I'm having trouble getting my Dockerfile to properly reference my SharedKernel class project.

Without the SharedKernel, something like this usually works fine:

dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY ["RecipeManagement.csproj", "./"]
RUN dotnet restore "./RecipeManagement.csproj"

# Copy everything else and build
COPY . ./
RUN dotnet build "RecipeManagement.csproj" -c Release -o /app/build

FROM build-env AS publish
RUN dotnet publish "RecipeManagement.csproj" -c Release -o /app/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .

ENV ASPNETCORE_URLS=https:// :8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "/app/RecipeManagement.dll"]

compose:

version: '3.7'

services:
  recipemanagement-db:
    image: postgres
    restart: always
    ports:
      - '52450:5432'
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=dev_recipemanagement
    volumes:
      - recipemanagement-data:/var/lib/postgresql/data

  recipemanagement-api:
    build:
      context: ./RecipeManagement/src/RecipeManagement
      dockerfile: Dockerfile
    ports:
      - "52451:8080"
    environment:
      ASPNETCORE_ENVIRONMENT: "Development"
      DB_CONNECTION_STRING: "Host=recipemanagement-db;Port=5432;Database=dev_recipemanagement;Username=postgres;Password=postgres"

    volumes:
      - ~/.aspnet/https:/https:ro
        
volumes:
  recipemanagement-data:

But, once I try to bring in the SharedKernel, it gets unhappy. Note the differences:

  1. Updated context and dockerfile path in compose
  2. Updated Copy csproj and restore as distinct layers section to account for new context and project

dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY ["RecipeManagement/src/RecipeManagement/RecipeManagement.csproj", "RecipeManagement/"]
COPY ["SharedKernel/SharedKernel.csproj", "SharedKernel/"]
RUN dotnet restore "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj"

# Copy everything else and build
COPY . ./
RUN dotnet build "RecipeManagement.csproj" -c Release -o /app/build

FROM build-env AS publish
RUN dotnet publish "RecipeManagement.csproj" -c Release -o /app/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .

ENV ASPNETCORE_URLS=https:// :8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "/app/RecipeManagement.dll"]

compose:

version: '3.7'

services:
  recipemanagement-db:
    image: postgres
    restart: always
    ports:
      - '52450:5432'
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=dev_recipemanagement
    volumes:
      - recipemanagement-data:/var/lib/postgresql/data

  recipemanagement-api:
    build:
      context: .
      dockerfile: RecipeManagement/src/RecipeManagement/Dockerfile
    ports:
      - "52451:8080"
    environment:
      ASPNETCORE_ENVIRONMENT: "Development"
      DB_CONNECTION_STRING: "Host=recipemanagement-db;Port=5432;Database=dev_recipemanagement;Username=postgres;Password=postgres"

    volumes:
      - ~/.aspnet/https:/https:ro
        
volumes:
  recipemanagement-data:

The result here being that it can't find the file for some reason:

------
 > [build 5/8] RUN dotnet restore "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj":
#13 0.374 MSBUILD : error MSB1009: Project file does not exist.
#13 0.374 Switch: RecipeManagement/src/RecipeManagement/RecipeManagement.csproj
------

Potentially of note, if i just adjust the context and dockerfile path with the original project that doesn't have a shared kernel, i start getting yelled at about my test projects not being included

Edit

In response to the answer from @Paolo, I tried both of the below dockerfiles running docker build -f RecipeManagement/src/RecipeManagement/Dockerfile . from my root MySolution directory and get the same error. I've tried a few different dockerfile iterations. see two below:

one iteration:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY ["RecipeManagement/src/RecipeManagement/RecipeManagement.csproj", "RecipeManagement/"]
COPY ["SharedKernel/SharedKernel.csproj", "SharedKernel/"]
RUN dotnet restore "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj"

# Copy everything else and build
COPY . ./
RUN dotnet build "RecipeManagement.csproj" -c Release -o /app/build

FROM build-env AS publish
RUN dotnet publish "RecipeManagement.csproj" -c Release -o /app/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .

ENV ASPNETCORE_URLS=https:// :8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "/app/RecipeManagement.dll"]

second iteration:

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
ENV ASPNETCORE_URLS=https:// :8080
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["RecipeManagement/src/RecipeManagement/RecipeManagement.csproj", "RecipeManagement/"]
COPY ["SharedKernel/SharedKernel.csproj", "SharedKernel/"]
RUN dotnet restore "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj"
COPY . .
WORKDIR "/src/RecipeManagement"
RUN dotnet build "RecipeManagement.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "RecipeManagement.csproj" -c Release -o /app/publish

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

** Update: if i change RUN dotnet restore "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" to RUN dotnet restore "RecipeManagement/RecipeManagement.csproj"

in option 2 it gets past the error, but wants to build all my tests

CodePudding user response:

You can achieve the desired behavior by using docker build with the -f option to build the image.

From the MySolution folder, you can run:

docker build -f RecipeManagement/src/RecipeManagement/Dockerfile .

This command will build the Dockerfile from the nested folder with the current directory, MySolution, as the root of the build context.

CodePudding user response:

okay, so i updated it to have the copy paths mirror my solution paths and that seemed to do the trick! also had a typo in http vs https but that's seprate :-)

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY ["RecipeManagement/src/RecipeManagement/RecipeManagement.csproj", "./RecipeManagement/src/RecipeManagement/"]
COPY ["SharedKernel/SharedKernel.csproj", "./SharedKernel/"]
RUN dotnet restore "./RecipeManagement/src/RecipeManagement/RecipeManagement.csproj"

# Copy everything else and build
COPY . ./
RUN dotnet build "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" -c Release -o /app/build

FROM build-env AS publish
RUN dotnet publish "RecipeManagement/src/RecipeManagement/RecipeManagement.csproj" -c Release -o /app/out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=publish /app/out .

ENV ASPNETCORE_URLS=http:// :8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "/app/RecipeManagement.dll"]
version: '3.7'

services:
  recipemanagement-db:
    image: postgres
    restart: always
    ports:
      - '52450:5432'
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=dev_recipemanagement
    volumes:
      - recipemanagement-data:/var/lib/postgresql/data

  recipemanagement-api:
    build:
      context: .
      dockerfile: RecipeManagement/src/RecipeManagement/Dockerfile
    ports:
      - "52451:8080"
    environment:
      ASPNETCORE_ENVIRONMENT: "Development"
      DB_CONNECTION_STRING: "Host=recipemanagement-db;Port=5432;Database=dev_recipemanagement;Username=postgres;Password=postgres"

    volumes:
      - ~/.aspnet/https:/https:ro
        
volumes:
  recipemanagement-data:
  • Related