skip to Main Content

I have a simple Docker Compose file to initialize a Postgres DB Instance:

version: '3.8'

services:
  my-database:
    container_name: my-database
    image: library/postgres:13.1
    volumes:
      - ./db/init-my-database.sql:/docker-entrypoint-initdb.d/init-db-01.sql
    environment:
      - POSTGRES_DB=my-database
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=password
    ports:
      - 10040:5432
    restart: always
    networks:
      - app-network

And my script init-my-database.sql looks like this:

DROP DATABASE IF EXISTS myschema;

CREATE DATABASE myschema;

-- Make sure we're using our `myschema` database
c myschema;


CREATE SEQUENCE IF NOT EXISTS recipient_seq
    START WITH 1
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;

CREATE TABLE IF NOT EXISTS recipient
(
    id                      BIGINT                   NOT NULL,
    recipient_id            VARCHAR(255)             NOT NULL,
    first_name              VARCHAR(255)             NOT NULL,
    middle_name             VARCHAR(255)             NOT NULL,
    last_name               VARCHAR(255)             NOT NULL,
    CONSTRAINT recipient_pk PRIMARY KEY (id)
);

When I tail the Docker logs I do see that the initialization script is being called. However, towards the end the database is shutdown and restarted –> "received fast shutdown request"

Why is the database restarted at the end? As the database and table created in the script is not available anymore.

Complete Docker Logs –>

