簡體   English   中英

flyway 無法連接到 docker-entrypoint-initdb.d 腳本中的 postgres 容器

[英]flyway unable to connect to postgres container within docker-entrypoint-initdb.d script

我正在嘗試將postgres Docker映像擴展為可能(通過環境變量標志)在 DB init 上執行 flyway DB 遷移。 我的 Dockerfile 在這里:

FROM postgres:9.6

# Install curl and java (for Flyway)
RUN set -x \
    && apt-get update \
    && apt-get install -y --no-install-recommends ca-certificates curl openjdk-8-jre 

# Install Flyway
ENV FLYWAY_VERSION 4.2.0
ENV FLYWAY_INSTALL_DIR /usr/src/flyway
ENV FLYWAY_CONF ${FLYWAY_INSTALL_DIR}/flyway-${FLYWAY_VERSION}/conf/flyway.conf
ENV FLYWAY_EXE ${FLYWAY_INSTALL_DIR}/flyway-${FLYWAY_VERSION}/flyway
RUN mkdir -p ${FLYWAY_INSTALL_DIR} && \
    curl -L https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/${FLYWAY_VERSION}/flyway-commandline-${FLYWAY_VERSION}.tar.gz | \
    tar -xzC ${FLYWAY_INSTALL_DIR} && \
    chmod +x ${FLYWAY_EXE}

# Copy migration scripts
ENV MIGRATIONS_LOCATION /flyway/migrations
COPY migrations $MIGRATIONS_LOCATION

COPY init_db.sh /docker-entrypoint-initdb.d/init_db.sh

使用我的init_db.sh啟動腳本:

#!/bin/bash
set -e

RUN_MIGRATIONS="${RUN_MIGRATIONS:-false}"
DB_URL="jdbc:postgresql://localhost:5432/$DB_NAME"

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
    CREATE DATABASE $DB_NAME;
EOSQL

if [ "$RUN_MIGRATIONS" == "true" ]; then
        echo "running migrations ..."
        ${FLYWAY_EXE} -user=$POSTGRES_USER -password=$POSTGRES_PASSWORD -url=$DB_URL -locations="filesystem:$MIGRATIONS_LOCATION" migrate
fi

但是,當使用RUN_MIGRATIONS=true運行容器時, RUN_MIGRATIONS=true無法連接到 postgres:

docker build . -t postgres-flyway && docker run -e DB_NAME=db -e RUN_MIGRATIONS=true -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres postgres-flyway
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
running bootstrap script ... ok
performing post-bootstrap initialization ... 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:

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

waiting for server to start....LOG:  database system was shut down at 2018-08-06 02:19:32 UTC
LOG:  MultiXact member wraparound protections are now enabled
LOG:  autovacuum launcher started
LOG:  database system is ready to accept connections
 done
server started
ALTER ROLE


/usr/local/bin/docker-entrypoint.sh: sourcing /docker-entrypoint-initdb.d/init_db.sh
CREATE DATABASE
running migrations ...
Flyway 4.2.0 by Boxfuse

ERROR:
Unable to obtain Jdbc connection from DataSource (jdbc:postgresql://localhost:5432/db) for user 'postgres': Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL State  : 08001
Error Code : 0
Message    : Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

postgres 映像在端口 5432 上運行 postgres(像往常一樣),所以我不知道為什么 flyway 無法通過localhost:5432連接到 postgres。

我還注意到,在這種情況下, pg_isready指出 postgres 正在接受連接,但是當將主機名指定為localhost127.0.0.1它也無法訪問 postgres。 也就是說,通過在我的init_db.sh腳本中插入一些pg_isready命令:

...
pg_isready
pg_isready -p 5432
pg_isready -h localhost -p 5432
...

我在 postgres init 上看到以下日志輸出:

...
/var/run/postgresql:5432 - accepting connections
/var/run/postgresql:5432 - accepting connections
localhost:5432 - no response
...

我懷疑我已經達到了 postgres 初始化上下文的限制,但我想了解為什么在初始化時無法通過localhost/127.0.0.1:5432訪問 postgres。

在基於 postgres:10.5 圖像為我的數據庫創建 docker 圖像時,我在運行 flyway 時遇到了同樣的問題。 在運行 flyway 之前,我將以下內容添加到我的 entrypoint.sh 中,以確認我看到的問題是由 @Nick Maraston 在他的回答中發布的 docker-entrypoint.sh 更改引起的:

echo "$(date) - waiting for database to start"
while ! pg_isready -h localhost -p 5432 -d $POSTGRES_DB
do
    echo "$(date) - waiting for database to start"
    sleep 10
done

結果是上面的代碼永遠循環。 然后,我將其替換為以下代碼,以重新啟動在 localhost 上偵聽 TCP/IP 連接的數據庫:

pg_ctl -D "$PGDATA" -m fast -w stop
pg_ctl -D "$PGDATA" \
            -o "-c listen_addresses='localhost'" \
            -w start

與其像這樣重新啟動數據庫,更-socketFactory解決方案是使用此處解釋的 JDBC -socketFactory選項。

我在挖掘圖像入口點腳本時發現了這個問題。 最近對圖像的更改將 postgres 限制為僅在內部初始化期間通過 unix 域套接字偵聽連接: https : //github.com/docker-library/postgres/pull/440

確實,postgres docker 正在偵聽 unix 套接字,例如。 /var/run/postgresql/.s.PGSQL.5432 但是沒有必要強制服務器切換它的監聽地址。 Postgres 數據庫 URI 允許連接字符串指向 unix 套接字。

參考: 使用 SQLAlchemy 通過 unix 套接字連接到數據庫

該示例提供:

export DATABASE_URL=postgres://user:password@/dbname?host=/path/to/unix/socket

我能夠省略主機,並決定在我的/docker-entrypoint-initdb.d/*.sh腳本中使用這個環境變量。 請注意,@ 符號后面沒有字符串,此處也沒有主機查詢字符串。 您可能需要根據您的應用程序明確定義主機。

解決方案:

export DATABASE_URL="postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@/$POSTGRES_DB"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM