IotEdge: Setting file permissions
When you implement .NET Core module in C#, which reads/writes files, you might run in several permission related issues. For example, your module outputs some configuration file in the output folder of build process. You can do it typically by setting file property in solution explorer to "copy always" or "copy if newer".
This is all fine, but if you build image for Linux containers, your application might (will) fail with following exception, when file is touched:
System.IO.IOException: Permission denied
The reason for this is that your application by default has no permission to read any file copied to output folder. If you run container with bash and list permissions, you will see following:
docker run -it --entrypoint bash IMAGENAME
Then execute following in container to see file permissions:
ls -la
Here is a typical result:
8 -rwxr-xr-x 1 root root 4530
Workaround
In my example, I have a Machine Learning model file model.json and want to set extra permissions. The workaround for this issue is to place RUN chmod inside of dockerfile. However the command must be placed before USER moduleuser.
This is dockerfile, which sets correrctly permissions:
FROM microsoft/dotnet:2.0-sdk AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM microsoft/dotnet:2.0-runtime
WORKDIR /app
COPY --from=build-env /app/out ./
# Note, this is before USER moduleuser
RUN chmod 777 /app/model.json
RUN useradd -ms /bin/bash moduleuser
USER moduleuser
ENTRYPOINT ["dotnet", "xyz.dll"]
This is an example of dockerfile, which will NOT set permissions on file. It will fail with error:
chmod: changing permissions of '/app/model.json': Operation not permitted
FROM microsoft/dotnet:2.0-sdk AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM microsoft/dotnet:2.0-runtime
WORKDIR /app
COPY --from=build-env /app/out ./
RUN useradd -ms /bin/bash moduleuser
USER moduleuser
# This does not work, because it is executing after USER moduleuser
RUN chmod 777 /app/model.json
ENTRYPOINT ["dotnet", "xyz.dll"]
You can follow this issue on github.