docker-library/postgres

docker-entrypoint.sh ignoring my init scripts

tommyp1ckles opened this issue · 26 comments

My project directory looks like:

.
├── Dockerfile
├── docker-entrypoint-initdb.d
│   └── init-user-db.sh
└── test.sh

However the for f in /docker-entrypoint-initdb.d/*; do step in the docker-entrypoint.sh file seems to be incorrectly iterating over the contents of docker-entrypoint-initdb.d.

I ran a little test script:

# This works
for f in docker-entrypoint-initdb.d/*; do
        echo "$f"
done
echo "---"
# This is in docker-entrypoint.sh
for f in /docker-entrypoint-initdb.d/*; do
        echo "$f"
done

which gives me:

docker-entrypoint-initdb.d/init-user-db.sh

---
/docker-entrypoint-initdb.d/*

I'm not great with bash scripts, anyone know whats going on here or is this a bug?

What's in your Dockerfile?

FROM postgres:9.4

You'll need to COPY your local files into the container -- try adding COPY docker-entrypoint-initdb.d /docker-entrypoint-initdb.d to your Dockerfile. 👍

Whoops, you're right. However even after COPY'ing my scripts into that directory I still get /docker-entrypoint.sh: ignoring docker-entrypoint-initdb.d/*.

I built the postgres image myself and it works when I do:

            for f in docker-entrypoint-initdb.d/*; do
                case "$f" in
                    *.sh)     echo "$0: running $f"; . "$f" ;;
                    *.sql)    echo "$0: running $f"; "${psql[@]}" < "$f"; echo ;;
                    *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;;
                    *)        echo "$0: ignoring $f" ;;
                esac
                echo
            done

So if your Dockerfile is something like this:

FROM postgres:9.4
COPY docker-entrypoint-initdb.d /docker-entrypoint-initdb.d

Then with your directory structure from above, you should be able to see something similar to the following:

$ ls -ln . */
.:
total 8
drwxrwsr-x 2 1000 1000 4096 Sep  2 13:34 docker-entrypoint-initdb.d
-rw-rw-r-- 1 1000 1000   78 Sep  2 13:35 Dockerfile

docker-entrypoint-initdb.d/:
total 4
-rw-rw-r-- 1 1000 1000 75 Sep  2 13:34 init-user-db.sh
$ docker build -t my-postgres .
Sending build context to Docker daemon 3.584 kB
Step 1 : FROM postgres:9.4
 ---> dc08cef45d8d
Step 2 : COPY docker-entrypoint-initdb.d /docker-entrypoint-initdb.d
 ---> c6c2079ce77e
Removing intermediate container 8df5767e1f66
Successfully built c6c2079ce77e
$ docker run -it --rm my-postgres ls -ln /docker-entrypoint-initdb.d
total 4
-rw-rw-r-- 1 0 0 75 Sep  2 20:34 init-user-db.sh
$ docker run -it --rm my-postgres
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
creating template1 database in /var/lib/postgresql/data/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating collations ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
loading PL/pgSQL server-side language ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok
syncing data to disk ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    postgres -D /var/lib/postgresql/data
or
    pg_ctl -D /var/lib/postgresql/data -l logfile start

****************************************************
WARNING: No password has been set for the database.
         This will allow anyone with access to the
         Postgres port to access your database. In
         Docker's default configuration, this is
         effectively any other container on the same
         system.

         Use "-e POSTGRES_PASSWORD=password" to set
         it in "docker run".
****************************************************
waiting for server to start....LOG:  database system was shut down at 2016-09-02 20:37:25 UTC
LOG:  MultiXact member wraparound protections are now enabled
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started
 done
server started
ALTER ROLE


/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init-user-db.sh
THIS IS A TEST

MORE LINES
FOO BAR BAZ

AND MORE TEST


waiting for server to shut down....LOG:  received fast shutdown request
LOG:  aborting any active transactions
LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
 done
server stopped

PostgreSQL init process complete; ready for start up.

LOG:  database system was shut down at 2016-09-02 20:37:26 UTC
LOG:  MultiXact member wraparound protections are now enabled
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started
^CLOG:  received fast shutdown request
LOG:  aborting any active transactions
LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down

It can also be accomplished with docker run -it --rm -v "$PWD"/docker-entrypoint-initdb.d/:/docker-entrypoint-initdb.d/ postgres:9.4.

I'm seeing this issue too, using docker-compose with a node app and postgres. The folder is being copied into / and I have docker-entrypoint-initdb.d/init.sh there, but I still see /docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*

I still have yet to be able to reproduce this issue. It can't be permission based, since the container is still running as root when it is trying to run the scripts. Though it might be possible to fail if user namespaces is turned on and the files are mounted with -v.

Can someone show me a minimum reproducible case? ie, folder structure, Dockerfile, other files, docker run line. Preferably with information about the system they are running it on as well like docker info and docker version.

woto commented

@DCRichards @tommyp1ckles remove db image and recreate it, i've got same issue.

