How to mount app directory as a persistent volume when the app starts?

I have some questions about disk space and usage. I have a sqlite app with a static file database (sqlite) and when I start the app I mount this as a volume to my Docker image.

docker run -v ./data:/mnt my_image

I’m trying to understand how to accomplish this using fly deploy.

First, I’m curious which directory the app files are mounted when I use a Dockerfile in my app deployment. Then I can tell my app in the container to use that volume to start itself.

Second, I’m wondering how much disk space does fly give me in the free tier? My app isn’t big, but I could need a 1GB-2GB of disk storage.

Persistent volumes need to be added separately. You’d need to do something like:

flyctl volumes create <name> --size 10 --region <region>

If you name it data, you can add this to your fly.toml to do the equivalent of your Docker volume:

source = "data"
destination = "/mnt"

Running instances use 5GB volumes, but these do not persist between reboots. You could copy your sqlite file elsewhere periodically and pull it down to the instance at boot time, but it’s not built in.

I added a volume and tried the [mount] clause, but it didn’t work. I think the error message was "/mnt already exists."

The issue isn’t creating or using a volume, but adding the local database to the volume from the commandline. How do I put the sqlite database into a volume without going through the webapp? The webapp needs the file to be there – otherwise it won’t start.

Ah! What kind of app is this?

It’s a little bit of a pain to get data onto a volume for the first time, you’ll need to add it to your Dockerfile, then create a script that copies the file to /mnt if it doesn’t already exist before it starts your app process.

It’s a datasette app. It’s fine to add the db to the image for now, which is what I did, but it limits the functionality because, as you said, the db won’t persist between restarts, and the app will need to be read-only.

So basically, you’re saying the first time I deploy I copy the db to the volume, and the next time I change the ENTRYPOINT and use the volume mount instead. I think that would work. But it’d be great if there was a cleaner solution.

Yes, although you don’t necessarily have to change the entrypoint between deploys. Here is an entrypoint we use to do some extra logic if there are files missing:

You could do that same kind of if block to copy the sqlite file from a temp Docker Image path to the mounted volume path.

Interesting. Yes, that should work.

We should have a better method of getting files into these VMs in the next few weeks, too. This is a pain. :smiley: