dockerdocker-composevolumedocker-volume

How to move or clone docker volume from an implicit named volume to an explicit mounting point on the host


I want to get better persistence of the data of a docker image

my current docker-compose file have a simple definition to persist data

services:
  postgres:
   ...
   volumes:
   - pgdata:/var/lib/postgresql/data:Z
...

volumes:
  pgdata:
    driver: local

In order to avoid data loss if volume is removed and get a better control on the data I want to switch to something like

services:
  postgres:
   ...
   volumes:
     - pgdata:/var/lib/postgresql/data:Z
...

volumes:
  pgdata:
    driver: local
    driver_opts:
      o: bind
      type: none
      device: /my/path
      external: true

But is it possible to get the existing data from the old volume to /my/path before or during that switch ? (or temporary mouting both to the same target for the old one to overwrite /my/path ?)


Solution

  • For what it's worth, I think using a Docker volume (what you're doing in the first example) is better practice than using a bind mount (what you're doing in the second example). Using bind mounts often but not always brings ownership and permission challenges that you largely sidestep by letting Docker manage the storage.

    With respect to your question, just start a container that mounts your existing pgdata volume and bind mounts /my/path and then just copy data between the two:

    docker run --rm -it -v pgdata:/src -v /my/path:/dest alpine sh
    / # cp -a /src/* /dest/*
    

    Or perform a database dump and restore. Dump data from your existing database:

    $ docker exec postgres pg_dump my_db_name > pg.dump
    

    And then start the new database and import the data:

    $ docker exec postgres psql my_db_name < pg.dump