Video Lesson: Understand Docker volumes and host bind mounts

Understand Docker volumes and host bind mounts

Understand how Docker named volumes and host bind mounts manage data between containers and the host.


Lesson Content

Docker Compose defines the services and volumes used by the project. Open docker-compose.yml and find the app service. Its volumes property contains the locations that Docker mounts into the container:

services:
  app:
    volumes: &appvolumes
      - ~/.composer:/var/www/.composer:cached
      - ~/.ssh/id_rsa:/var/www/.ssh/id_rsa:cached
      - ~/.ssh/known_hosts:/var/www/.ssh/known_hosts:cached
      - appdata:/var/www/html
      - sockdata:/sock
      - ssldata:/etc/nginx/certs

The last three entries are native Docker volumes, also called named volumes. For example, the appdata volume maps to /var/www/html inside the container. At the bottom of the file is the list of every named volume the project defines:

volumes:
  appdata:
  dbdata:
  rabbitmqdata:
  sockdata:
  ssldata:

Named volumes live inside Docker rather than directly on your host machine. This gives them native Docker performance, but it also means there is no easy way to get their data back onto your host.

The first entries under the app service use a different approach: host bind mounts. A bind mount maps a directory or file from your host into a location inside the container. For example, the host's ~/.composer directory is mounted as /var/www/.composer.

The cached flag tells Docker how to handle the mount. It is the most performant and reliable mounting strategy for this kind of host-to-container synchronization, so it is what the project uses.

The project uses bind mounts selectively, for performance reasons. Close docker-compose.yml and open docker-compose.dev.yml. When you run bin/start, Docker Compose starts the containers using both files. The &appvolumes YAML anchor pulls in the volume configuration from the base file, so both are merged together at runtime:

services:
  app:
    volumes: &appvolumes
      ## Host mounts with performance penalty, only put what is necessary here
      - ./src/app/code:/var/www/html/app/code:cached
      - ./src/app/design:/var/www/html/app/design:cached
      - ./src/app/etc:/var/www/html/app/etc:cached
      - ./src/composer.json:/var/www/html/composer.json:cached
      - ./src/composer.lock:/var/www/html/composer.lock:cached
      - ./src/nginx.conf.sample:/var/www/html/nginx.conf:cached
      #- ./src/auth.json:/var/www/html/auth.json:cached
      #- ./src/m2-hotfixes:/var/www/html/m2-hotfixes:cached
      #- ./src/patches:/var/www/html/patches:cached
      #- ./src/var/log:/var/www/html/var/log:cached
      #- ./src/var/report:/var/www/html/var/report:cached

The comment above these mounts explains the trade-off: host mounts have a performance penalty, so only put what is necessary here. The project does not mount the entire src directory, which would really slow Docker down. Instead, it mounts specific folders within app, the Composer files, and the Nginx configuration file.

You can add another bind mount for a one-off development scenario, or for a non-standard file location in Magento. In general, avoid anything Magento treats as a cache or temporary folder. Do not mount the generated directory, var/cache, or any other directory containing a large number of files that are hit on every web request.

The vendor directory is a good example. It contains many files and is accessed constantly, so mounting it from the host would noticeably reduce performance.

This selective approach to volume mounts gives you really good performance in these Docker containers, while still letting you edit the important project files on your host.

Maggie

Hey, I'm Maggie! 👋

Ask me anything.

Want to chat with Maggie?

Log in for AI tutor access.

Comments

Join the discussion!

Notes

Keep track of what you learn!