Skip to content
Advertisement

Docker — mounting a volume not behaving like regular mount

I am new to docker so I am certain I am doing something wrong. I am also not a php developer but that shouldn’t matter in this case.

I am using a drupal docker image which has data at the /var/www/html directory.

I am attempting to overwrite this data with a drupal site from a local directory on the host system.

According to the docs this is the expected behavior

Mount a host directory as a data volume

In addition to creating a volume using the -v flag you can also mount a directory from your Docker engine’s host into a container.

$ docker run -d -P –name web -v /src/webapp:/webapp training/webapp python app.py

This command mounts the host directory, /src/webapp, into the container at /webapp. If the path /webapp already exists inside the container’s image, the /src/webapp mount overlays but does not remove the pre-existing content. Once the mount is removed, the content is accessible again. This is consistent with the expected behavior of the mount command.

However I am finding that the local drupal site files do not exist on the container. My complete workflow is as follows:

docker-compose.yml
drupal:
  container_name: empower_drupal
  build: ./build/drupal-local-codebase
  ports:
   - "8888:80"
   - "8022:22"
   - "443"
 #volumes: THIS IS ALSO NOT WORKING
 #- /home/sameh/empower-tap:/var/www/html


$ docker-compose up -d
# edit the container by snapshotting it
$ docker commit empower_drupal empower_drupal1
$ docker run -d -P --name empower_drupal2 -v /home/sameh/empower-tap:/var/ww/html empower_drupal1
# snapshot the container to examine it
$ docker commit 9cfeca48efd3 empower_drupal2
$ docker run -t -i empower_drupal2 /bin/bash

The empower_drupal2 container does not have the correct files from the /home/sameh/empower-tap directory.

Advertisement

Answer

Why this did not work

Here’s what you did, with some annotations.

$ docker-compose up -d

Given your docker-compose.yml, with the volumes section commented out, at this point you have running container, but no volumes mounted.

# edit the container by snapshotting it
$ docker commit empower_drupal empower_drupal1

All you’ve really done here is made a copy of the image you had already, unless your container makes changes to itself on startup.

$ docker run -d -P --name empower_drupal2 -v /home/sameh/empower-tap:/var/ww/html empower_drupal1

Here you have run your new copy, mounted a volume. Ok, the files are available in this container now.

# snapshot the container to examine it
$ docker commit 9cfeca48efd3 empower_drupal2

I’m assuming here that you wanted to commit the contents of the volume into the image. That will not work. The commit documentation is clear about this point:

The commit operation will not include any data contained in volumes mounted inside the container.

$ docker run -t -i empower_drupal2 /bin/bash

So, as you found, when you run the image generated by commit, but without volume mounts, the files are not there.

Also, it is not clear in your docker-compose.yml example where the volumes: section was before it was commented out. Currently it seems to be on the left margin, which would not work. It would need to be at the same level as build: and ports: in order to work on your drupal service.

What to do instead

That depends on your goal.

Just copy the files from local

If you literally just want to populate the image with the files from your local system, you can do that in Dockerfile.

COPY local-dir/* /var/www/html

You mentioned that this copy can’t work because the directory is not local. Unfortunately that cannot be solved easily with something like a symlink. Your best option is to copy the directory to the local context before building. Docker does not plan to change this behavior.

Override contents for development

A common scenario is you want to use your local directory for development, so that changes are reflected right away instead of doing a rebuild. But when not doing development, you want the files baked into the image.

In that case, start by telling Dockerfile to copy the files into the image, as above. That way an image build will contain them, volume mount or no.

Then, when you are doing development, use volumes: in docker-compose.yml, or the -v flag to docker run, to mount a volume. A volume mount will override whatever is baked into the image, so you will be using your local files. When you’re done and the code is ready to go, just do an image build and your final files will be baked into the image for deployment.

Use a volume plus a commit

You can also do this in a slightly roundabout way by mounting the volume, copying the contents elswhere, then committing the result.

# start a container with the volume mounted somewhere
docker run -d -v /home/sameh/empower-tap:/var/www/html_temp [...etc...]

# copy the files elsewhere inside the container
docker exec <container-name> cp -r /var/www/html_temp /var/www/html

# commit the result
docker commit empower_drupal empower_drupal1

Then you should have your mounted volume files in the resulting image.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement