13

I have a docker container that holds a django app. The static files are produced and copied to a static folder.
container folder hierarchy:

- var
    - django
        - app
        - static

before i build the docker image, i run ./manage.py collectstatic so the static files are in the /var/django/static folder. To expose the app and serve the static files, i have on the host an nginx. The problem is that if i do a volume between the static folder and a designated folder on the host, when i run the docker container, the /var/django/static folder in the container gets deleted (well, not deleted but mounted). Is there any way to overcome this? as in set the volume but tell docker to take the current files as well?

Mr T.
  • 4,278
  • 9
  • 44
  • 61
  • Why not build a `nginx` docker image instead? So what you would do here is to do whatever that is needed to `build` your django web application and then add (using dockerfile's `ADD` keyword) to push the static files into the the nginx image? – Samuel Toh Aug 14 '16 at 09:47
  • because thats how our qa/integration/production env works. the nginx is on the host and does not run on docker. – Mr T. Aug 14 '16 at 10:39
  • I see. So you are looking at mounting a container's files out onto the host which is pretty unconventional because people typically do it the other way round. So what is the purpose of having a container where you are only interested in its files? Why not just symbolic link the static file directory to the directory which `ngix` will serve its files. – Samuel Toh Aug 14 '16 at 10:46

3 Answers3

11

Volumes are treated as mounts in Docker, which means the host directory will always be mounted over the container's directory. In other words, what you're trying to do isn't currently possible with Docker volumes.

See this Github issue for a discussion on this subject: https://github.com/docker/docker/issues/4361

One possible work-around would be to have a docker volume to an empty directory in your container, and then in your Docker RUN command (or start-up script), copy the static contents into that empty directory that is mounted as a volume.

C. Reed
  • 2,382
  • 7
  • 30
  • 35
  • My solution was close to yours. After i started the container and mounted the volume, i just ran anothe collectstatic command which repopulated the volume with the files. – Mr T. Aug 16 '16 at 11:54
  • to clarify, are you saying that one can get around this issue in the build process by executing copy so this is taken care of automatically? Do you mean the Dockerfile COPY command? or use RUN "cp /files1 /files2"? I can populate the mounted directory by executing commands in the container after the fact, but this feels like an unnecessary and avoidable manual step. – user658182 Jul 08 '21 at 18:27
6

Reading from: Dockers Volume Page

Volumes have several advantages over bind mounts:

New volumes can have their content pre-populated by a container.


Similar example using docker-compose

Using nginx's default webpage folder as the example:

$ docker volume create xmpl
$ docker run -v xmpl:/usr/share/nginx/html nginx

Will yield all the files on the host system via:

$ docker inspect xmpl
...
"Mountpoint": "/var/lib/docker/volumes/xmpl/_data"

And you can then view the files on the host:

# ls /var/lib/docker/volumes/xmpl/_data                               
  50x.html  index.html

And finally to use it from /var/nginx/static:

# mkdir -p /var/nginx
# ln -s /var/lib/docker/volumes/xmpl/_data /var/nginx/static
# ls /var/nginx/static
  50x.html  index.html
Community
  • 1
  • 1
Tyhal
  • 759
  • 9
  • 12
  • Note that the `volumes` directory is owned by root and not group or world readable, at least on Debian/Ubuntu. nginx probably cannot see those files even with the symlink. – blee Mar 09 '23 at 05:58
5

Another nice solution: 1. Install SSHd 2. Install SSHFS on Host 3. Mount folder inside docker container to outside (host) by SSHFS

xnohat
  • 311
  • 3
  • 4