Unable to get the local directory referenced to docker - c#

I have a console application published in linux, the application reads the data from a particular directory in Linux. so if I want to run the console application, I would do the below
./myapp "/home/user1/mydata"
Files in mydata directory will be changing. It all works fine when I run the application directly in the Linux terminal.
But when I dockerize the application, I am unable to read the directory "/home/user1/mydata".
Below is Dockerfile contents
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
COPY . .
ENTRYPOINT ["./myapp"]
my intention is when I run the docker image, I will also the include path of the directory
for example
docker run myimage:latest "/home/user1/mydata"
I understand that in order to read the directory, I need first mount the directory, so I created a volume
docker volume create myvolume
and then mounted my target directory
docker run -t -d -v my-vol:/home/user1/mydata --name mycontainer myimage:latest
even after mounting when I am running the docker as
docker run myimage:latest "/home/user1/mydata"
It is still unable to read the directory. Am I doing something wrong here ? After mounting the directory do I have to change the way I call my argument in this case /home/user1/mydata ?

docker volume create myvolume will create a folder in docker system location, while -v my-vol:/home/user1/mydata will pop the /home/user1/mydata in container to that docker host's system location, typically /var/lib/docker/volumes.
So, for your case, you need to use bind mount, not volume, something like next:
docker run -t -d -v /home/user1/mydata:/home/user1/mydata --name mycontainer myimage:latest "/home/user1/mydata"
-v /home/user1/mydata:/home/user1/mydata will mount the folder /home/user1/mydata on docker host to container's /home/user1/mydata, so this I guess could meet your requirement.

Related

Azure Functions Kubernetes cannot find local.settings.json

I am trying to publish my Azure Functions App to Kubernetes but I am getting the following error when I run this command
func kubernetes deploy --name my-function-api --namespace default --registry mycontainerregistry/docker-azure-function --csharp
Unable to find project root. Expecting to find one of host.json, local.settings.json in project root.`
This is my docker file
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS installer-env
COPY . .
RUN cd /MyFunctionApp.Api && \
mkdir -p /home/site/wwwroot && \
dotnet publish *.csproj --output /home/site/wwwroot
COPY /MyFunctionApp.Api/host.json /home/site/wwwroot
COPY /MyFunctionApp.Api/local.settings.json /home/site/wwwroot
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet:2.0-appservice
FROM mcr.microsoft.com/azure-functions/dotnet:3.0
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]
As you can see I have tried adding the following lines
COPY /MyFunctionApp.Api/host.json /home/site/wwwroot
COPY /MyFunctionApp.Api/local.settings.json /home/site/wwwroot
But that does not seem to help either, so not sure what I need to do to get this working?
Any help would be appreciated.
Ok so figured this out. Azure Functions does not read local.settings.json or settings.json when running in a container. These keys need to be set as environment variables.
You need to have the local.settings.json in the the same folder that you run the func kubernetes deploy command from and that will generate a yaml file with the settings that get passed into the container when it is started.
NB: this does not seem to work with setting CORS settings. I have a new question for that here CORS Issue with Azure Functions inside AKS Cluster

appsettings.json file not found issue on docker run

I am trying to build and run a docker image of the .Net Core application.
Here is what I tried so far:
Created a .Net Core Application (.Net Core 2.2)
Published the application using below command
dotnet publish -c Release
Created a Docker file with following instructions:
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
COPY myapp/bin/Release/netcoreapp2.2/publish/ app/
ENTRYPOINT ["dotnet", "app/myapp.dll"]
Built the docker image with following command
docker build -t planservice -f Dockerfile .
Here, Image got built successfully. But, when I run the image, I'm getting the error as below:
C:\app>docker run -it --rm planservice
Unhandled Exception: System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path i
s '/appsettings.json'.
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
at myapp.Program.GetConfiguration() in C:\app\MFPServices\myapp\Program.cs:line 64
at myapp.Program.Main(String[] args) in C:\app\MFPServices\myapp\Program.cs:line 16
As per #Jawad suggestion, I have modified my Docker file to navigate to /app folder.
appsettings.js should be present in current location to run.
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
COPY myapp/bin/Release/netcoreapp2.2/publish/ app/
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "myapp.dll"]
Now, it is working properly.
Caused because it's case sensitive
Try command:
docker exec -it <container number>
cp appsettings.json AppSettings.json

Docker container won't start

Created a simple application that connects to PostgreSQL but when I containerized it using Docker i cant seem to start it and no port/s were shown when i ran the container. What seems to be the problem?
The application works without the Docker but when I containerize it, that's where the problem arises.
docker build is successful and when I use docker run
it gives me a container but when I check it using docker ps -a no ports where shown
This is what I did on docker terminal
and this is my code when connecting to PostgreSQL db
class Program
{
static void Main(string[] args)
{
using (var connection = new NpgsqlConnection("Host=localhost;Username=postgres;Password=password;Database=user"))
{
connection.Open();
connection.Execute("Insert into customer (name) values ('Mikolasola');");
var value = connection.Query<string>("Select name from customer;");
Console.WriteLine(value.First());
}
Console.Read();
}
}
here's my docker file
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "webapplication1.dll"]
Edit: Changed my Docker file to this and somehow I can get the port now
FROM microsoft/dotnet:2-sdk AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -r linux-x64 -o out
FROM microsoft/dotnet:2-runtime-deps
WORKDIR /app
COPY --from=build-env /app/out ./
ENTRYPOINT ["./webapplication1"]
But I can't run it. Here's the screenshot
Any help would be much appreciated. Thanks!
PS: im a newbie
If you're using Docker for Mac (or Docker for Windows), to access anything on the host, you need to use host.docker.internal. More on that here.
Read the connection string from config and environment variables. That will allow you to override it when running the container.
PS: im a newbie
Pro tip for you :p
You might not want to use -d on the container you're working, so you see it's logs right there. Had you not used it, you'd have seen the process exit and not wondered why there's no port shown there :)
UPDATE:
Use the Dockerfile from the original question (before the edit).
I suggested you run it without -d:
docker run -p 8080:80 --name test webapp1
This will show you the aspnet app crash. You'll see what's happening. In this case since I know what's happening I can help, but in general you want to know what's happening. You do that by not running it in a detached state for small things like this, and using docker logs when there's a lot to parse. Anyway...
... you want the container to access the database on the host, not on its localhost. You do that by using host.docker.internal as the host. Eg:
Host=host.docker.internal;Username=postgres;Password=password;Database=user
This only works if you're using Docker for Windows or Docker for Mac. Doesn't work on Docker Toolbox or on linux AFAIK.
Now you need to figure out a way your application to use host.docker.internal when running within docker and localhost otherwise. My suggestion was to read it from config.

Write Permissions in Docker Volume

I created a docker volume with:
docker volume create my-volume-name
In my console app running in the docker container, I use a creation config like this:
{
"HostConfig": {
"Binds": [
"my-volume-name:/app/my-volume-name:rw"
],
"Privileged": true
}
}
The container sees the volume, but doesn't have any permissions to write to it.
It gives me a permission denied error. (exception below is me trying to create a file in the volume).
//create a file
try{
string path = Path.Combine(Directory.GetCurrentDirectory(), "my-volume-name","example.txt");
Console.WriteLine($"PATH {path}");
if (!File.Exists(path)){
File.Create(path);
TextWriter tw = new StreamWriter(path);
tw.WriteLine($"{DateTime.Now.ToString()}The very first line!");
tw.Close();
}else if (File.Exists(path)){
using(var tw = new StreamWriter(path, true)){tw.WriteLine($"{DateTime.Now.ToString()}The next line!");}
}
}catch(Exception e){Console.WriteLine($"ERROR:{e.ToString()}");}
This is what I get:
Access to the path '/app/my-volume-name/example.txt' is denied. ---> System.IO.IOException: Permission denied
What am I missing to be able to write to the volume I created with the docker volume create command? The goal here is to have a shared volume at the host that certain containers I've created can read and write into it.
edit (the dockerfile appended):
FROM microsoft/dotnet:2.0-runtime-stretch AS base
RUN apt-get update && \
apt-get install -y --no-install-recommends unzip procps && \
rm -rf /var/lib/apt/lists/*
RUN useradd -ms /bin/bash moduleuser
USER moduleuser
RUN curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l ~/vsdbg
FROM microsoft/dotnet:2.0-sdk AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Debug -o out
FROM base
WORKDIR /app
COPY --from=build-env /app/out ./
#moving down because CI/CD builds in VSTS didnt like two copies next to each other.
ENTRYPOINT ["dotnet", "ResourceModule.dll"]
When I ls -l in the container, I see this:
drwxr-xr-x 3 root root 4096 Jul 2 13:28 my-volume-name
edit 2:
When I remove the creation of moduleuser in the dockerfile, I get this error:
ERROR:System.IO.IOException: The process cannot access the file '/app/my-volume-name/example.txt' because it is being used by another process.
But it was created - so it looks like I'm on the right path.
docker volume create my-volume-name will create space with root privileges. Please check in container with which user, your app is running. Either update the ownership of volume or run application with root user. if need further help, please provide dockerfile used for application.

Docker - understanding start/run

I know I have images and instance of these images - containers. But.
Consider I have image image created for .net core app. Here is docker file.
FROM microsoft/dotnet:1.1-sdk
WORKDIR /app
COPY . ./
RUN dotnet restore
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/dotnetapp.dll"]
My dotnetapp.dll throws exception at startup.
So, now I can buld image:
docker build . -t my-image
Then create and run image:
docker run --name my-container -t my-image
Everything as expected - my dotnetapp.dll is run and then exception is thrown (from inside app, as expected).
How I'd like to rerun (restart) my container.
So I thought that start should be enough:
docker start my-container
But nothing happens (my dotnetapp.dll was not run). I have also tried to stop and start again:
docker stop my-container
docker start my-container
run also doesn't help:
docker run --name my-container -t my-image
because container already exists.
So, till now my pattern to re-run app is:
docker rm my-container --force
docker run --name my-container -t my-image
But I don't think it is proper way.
So why start/stop doesn't work in this case? How to restart container so my dotnetapp.dll is run again without removing container?

Categories