How to share data between host and containers using volumes in Docker Compose

ReynierPM picture ReynierPM · Oct 12, 2016 · Viewed 29.3k times · Source

I am playing with Docker Compose and volumes

version: '2'
services:
    php-apache:
        env_file:
          - dev_variables.env
        image: reypm/php55-dev
        build:
            context: .
            args:
                - PUID=1000
                - PGID=1000
        expose:
            - "80"
            - "9001"
        extra_hosts:
            # IMPORTANT: Replace with your Docker Host IP (will be appended to /etc/hosts)
            - "dockerhost:xxx.xxx.xxx.xxx"
        volumes_from:
            - volumes_source
    volumes_source:
        image: tianon/true
        volumes:
            - ../:/var/www
    volumes_data:
        image: tianon/true
        volumes:
            - ./data/sessions:/sessions

Let's take the following facts:

  • I have a directory under the host at: ~/var/www
  • The data in such directory should persist regarding container status.
  • The container should write the data from the host under /var/www

I have read docs here but is not clear to me how to deal with data volumes and host data.

I want to share the data on the host with the container but I don't even know if the docker-compose.yml file above is right or what needs to be changed in order to achieve what I need. I know how to do it using docker run alone but doesn't have a clue for Docker Compose?

Can any help me to get this working?

Update: playing with this

I have added this lines to the docker-compose.yml file:

    volumes_from:
        - volumes_source

And I run the docker-compose up once again but this is the result:

php55devwork_volumes_data_1 exited with code 0
php55devwork_volumes_source_1 exited with code 0

I am not sure what is happening or why I am getting the error, any?

Answer

programmerq picture programmerq · Oct 12, 2016

It looks like you are trying to define a "data container". This pattern used to be common, but this isn't necessary after the docker volume system was added in Docker 1.9 (https://github.com/docker/docker/blob/master/CHANGELOG.md#190-2015-11-03)

This image that you are using, tianon/true, is designed to run the "true" command, which does nothing other than return exit code 0, and then exit. This is why the container is showing as exited.

Instead of using data containers, use a named volume. For example, the following approach using a data container:

docker create --name data-container -v /sessions tianon/true
docker run --volume-from data-container -d myapp

becomes this:

docker volume create --name sessions
docker run -v sessions:/sessions -d myapp

Since you are using compose, you can define volumes using the volumes key.

version: '2'
services:
    php-apache:
        env_file:
          - dev_variables.env
        image: reypm/php55-dev
        build:
            context: .
            args:
                - PUID=1000
                - PGID=1000
        expose:
            - "80"
            - "9001"
        extra_hosts:
            # IMPORTANT: Replace with your Docker Host IP (will be appended to /etc/hosts)
            - "dockerhost:xxx.xxx.xxx.xxx"
        volumes:
            - sessions:/sessions
            - docroot:/var/www
volumes:
    sessions:
        driver: local
    docroot:
        driver: local

Full details and an example are located here: https://docs.docker.com/compose/compose-file/compose-file-v2/

However, you also mentioned wanting to share this volume data between the container and your host. In that case, neither a data container nor named volume is necessary. You can just specify a host volume directly:

version: '2'
services:
    php-apache:
        env_file:
          - dev_variables.env
        image: reypm/php55-dev
        build:
            context: .
            args:
                - PUID=1000
                - PGID=1000
        expose:
            - "80"
            - "9001"
        extra_hosts:
            # IMPORTANT: Replace with your Docker Host IP (will be appended to /etc/hosts)
            - "dockerhost:xxx.xxx.xxx.xxx"
        volumes:
            - ./data/sessions:/sessions
            - ../:/var/www