my-database    | The files belonging to this database system will be owned by user "postgres".
my-database    | This user must also own the server process.
my-database    |
my-database    | The database cluster will be initialized with locale "en_US.utf8".
my-database    | The default database encoding has accordingly been set to "UTF8".
my-database    | The default text search configuration will be set to "english".
my-database    |
my-database    | Data page checksums are disabled.
my-database    |
my-database    | fixing permissions on existing directory /var/lib/postgresql/data ... ok
my-database    | creating subdirectories ... ok
my-database    | selecting dynamic shared memory implementation ... posix
my-database    | selecting default max_connections ... 100
my-database    | selecting default shared_buffers ... 128MB
my-database    | selecting default time zone ... Etc/UTC
my-database    | creating configuration files ... ok
my-database    | running bootstrap script ... ok
my-database    | performing post-bootstrap initialization ... ok
my-database    | syncing data to disk ... ok
my-database    |
my-database    | initdb: warning: enabling "trust" authentication for local connections
my-database    | You can change this by editing pg_hba.conf or using the option -A, or
my-database    | --auth-local and --auth-host, the next time you run initdb.
my-database    |
my-database    | Success. You can now start the database server using:
my-database    |
my-database    |     pg_ctl -D /var/lib/postgresql/data -l logfile start
my-database    |
my-database    | waiting for server to start....2020-12-22 23:42:50.083 UTC [45] LOG:  starting PostgreSQL 13.1 (Debian 13.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
my-database    | 2020-12-22 23:42:50.085 UTC [45] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
my-database    | 2020-12-22 23:42:50.091 UTC [46] LOG:  database system was shut down at 2020-12-22 23:42:49 UTC
my-database    | 2020-12-22 23:42:50.096 UTC [45] LOG:  database system is ready to accept connections
my-database    |  done
my-database    | server started
my-database    | CREATE DATABASE
my-database    |
my-database    |
my-database    | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init-db-01.sql
my-database    | psql:/docker-entrypoint-initdb.d/init-db-01.sql:1: NOTICE:  database "mergeletter" does not exist, skipping
my-database    | DROP DATABASE
my-database    | CREATE DATABASE
my-database    | You are now connected to database "mergeletter" as user "admin".
my-database    | CREATE SEQUENCE
my-database    | CREATE TABLE
my-database    |
my-database    |
my-database    | 2020-12-22 23:42:50.515 UTC [45] LOG:  received fast shutdown request
my-database    | waiting for server to shut down....2020-12-22 23:42:50.516 UTC [45] LOG:  aborting any active transactions
my-database    | 2020-12-22 23:42:50.521 UTC [45] LOG:  background worker "logical replication launcher" (PID 52) exited with exit code 1
my-database    | 2020-12-22 23:42:50.521 UTC [47] LOG:  shutting down
my-database    | 2020-12-22 23:42:50.541 UTC [45] LOG:  database system is shut down
my-database    |  done
my-database    | server stopped
my-database    |
my-database    | PostgreSQL init process complete; ready for start up.
my-database    |
my-database    | 2020-12-22 23:42:50.648 UTC [1] LOG:  starting PostgreSQL 13.1 (Debian 13.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
my-database    | 2020-12-22 23:42:50.649 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
my-database    | 2020-12-22 23:42:50.649 UTC [1] LOG:  listening on IPv6 address "::", port 5432
my-database    | 2020-12-22 23:42:50.652 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
my-database    | 2020-12-22 23:42:50.657 UTC [73] LOG:  database system was shut down at 2020-12-22 23:42:50 UTC
my-database    | 2020-12-22 23:42:50.663 UTC [1] LOG:  database system is ready to accept connections

3

Answers


  1. Chosen as BEST ANSWER

    Thanks for the above tip from @TorEHagermann (https://stackoverflow.com/a/65417566/5631863) I was able to resolve the problem.

    The solution was to include the following:

    volumes:
      - ./data/pgsql:/var/lib/postgresql/data
    

    Also, in my case, I needed to clear and refresh the data every time I started the container. So, I included the following in my shell script to delete the drive /data/pgsql:

    rm -rf data
    

    With that change, my docker-compose file looks like: version: '3.8'

    services:
      my-database:
        container_name: my-database
        image: library/postgres:13.1
        volumes:
          - ./db/init-my-database.sql:/docker-entrypoint-initdb.d/init-db-01.sql
          - ./data/pgsql:/var/lib/postgresql/data
        environment:
          - POSTGRES_DB=my-database
          - POSTGRES_USER=admin
          - POSTGRES_PASSWORD=password
        ports:
          - 10040:5432
        restart: always
        networks:
          - app-network
    

  2. Put simply, this happens on purpose; the author does it as part of the initialization.

    It looks like some answers can be found in the image’s entrypoint shell script:

    _main() {
        # if first arg looks like a flag, assume we want to run postgres server
        if [ "${1:0:1}" = '-' ]; then
            set -- postgres "$@"
        fi
    
        if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then
            docker_setup_env
            # setup data directories and permissions (when run as root)
            docker_create_db_directories
            if [ "$(id -u)" = '0' ]; then
                # then restart script as postgres user
                exec gosu postgres "$BASH_SOURCE" "$@"
            fi
    
            # only run initialization on an empty data directory
            if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
                docker_verify_minimum_env
    
                # check dir permissions to reduce likelihood of half-initialized database
                ls /docker-entrypoint-initdb.d/ > /dev/null
    
                docker_init_database_dir
                pg_setup_hba_conf
    
                # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless
                # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS
                export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}"
                docker_temp_server_start "$@"
    
                docker_setup_db
                docker_process_init_files /docker-entrypoint-initdb.d/*
    
                docker_temp_server_stop
                unset PGPASSWORD
    
                echo
                echo 'PostgreSQL init process complete; ready for start up.'
                echo
            else
                echo
                echo 'PostgreSQL Database directory appears to contain a database; Skipping initialization'
                echo
            fi
        fi
    
        exec "$@"
    }
    

    As for "why?" I think it’s because of desire to run as a less-privileged user.

    You can "solve" the problem by specifying a volume in the Compose file like so:

        volumes:
           - ./data/pgsql:/var/lib/postgresql/data
    

    Then, it will skip the routine to ensure DATABASE_ALREADY_EXISTS.

    Or, if that’s not helpful–you can dig into the entrypoint script a bit more.

    Login or Signup to reply.
  3. As mentioned above, the restart is intentional. The reason is that changes in some of the database server settings need restart to take effect. The entrypoint init script is a convenient place for the queries that change these settings.

    e.g.

    ALTER SYSTEM SET max_connections = 300;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search