dab0bby
dab0bby

Reputation: 2991

How to mount Docker directory into host directory with docker-compose

Imagine I have a Docker container containing some static data.

Now for development purpose I want the content of the container directory /resources mounted to my local working directory ..

docker-compose.yml:

version: '3.2'

services:
  resources:
    image: <private_registry>/resources:latest
    volumes:
    - ./resources:/resources

When running docker-compose up the folder resources is created in my working directory, but it has no content, whereas the container has content in /resources/

When using a named volume and inspecting it, it works like expected.

Upvotes: 2

Views: 9238

Answers (2)

BMitch
BMitch

Reputation: 263469

Docker provides initialization of the the volume source to the content of your image in a specific scenario:

  • It must be a named volume, not a host volume (mapping a path into the container)
  • The volume source must be empty, once there is data inside the directory it will not be changed by docker
  • Only on creation of the container (while the container is running it won't reinitialize the folder)
  • The option to disable the copy has not been set (this is the "nocopy" option in the compose file).

You are currently stuck at the first requirement, but it is possible to map any folder from the host into the container using a named volume that performs a bind mount. Here are some examples of three different ways to do that:

  # create the volume in advance
  $ docker volume create --driver local \
      --opt type=none \
      --opt device=/home/user/test \
      --opt o=bind \
      test_vol

  # create on the fly with --mount
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
    foo

  # inside a docker-compose file
  ...
  volumes:
    bind-test:
      driver: local
      driver_opts:
        type: none
        o: bind
        device: /home/user/test
  ...

Your example would look more like:

version: '3.2'

services:
  resources:
    image: <private_registry>/resources:latest
    volumes:
    - resources:/resources
volumes:
  resources:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /full/path/to/resources

Note that this directory must exist on the host in advance. The bind mount will fail without it, and unlike a host mount, docker will not create it for you.

Upvotes: 11

Software Engineer
Software Engineer

Reputation: 16100

There are a couple of things here. First, when you mount a host directory it 'shades' any existing content on the given path, effectively replacing it with the contents of the mount. So, your resources directory on your host is hiding any content in your container.

There is no easy solution to your problem. When I want to edit files in a container and on the host, I keep the files on the host and mount them in the container. If I want a copy of a container, I mount a host dir to a different dir in the container and arrange for the files to be copied.

Upvotes: 0

Related Questions