Keeping the content of a folder after bind mount

Hi, I was wondering if it was possible to maintain the files of a folder in a docker container after bind mounting that folder to an empty folder on the host machine.
I know bind mounting was not made for this but it’s the only mount that allows you to choose a specific folder.
If you have an alternative to bind mounting that keeps the original files and still let’s you choose the mounting folder, please let me know.
Thanks!

With a “bind mount” you mount a host folder into the container. If the container writes files into the folder, they will stored on host and are available even after a container re-create.

Kind of, but not really. You can create a named volume backed by a bind. When the volume is empty, it will copy the original content from the container path into the volume, before binding it into the container path. This is a one time thing! So if you choose to delete, change or add new files in your image, this mechanism will not copy them back to the volume.

You can create a named volume backed by a bind like this:

volumes:
  mybindvolume:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /host/path

From my perspective, it is bad image design to depend on that mechanism.

Instead, store your files in a different location, and create an entrypoint script that copies the files into the target location. This way you can handle if and how you want to copy new files to the target location.

Note: a bind or a named volume will always eclipse the original content of the container folder, so the original content can’t be seen or accessed anymore.

i tried using a script to copy files but it didn’t seem to work (probably because i wrote something wrong). if you could send me an example it would help a lot

How about instead you share what you did, and we find out what needs to be done differently?

sorry i forgot to publish what i did, here’s the code:

Dockerfile:

FROM --platform=linux/amd64 ubuntu:jammy

RUN apt-get update && apt-get install -y openjdk-17-jre-headless

COPY src /docker/temp
RUN mkdir /docker/mc-server
WORKDIR /docker/temp

CMD ["bash","start.sh"]

start.sh:

if [ ! -f /docker/mc-server/spigot-1.20.1.jar ]
then
    mv /docker/temp /docker/mc-server
    rm -f -r /docker/temp
fi

cd /docker/mc-server
java -Xmn1G -Xmx1G -jar spigot-1.20.1.jar nogui

this script should check if the file is in /docker/mc-server and if it’s not there it moves it to that folder, then it should move to that folder and run the spigot-1.20.1.jar file

when i run a docker container of this image it gives me an error:
start.sh: line 3: [: missing `]’
Error: Unable to access jarfile spigot-1.20.1.jar

The idea is quite okay, I see you already fixed the reason for the error message in your updated post, but left the error message about the missing ].

Since we don’t know the content of /docker/temp, it is hard to say if what you do is correct.

Some observations:

  • deleting files that come through the image, does only mark the files as deleted. It saves you no space in the filesystem at all.
  • your entrypoint script is in /docker/temp, still you delete the whole content of that folder in the entrypoint script. How is the container supposed to be restarted?
  • your main process does not run as pid 1

To fix the later, you need following modifications:

  1. add shebang, so the CMD can call /docker/temp/start.sh to run the script as pid1, then use exec to hand over pid1 to the java process:
#!/bin/bash
if [ ! -f /docker/mc-server/spigot-1.20.1.jar ]; then
    cp -r /docker/temp/* /docker/mc-server/
fi
ls -l -R /docker # debug: list directory recusively with owner and permissions
exec java -Xmn1G -Xmx1G -jar spigot-1.20.1.jar nogui
  1. to fix issue 1 and 2 I use cp instead of mv
  2. no need to change into the mc-server directory, if it’s already declared as WORKDIR in the Dockerfile.
  3. modify your Dockerfile to run the script as pid1 and change permissions on the copied files + set WORKDIR:
FROM --platform=linux/amd64 ubuntu:jammy

RUN apt-get update && apt-get install -y openjdk-17-jre-headless \
         && mkdir -p /docker/mc-server

COPY --chmod=755 src /docker/temp

WORKDIR /docker/mc-server

CMD ["/docker/temp/start.sh"]

Please share the output of the entrypoints ls -l -R command, so we see what’s going on.