How to persist data in a Docker .NET Core Web app?
Asked Answered
F

2

6

I have trouble understanding how to work with data in a WebApi-app running with Docker.

In my app, a user can upload files which are stored like this:

~\App_Data\accounts\user123\files\<sha256>.bin

Without configuring any volumes, a Docker container with my app-image seem to work fine and writes files without any problems.

Now I'd like to configure so that the files ends up somewhere I can specify explicitly and not inside the default docker volumes folder.

I assume I need to create a volume mapping?

I have tried creating a folder and mapped it to "/App_Data". It still works as before, but I still don't see any files in this folder.

Is it a problem with write access on this folder? If not having access, will Docker fallback and write to a default volume?

What user/group should have write access to this folder? Is there a "docker" user?

I'm running this on a Synology NAS so I'm only using the standard Docker UI with the "Add Folder" button.

Here's the folders I have tried:

enter image description here

Finger answered 12/6, 2017 at 20:46 Comment(3)
How did you map the volume? This depends on the future response.Samba
Since I'm using Synology Docker UI I don't get much insight into the actual CLI under the hood, but all I do is to click "Add Folder", pick a folder from a tree and then enter "/App_Data" as the mapped path inside the container.Finger
Ok read some about this technology, it's an alternative to kitematic. I suggest you do it the hard way to understand how it works.Samba
F
4

Got it working now!

The problem was this line:

var appDataPath = env.ContentRootPath + @"\App_Data";

which translated to @"/app\App_Data" when running in Docker.

First of all I was using a Windows dir separator '\' which I don't think work on Linux. Also I don't think the path can include the "/app" since it is relative to this folder. When running this outside of Docker in Windows I got a rooted path which worked better: @"c:\wwwroot\app\App_Data"

Anyway, by changing to this it started working as expected:

var appDataPath = @"/App_Data";

Update

Had a follow up problem. I wanted the path's to work both in Docker on Linux and with normal Windows hosting but I couldn't just use /App_Data as path because that would translate to c:\App_Data on Windows. So I tried using this path instead: ./AppData which worked fine in Windows, resulting in c:\wwwroot\app\App_Data. But this would still not work in Docker unfortunately. Don't get why though. Maybee Docker is really picky with the path-matching and only accepts an exact match, i e /App_Data because that's the path I have mapped to in the container-config.

Anyway, this was a real headache, have spent 6 hrs straight with this now. This was what I came up with that worked both on Linux and Windows. Not looking terribly nice but it works:

Path.Combine(Directory.GetCurrentDirectory().StartsWith("/") ? "/" : ".", "App_Data");

If you can come up with a better looking method, please feel free to let me know.

Update 2

Ok I think I get it now. I think. When running this in Docker every path has to be rooted with '/'. Relative path's are not allowed. My app-files are copied to the container path '/app' and I have mapped my data to '/data'. The current dir is set to '/app' but to access the data I obviously have to point to '/data' and not '/app/data'. I was mistakenly believing that all paths was relative to '/app' and not '/'. The reason for this is likely since I have my data-files inside the app-folder when running this in standard Windows hosting (which probably not is a very good idea in any case). This however confused me to think the same applied for my Docker environment.

Now that I realized this it is a lot more clearer. I have to use '/data' and not './data' or '/app/data' or even 'data' (which is also relative) etc.

In standard Windows hosting where relative paths are ok I can still use './data' or any other relative path which will be resolved relative to ContentRootPath/CurrentDir. However a absolute rooted path like '/data' will not work because it will resolve to 'c:\data' (relative to the root of the current drive).

Finger answered 13/6, 2017 at 20:30 Comment(0)
S
0

I suggest you do a mapping of the volume, in the application is done as follows. Check that this is not read mode because you will not see the files.

Volume:Since Transmission is a downloader, we need a way to access the file downloaded. Without mapping a physical shared folder on Synology NAS, all downloaded files will be stored in the containers and are difficult to retrieve.In Transmission’s Dockerfile page, we saw two volumes in Transmission: /config and /downloads. We will now perform the following to map these two volumes to the physical shared folders on Synology NAS: Un-check the Read-Only option as we need to grant Transmission permission to write data into the physical drives.

enter image description here

Samba answered 13/6, 2017 at 14:43 Comment(2)
Tried that, still no data in the folders.Finger
It´s wired, because If you map the correct directory the information will be there. To check it you can execute this command docker psSamba

© 2022 - 2024 — McMap. All rights reserved.