This is docker-compose issue for my configuration. I run docker-compose using script startup.sh.

Dockerfile:

FROM postgres:9.6
ADD init.sh /docker-entrypoint-initdb.d/
RUN chmod 0755 /docker-entrypoint-initdb.d/init.sh
RUN echo "host all  all    0.0.0.0/0  md5" >> /var/lib/postgresql/pg_hba.conf
RUN echo "listen_addresses='*'" >> /var/lib/postgresql/postgresql.conf
EXPOSE 5432

init.sh:

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
    CREATE TABLE USERS (user_id varchar(200), password varchar(200));
    CREATE TABLE ROLES (user_id varchar(200), user_role varchar(200));
EOSQL

docker-compose.yml:

version: '2'
services:
    postgres:
        image: postmy
        ports:
            - "5432:5432"
    wildfly:
        image: local/wildmy
        ports:
            - "9990:9990"
            - "8080:8080"
        depends_on: 
            - postgres

startup.sh:

docker-compose down
docker-compose up &
sleep 10
docker exec wildflypostgres_wildfly_1 /opt/jboss/wildfly/bin/jboss-cli.sh --file=/tmp/createdatasource.cli

postmy log:

server started
ALTER ROLE
2016-11-09T07:12:01.247601622Z 
2016-11-09T07:12:01.247665187Z 
/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
2016-11-09T07:12:01.248064429Z 

My issue was about wrong startup image name (typo). Since i correct it, all works fine.

Adding my two pence worth

Using a postgres image to run a django site with docker-compose

Here's the element of my docker-compose.yml file that is relevant

version: '2'
services:
  db:
    container_name: db
    image: postgres
    volumes:
      - ./scripts:/docker-entrypoint-initdb.d postgres

I have a data.sql file in my apps scripts folder, and I can delete all the volumes, containers and images but it always says "/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*"

I'm probably doing something stupid, any help would be greatly appreciated.

Apologies for the noise, solved my issue by taking this approach

http://stackoverflow.com/questions/37834435/docker-compose-postgresql-import-dump

Namely, a separate dockerfile for postgres within the project that adds the file.

Don't forget to rebuild and docker-compose rm -v!!!

Same issue here, only solution is remove image and try again ? What does this happened ?

@ScreamZ, the initdb.d scripts are only executed the first time the container is started (and the database files are empty). If the database files still exist then the initdb.d scripts are ignored (e.g. when you mount a local directory or when docker-compose saves the volume and reuses it for the new container).

Longish explanation: #203 (comment).

As for any other cause of the problem described in this issue; I have not been able to see a reproducible case.

s111d commented

Check the comment above on volumes. Removing named volume in Postgres section fixed the issue in my case.

I had the same issue, the init scripts were ignored. I was mounting the directory containing my init scripts via docker-compose.yml, but I had a typo in my local path which resulted in this behaviour. Fixing the path, fixed the issue and the scripts were run properly.
Just in case someone has the same issue, or you want to reproduce it. :)

Closing given that:

  1. the original issue seems to be environmental
  2. follow-up questions have been resolved
  3. this thread has become a target for unrelated issues too 😅

In the future, these sorts of questions/requests would be more appropriately posted to the Docker Community Forums, the Docker Community Slack, or Stack Overflow. Thanks!

For what it is worth, what was happening to me is I had restart: always set up in my docker-compose file. That would cause it to start, run the scripts, and if one of them failed it would stop. Then it would automatically restart, but the scripts would not have fully run, and it won't run them again so it doesn't fail anymore but it looks like nothing happened.

@ScreamZ, the initdb.d scripts are only executed the first time the container is started (and the database files are empty). If the database files still exist then the initdb.d scripts are ignored (e.g. when you mount a local directory or when docker-compose saves the volume and reuses it for the new container).

The fact these are being skipped should probably be logged.

The fact these are being skipped should probably be logged.

It's not really so much that they're being skipped, but that they're explicitly defined to only run when the database is first initialized (ie, when the mounted volume is empty). If we get an already initialized folder passed in, we defer all image behavior and simply start postgres (so the output of the container is thus an accurate representation of the raw postgres log from that point forward).

It's not really so much that they're being skipped

Multiple people have been confused by this implementation detail. Additionally, the documentation on dockerhub is vague about this behavior.

Adjusting docs: docker-library/docs#1436. 😸

beck commented

Same issue, discovered one machine was 👍 and another was 👎. The issue was file permissions (one box had a 027 umask). The fix for me was updating a wrapper script with:

chmod 755 ./scripts
chmod 644 ./scripts/*

Would be lovely if:

  • git allowed you to record all file permissions
  • docker would surface an error if mounting an unreadable directory
  • docker-entrypoint.sh special cases /docker-entrypoint-initdb.d/*

If someone has a better workaround, would love to see it (other than updating the umask config).

@woto you're my god by now

If you still encounter this in 2022 - check if you have another postgres running on the same port. 🤦🏻

Adding to this: if you're encountering this with .sh files - make sure you set chmod +x executable bit on them.