Search code examples
dockerf#type-providers

Unable to use type providers using file as a source in docker only


I am running out of ideas so I wanted to ask for help - maybe someone already had an adventure with F#, TypeProviders and Docker. The issue is that I am not able to use type provider (json or csv) with file as source in docker only (if I run it in the let's say old fashioned way then it works as expected).

The code is extra short;

Program.fs

open FSharp.Data;

type Config = JsonProvider<"config.json">

[<EntryPoint>]
let main argv =
    let config = Config.GetSample()
    printfn "%s" config.Whataver
    0

config.json

{
  "Whataver": "Value to print"
}

Dokerfile (Visual studio auto-generated one)

FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["ConsoleFsharp/ConsoleFsharp.fsproj", "ConsoleFsharp/"]
RUN dotnet restore "ConsoleFsharp/ConsoleFsharp.fsproj"
COPY . .
WORKDIR "/src/ConsoleFsharp"
RUN dotnet build "ConsoleFsharp.fsproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ConsoleFsharp.fsproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ConsoleFsharp.dll"]

Old fashion way result:

enter image description here

running in docker (linux):

enter image description here

I've already tried to use the file as embedded resource with TypePovider Embedded Resource setting but this does not change the behaviour. I can even have them embedded and this still works when I run it without docker, It even works when published as self-contained app single file... (without docker of course) But docker refuses to cooporate in any configuration. Thanks guys for any help in advance!

P.S Yes I am sure that the cinfig.json file is in the docker container.


Solution

  • The issue is that you have used Config.GetSample() which takes the path to the file you specified in provider constructor (in the angle brackets). Use instead:

    open FSharp.Data
    
    type Config = JsonProvider<"config.json">
    
    [<EntryPoint>]
    let main argv = 
        // ensure you have set the "Copy" property of config.json to "Copy Always"
        // specify here relative path to config.json, for example:
        let path = "./config.json"
        let config = Config.Load(path)
        printfn "%s" config.Whatever
        // prints "Value to print"
        0
    

    Again, ensure you have set the "Copy" property of config.json to "Copy Always".