Skip to content

Recurse subdirectories for docker-entrypoint-initdb.d functionality #179

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
md5 opened this issue Jul 25, 2016 · 7 comments
Closed

Recurse subdirectories for docker-entrypoint-initdb.d functionality #179

md5 opened this issue Jul 25, 2016 · 7 comments
Labels
Request Request for image modification or feature

Comments

@md5
Copy link
Contributor

md5 commented Jul 25, 2016

Over in postgis/docker-postgis#35, I had a user ask about adding their own script to /docker-entrypoint-initdb.d via docker-compose without overwriting the script I use for initializing PostGIS. My suggestion was to bind-mount individual scripts, but it dawned on me that it might be nice to be able to add scripts to subdirectories of /docker-entrypoint-initdb.d and have them sourced or executed according to the existing logic.

The main drawback I see of making this change is that it's possible that existing users of the postgres image may already have files in subdirectories of /docker-entrypoint-initdb.d that they don't want to have executed directly by the postgres entrypoint. Another minor but solvable issue is maintaining the execution order of the scripts, which I believe I documented when this functionality was originally added:

These initialization files will be executed in sorted name order as defined by the current locale, which defaults to en_US.utf8

@yosifkit
Copy link
Member

I agree about the main drawback; I'd rather not publish a breaking change. The sorting of a find should be about the same as globing; we can even make sure that everything within a directory comes before sub-directories. Maybe we hide it behind an environment flag to turn it on? If we were to add it would we limit the depth when finding scripts/sql?

Maybe we just recommend users mount a script and have it run other scripts in their folders.

@md5
Copy link
Contributor Author

md5 commented Jul 26, 2016

@yosifkit I think your second suggestion sounds better than adding another environment variable

@md5
Copy link
Contributor Author

md5 commented Jul 26, 2016

Also, I thought find uses readdir order

@wglambert wglambert added the Request Request for image modification or feature label Apr 24, 2018
@stepankuzmin
Copy link

My solution is mounting ./initdb.d folder to /initdb.d and ./initdb.sh script to /docker-entrypoint-initdb.d/initdb.sh:

for f in /initdb.d/*.sql; do
  echo "$0: running $f"
  "${psql[@]}" -f "$f"
done

@nullhack
Copy link

A simple solution is to create a file (init.sh inside /docker-entrypoint-initdb.d/initdb.sh) with the following content:

#!/usr/bin/env bash
find /docker-entrypoint-initdb.d -mindepth 2 -type f -print0 | while read -d $'\0' f; do
  case "$f" in
    *.sh)
      if [ -x "$f" ]; then
        echo "$0: running $f"
        "$f"
      else
        echo "$0: sourcing $f"
        . "$f"
      fi
      ;;
    *.sql)    echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;;
    *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;;
    *)        echo "$0: ignoring $f" ;;
  esac
  echo
done

This will recurse all sub-directories inside /docker-entrypoint-initdb.d/ and run the files the same way the original Dockerfile do

@yosifkit
Copy link
Member

yosifkit commented Dec 18, 2019

Closing since this is not something we want to add.

Since initdb scripts can be sourced (#452) and everything in the script is functionalized (#496), a custom script in initdb can easily use the docker_process_init_files function to recurse as deeply as desired.

Related issues #179, #605, docker-library/mysql#192, docker-library/mysql#193

@alexander793
Copy link

A simple solution is to create a file (init.sh inside /docker-entrypoint-initdb.d/initdb.sh) with the following content:

#!/usr/bin/env bash
find /docker-entrypoint-initdb.d -mindepth 2 -type f -print0 | while read -d $'\0' f; do
case "$f" in
*.sh)
if [ -x "$f" ]; then
echo "$0: running $f"
"$f"
else
echo "$0: sourcing $f"
. "$f"
fi
;;
*.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;;
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;;
*) echo "$0: ignoring $f" ;;
esac
echo
done

This will recurse all sub-directories inside /docker-entrypoint-initdb.d/ and run the files the same way the original Dockerfile do

In case anybody comes across this: The provided solution works, if your scripts do not depend on each other. If you need them to be executed in a specific order, prefix them with an increasing number and insert | sort -z to the second line in the provided script like: find /docker-entrypoint-initdb.d -mindepth 2 -type f -print0 | sort -z | while read -d $'\0' f; do.
This will sort all scripts in ascending order before they are executed.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Request Request for image modification or feature
Projects
None yet
Development

No branches or pull requests

6 participants