docker-composepersonal-access-token

Moving a file from host with docker-compose volume before Dockerfile is built


I have a few Dockerfiles that are dependant on a "pat" (Personal Access Token) file to be able to access a private nuget feed. I have taken some inspiration from somakdas to get this working.

To run my single Dockerfile I first create a "pat" file containing my token and build with docker build -f Services/User.API/Dockerfile -t userapi:dev --secret id=pat,src=pat .

This works as intended, but my issue is getting this to work using a docker-compose.yml file.

First I took a look at using docker-compose secrets, but it came to my attention that docker-compose secrets are access at runtime, not build-time. https://github.com/docker/compose/issues/6358

So now I'm trying to create a volume containing my pat file but I get cat: /pat: No such file or directory when the command RUN --mount=type=secret... is running. This may not be secure but it will only be running locally.

My Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
RUN wget -qO- https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | bash

WORKDIR /src
COPY ["User.API.csproj", "/Services/User.API"]

RUN --mount=type=secret,id=pat,dst=/pat export ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS="{\"endpointCredentials\": [{\"endpoint\":\"<feed>\", \"username\":\"<user>\", \"password\":\"`cat /pat`\"}]}" \
&& dotnet restore "User.API.csproj" \
&& unset VSS_NUGET_EXTERNAL_FEED_ENDPOINTS

...

My docker-compose.yml

services:
  user.api:
    container_name: User.API
    image: ${DOCKER_REGISTRY-}userapi
    build:
      context: .
      dockerfile: Services/User.API/Dockerfile
    networks:
      - app_network
    volumes:
      - ./pat:/app/src/pat

Am I only able to access docker-compose volumes after the Dockerfile is built?


Solution

  • I solved this by attacking the problem in a different way. As the main goal was to get this working locally I created Dockerfile.Local and docker-compose.local.yml. Together with this I created an .env file containing the "pat".

    The docker-compose.local.yml passes the "pat" as an argument to the Dockerfile.Local where it's used. I also discarded --mount=type=secret and set the value to VSS_NUGET_EXTERNAL_FEED_ENDPOINTS directly.

    .env file:

    PAT_TOKEN=<personal access token>
    

    docker-compose.local.yml:

    services:
      user.api:
        container_name: User.API
        image: ${DOCKER_REGISTRY-}userapi
        build:
          context: .
          dockerfile: Services/User.API/Dockerfile
        args:
          - PAT=${PAT_TOKEN}
        networks:
          - app_network
        volumes:
          - ./pat:/app/src/pat
    

    Dockerfile.Local:

    FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
    WORKDIR /app
    EXPOSE 80
    
    FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
    RUN wget -qO- https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | bash
    
    WORKDIR /src
    COPY ["User.API.csproj", "/Services/User.API"]
    
    ARG PAT
    ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS="{\"endpointCredentials\": [{\"endpoint\":\"<feed>\", \"username\":\"<user>\", \"password\":\"${PAT}\"}]}" \
    && dotnet restore "User.API.csproj" \
    && unset VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
    
    ...
    

    Note: The .env file was added to .gitignore because it is containing sensitive information. We don't want that in our repository.