Skip to content

Instantly share code, notes, and snippets.

@metinsenturk
Last active December 6, 2025 15:45
Show Gist options
  • Select an option

  • Save metinsenturk/59eb63aad772390f095d035470d93abb to your computer and use it in GitHub Desktop.

Select an option

Save metinsenturk/59eb63aad772390f095d035470d93abb to your computer and use it in GitHub Desktop.
Create docker volume with subfolders inside the volume.
# This script has functions to create a Docker volume and manages folders
# within the volume.
# Author: Metin Senturk
# Url: https://gist.github.com/metinsenturk/59eb63aad772390f095d035470d93abb
__create_volume_with_folders() {
local volume_name="$1"
local command="$2"
shift
shift
local folders=("$@")
# Create the Docker volume
vol=$(docker volume create $volume_name)
echo "Created volume: '$vol'"
# Build the mkdir command for all folders
local full_command=$command
for folder in "${folders[@]}"; do
full_command+=" //data/$folder"
done
echo "Full command: $full_command"
# Run a temporary container to create the subfolders
# --rm to remove tmp container after folder creation
# --mount to mount volume to this tmp container
# using a tmp image (alpine) to create folder(s) in the volume
docker run --rm --mount type=volume,source=$volume_name,target=//data alpine sh -c "$full_command"
}
# Function: create_volume_add_folders
# Description: Creates a docker volume and adds subfolders within it.
# Arguments:
# $1: The name of the Docker volume to create.
# $2: A list of folder names to create inside the volume.
# Returns: None
# Usage: create_volume_add_folders <volume_name> <folder1> <folder2> ...
# Example: create_volume_add_folders my_volume folder1 folder2/subfolder
create_volume_add_folders() {
local volume_name="$1"
shift
local folders=("$@")
local cmd="mkdir -p"
__create_volume_with_folders "$volume_name" "$cmd" "${folders[@]}"
echo "Created folders: ${folders[*]} in volume '$volume_name'"
}
# Function: create_volume_remove_folders
# Description: Creates a docker volume and removes subfolders within it.
# Arguments:
# $1: The name of the Docker volume to create.
# $2: A list of folder names to create inside the volume.
# Returns: None
# Usage: create_volume_remove_folders <volume_name> <folder1> <folder2> ...
# Example: create_volume_remove_folders my_volume folder1 folder2/subfolder
create_volume_remove_folders() {
local volume_name="$1"
shift
local folders=("$@")
local cmd="rm -rf"
__create_volume_with_folders "$volume_name" "$cmd" "${folders[@]}"
echo "Removed folders: ${folders[*]} in volume '$volume_name'"
}
# Example usage
# add folders to a volume
# create_volume_add_folders home_data app1 app2 app3
# remove folders to a volume
# create_volume_remove_folders home_data app1 app2
@metinsenturk

metinsenturk commented May 16, 2025

Copy link
Copy Markdown
Author

Ideally, every container or service in a docker compose file has their own volume and it makes it very easy to to use volumes this way. However, having a lot of volumes can also get messy, or you just have a use case, such as wanting to collect all of your logs into as single volume, which makes sense.

Docker allows multiple containers to use the same volume as of March 2024. However, there is a catch. Within the volume, subfolders must exist. With docker compose file, you need adjustments if you want services to use same volume but different subfolders. Here is how to do it:

  1. Create volume beforehand
# source the function
source create_volume_with_folders.sh 
# create a new volume with however many folders you want
create_volume_add_folders home_data pgadmin pgdata
  1. For each service, set subpath when setting volume. Because folders are already there, setting subpath just allows service to use that subdirectory.
services:

  pgadmin:
    image: dpage/pgadmin4:latest
    ...
    volumes:
      - type: volume
        source: home_data
        target: /var/lib/pgadmin
        volume:
          subpath: pgadmin # <----

  postgresdb:
    image: postgres:latest
    ...
    volumes:
      - type: volume
        source: home_data
        target: /var/lib/postgresql/data
        volume:
          subpath: pgdata # <----
  1. Set volume name and set external to true
volumes:
  home_data:
    # important: this volume already exists
    external: true

That's it, easy peasy.

For example, I did this for postgres and pgadmin. For the full docker compose file, see below.

services:

  pgadmin:
    image: dpage/pgadmin4:latest
    container_name: pgadmin
    restart: unless-stopped
    ports:
      - 1000:80
    volumes:
      - type: volume
        source: home_data
        target: /var/lib/pgadmin
        volume:
          nocopy: false
          subpath: pgadmin
    environment:
      - PGADMIN_DEFAULT_EMAIL=${MY_EMAIL}
      - PGADMIN_DEFAULT_PASSWORD=${MY_PASSWORD}

  postgresdb:
    image: postgres:latest
    container_name: pgdb
    restart: unless-stopped
    ports:
      - 1010:5432
    volumes:
      - type: volume
        source: home_data
        target: /var/lib/postgresql/data
        volume:
          nocopy: false
          subpath: pgdata
    environment:
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres
      POSTGRES_PASSWORD: postgres

volumes:
  home_data:
    external: true

networks:
  home_network:

That's it๐Ÿ‘

@metinsenturk

Copy link
Copy Markdown
Author

Quickly I realized that having subfolders comes with maintenance ๐Ÿ˜€. Therefore I made 2 functions, at least to make it easier to add or remove folders.

# add two folders: a1 and a2
create_volume_add_folders home_data a1 a2

# remove one: a2
create_volume_remove_folders home_data a2

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment