Home > Blockchain >  docker image - mounted volume is empty
docker image - mounted volume is empty

Time:11-22

I am building my first docker image. I am a beginner

It is a simple python http server. This is my DockerFile

FROM python:3.8.0-slim
WORKDIR /src
COPY src/ .
CMD [ "python", "-m", "http.server", "--cgi", "8000"]

I have a config folder in /src with some config files. I named the image "my-server"

I create a container with

docker run -d \
    --name "my-server" \
    -p 8000:8000 \
    -v /dockerdata/appdata/my-server/config/:/src/config \
--restart unless-stopped \
my-server

the issue is /dockerdata/appdata/my-server/config/ is empty on my host. I see this done on all docker images on dockerhub I use and the mounted volumes are not empty for these images. How do they do it?

CodePudding user response:

Their startup sequence explicitly copies source files into the volume, or otherwise creates them. A Docker mount always replaces the content in the image with the content of whatever's being mounted; there is no way to mount the container content to the host.

(The one exception to this "always" is, if you're using native Docker, and you're mounting a named volume, and the named volume is empty, then content from the image is copied into the volume first; but the content is never ever updated, it only works for named volumes and not other kinds of mounts, and it doesn't work on other environments like Kubernetes. I would not rely on this approach.)

If the configuration is a single file, this isn't a huge imposition. You probably already need to distribute artifacts like a docker-compose.yml file separately from the image, so distributing a default configuration isn't much more. If defaults are compiled into your application and an empty configuration is valid, this also simplifies things. Another helpful approach could be to have a search path for configuration files, and read both a "user" and "system" configuration.

If you do need to copy files out to a host directory or other mount point, I would generally do this with an entrypoint wrapper script. You will need to keep a copy of the configuration in the image somewhere that's not the actual config directory so that you can copy it when it doesn't exist. The script can be fairly straightforward:

#!/bin/sh

# Copy the default configuration if it doesn't exist
if [ ! -f config/config.yml ]; then
  cp default-config/config.yml config
fi

# Run the main container command
exec "$@"

You may need to do some shuffling in your Dockerfile; the important thing is to make this script be the ENTRYPOINT but leave the CMD unchanged.

# Save the "normal" config away; the entrypoint script will create
# the "real" config if one isn't mounted
RUN mv config default-config \
 && mkdir config

# Launch the server via the entrypoint wrapper
ENTRYPOINT ["./entrypoint.sh"] # must be JSON array syntax
CMD ["python", "-m", "http.server", "--cgi", "8000"] # unchanged

CodePudding user response:

This is expected, bind mount to a container directory will result to the content in the directory to be obscured. If you mount to a named volume, the directory’s contents are copied into the volume.

docker run -d \
  --name "my-server" \
  -p 8000:8000 \
  -v myvol:/src/config \
--restart unless-stopped \
my-server

Now if you run docker run -it -v myvol:/config --rm busybox ls /config you will see the copied content.

  • Related