Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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

like image 537
Andreas Zita Avatar asked Jun 12 '17 20:06

Andreas Zita


People also ask

How do I persist data in a docker container?

Volumes are the best way to persist data in Docker. Bind mounts may be stored anywhere on the host system. They may even be important system files or directories. Non-Docker processes on the Docker host or a Docker container can modify them at any time.

What feature in docker is used for data persistence?

Host-Based Persistence Data stored within the directory is visible inside the container mount namespace. The data is persisted outside of the container, which means it will be available when a container is removed. In host-based persistence, multiple containers can share one or more volumes.

Is docker compose persistent?

Whichever you choose, once you have set up a volume to the folder where the data is stored in the container, if you do a docker-compose down , and then a docker-compose up , your data will not be erased and it will become persistent.


1 Answers

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).

like image 71
Andreas Zita Avatar answered Nov 15 '22 06:11

Andreas Zita