All you need to know about Docker Compose Volumes

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn

Never miss a post!

Sign up for our newsletter and get FREE Development Trends delivered directly to your inbox.

You can unsubscribe any time. Terms & Conditions.
Categories

Docker-compose lets you create and run multi-container Docker apps. Compose allows you to configure your app’s services with YAML files. You can then run all of the services you have created using one command. There are two options for declaring volumes in Docker. The declarative method (Docker client) or the imperative way (Docker Compose Yaml File or Docker Dockerfile). To share data among multiple containers, it is easier to use docker-compose.

 

This article will explain everything you need to know about docker volume.

 

Volume Using docker-compose

It is easy to create a volume with docker-compose. Start with something similar to a container and then mention the name you want to mount in it. You can use lazy syntax if you don’t include a name.

 

Compose files uses the volume property to perform a bind mount (mount a directory from your local machine). This is similar to –volume and -v. To perform a bind (mount a directory on your local machine), you will need a relative path. This is in contrast to -v which requires an absolute path.

version: "3.2"
services:
  web:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - ./target:/usr/share/nginx/html

The containers and hosts in the above configuration use volumes in the services definition (web) to mount ./target from the host to /usr/share/nginx/html of the container. Volumes must be declared at the exact same level as services when using docker-compose. You can then refer to them as their names.

version: "3.2"
services:
  web:
    image: nginx:latest
    ports:
      - 8080:80
    volumes:
      - html_files:/usr/share/nginx/html
  web1:
    image: nginx:latest
    ports:
      - 8081:80
    volumes:
      - html_files:/usr/share/nginx/html
 
volumes:
  html_files:

This example shows how you created a volume called html_files, and then used it in both the web1 and web2 services. Multiple containers can mount the exact same volume.

 

Docker-compose up will generate a volume called If it does not already exist, _html_files. Run docker volume ls for a list of the volumes created. Start with the project name.

 

External Volume

 

We can also create a volume outside of Docker Compose and then reference it inside the ‘docker-compose.yaml’ file, as shown in an example below.

version: "3.3" 
 services: 
  frontend: 
   image: node:lts 
volumes: 
   - myvolume:/home/node/app 
  volumes: 
     myvolume: 
       external: true

The volume name “myvolume” is used in the docker-compose above file. A flag called ‘external’ has been specified. It is set to true and indicates that the volume was created outside of docker-compose.

 

Shared Volume

 

Syntax: –volumes-from container_name

 

You can create a new container by using volumes from another volume. Similar to –volume or -v, but without the need to specify a volume or mount paths.

 

$ docker run -it –name [my_new_container] –volumes-from [another_container] [image:tag] [command]

 

Note: –volumes from make sense if you are only using Docker. We can use top-level volumes for Docker-compose and make them available to multiple services. Example: Sharing web_data to app2 and app1:

volumes:
  web_data:
    external: true
services:
  app:
    image: nginx:alpine
    ports:
      - 80:80
    volumes:
      - web_data:/usr/share/nginx/html:ro
  app2:
    image: nginx:alpine
    ports:
      - 8080:80
    volumes:
      - web_data:/usr/share/nginx/html:ro

Docker Compose Volume Permissions

 

Let’s suppose you want to run WordPress in a docker container. The docker-compose.yaml is:


version: "2"
services:
  my-wpdb:
    image: mariadb
    ports:
      - "8081:3306"
    environment:
      MYSQL_ROOT_PASSWORD: [email protected]
  my-wp:
    image: wordpress
    volumes:
      - ./:/var/www/html
    ports:
      - "8080:80"
    links:
      - my-wpdb:mysql
    environment:
      WORDPRESS_DB_PASSWORD: [email protected]

According to the docker-compose, the user option sets the user id (and group id) of the process running in the container. If you set this to 1000:1000, your webserver is not able to bind to port 80 anymore. Binding to a port below 1024 requires root permissions. This means you should remove the added user: 1000:1000 statement again.

To provide the permission to the shared volume, you need to change the ownership of the directory. Run chown 1000:1000 /path/to/volume. This can be executed inside the container or directly on the host system. The change is persistent and effective immediately (no container restarted required).

In general, I think the volume should be in a sub-directory, e.g.

 

volumes:

– ./public:/var/www/html

 

Verify that the correct user has ./public. Docker will create the directory for you if you start the container but it does not exist. If this happens, root is the owner of the directory and you will need to manually change ownership as described above.

 

Alternatively, you could run the webserver with an unprivileged user (user : 1000:1000), and let the server listen to port 8080. You can then change routing to:

 

ports:

– “8080:8080”

 

You can grant full permission to a volume by using user: root in the docker compose file.

To give read permission to a volume, you can use ro.

 

volumes:

– ./:/var/www:ro #read only

 

Final Thoughts

It can be extremely helpful to organize your apps so that each app is distinct from the data. Volumes are an efficient way to achieve this. You can use them as disposable environments even in production, provided they are secure and backed up.

Docker Compose lets you configure volumes using a very short syntax string. It is up to you which syntax variation you use that determines whether you end with a volume, or a binding mount.

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn

Our website uses cookies that help it to function, allow us to analyze how you interact with it, and help us to improve its performance. By using our website you agree by our Terms and Conditions and Privacy Policy.