docker-compose persistent data on host and contain

2020-02-06 17:25发布

问题:

I have a problem with volumes in docker-compose yml 3.0+

So I know that a volume behaves like a mount.. But I have set up a wiki and when i set a volume in the docker-compose, the data on the container will be removed (hidden)

So how can I save data from my container to my host first and the next time I start the container, it will just overrides the data I saved.

So the current situation is: I start with "docker-compose up --build" and a volume is created (empty) and will be copied to the container.. Everything in that folder on the container is deleted as a result

docker-compose.yml

version: '3.1'

services:

  doku-wiki:
    build: .
    ports:
      - '4000:80'

Dockerfile

FROM php:7.1-apache
COPY dokuwiki-stable /var/www/html/
COPY entrypoint.sh /entrypoint.sh
RUN chmod 777 /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 80

回答1:

It sounds like you are using a host volume where you map a host directory into the container. When you do this, anything at that location inside your image will not be visible, only the files as they exist on the host.

If you want to have a copy of the files from inside your image to initialize the volume, you have two options:

  1. Switched to a named volume. Docker will automatically initialize these to the contents of the image, including any permissions. If you don't require direct access to the files from outside of docker, this is the preferred solution.

  2. Change your image entrypoint and the location where you store your files in the image.

On the second option, if you want /data to be a volume for your application, you could have an entrypoint.sh that does:

#!/bin/sh

if [ ! -d "/data" ]; then
  ln -s /data_save /data
elif [ -z "$(ls -A /data)" ]; then
  cp -a /data_save/. /data/
fi
exec "$@"

Your image would need to save all the initial files to /data_save instead of /data. Then if the directory is empty it would do a copy of /data_save to your volume /data. If the volume wasn't mapped at all, then it just creates a symlink from /data to /data_save. The last line runs the CMD from your Dockerfile or docker run cli as if the entrypoint wasn't ever there. The added lines to your Dockerfile would look like:

COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]