在 docker-entrypoint-initdb.d

时间:2020-12-22 23:51:30

标签: postgresql docker

我有一个简单的 Docker Compose 文件来初始化 Postgres 数据库实例:

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

我的脚本 init-my-database.sql 看起来像这样:

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)
);

当我跟踪 Docker 日志时,我确实看到正在调用初始化脚本。但是,最后数据库关闭并重新启动 --> "收到快速关闭请求"

为什么数据库最后重启了?由于脚本中创建的数据库和表不再可用。

完整的 Docker 日志 -->

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

2 个答案:

答案 0 :(得分:3)

简单地说,这是故意发生的;作者将其作为初始化的一部分。

看起来可以在图像的入口点 shell 脚本中找到一些答案:

_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 "$@"
}

至于“为什么?”我认为这是因为希望以较低权限的用户身份运行。

您可以通过在 Compose 文件中指定一个卷来“解决”问题,如下所示:

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

然后,它将跳过例程以确保DATABASE_ALREADY_EXISTS

或者,如果这没有帮助 - 您可以深入研究入口点脚本。

答案 1 :(得分:2)

感谢@TorEHagermann (https://stackoverflow.com/a/65417566/5631863) 的上述提示,我能够解决问题。

解决方案包括以下内容:

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

此外,就我而言,每次启动容器时都需要清除和刷新数据。因此,我在 shell 脚本中包含以下内容以删除驱动器 /data/pgsql

rm -rf data

有了这个改变,我的 docker-compose 文件看起来像: 版本:'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