在postgres Docker容器内连接到postgres

k2fxgqgv  于 2023-02-07  发布在  Docker
关注(0)|答案(1)|浏览(228)

我正在尝试为postgres设置一个自定义的Dockerfile,在启动时运行flyway迁移。到目前为止,我已经成功地构建、安装和执行了所有内容,但是由于连接错误,我无法让flyway在启动时连接到docker容器内的postgres数据库。
在你告诉我在一个docker-compose,文件中设置它之前,我想补充的是,我这样做是为了我可以使用gitlab ci/cd中的docker映像作为一个服务容器,所以使用docker-compose不是一个选项。
这是我的文档

FROM postgres:12 AS db

WORKDIR /home

# Install wget
RUN apt-get update -y \
  && apt-get install wget -y \
  && apt-get install sudo -y \
  && apt-get install lsof

RUN usermod -aG sudo postgres
RUN bash -c 'echo "postgres ALL=(ALL:ALL) NOPASSWD: ALL" | (EDITOR="tee -a" visudo)'

# Install latest version of flyway 7
RUN wget -qO- https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/7.9.2/flyway-commandline-7.9.2-linux-x64.tar.gz | tar xvz && \
  ln -s `pwd`/flyway-7.9.2/flyway /usr/local/bin

# Copy database migrations for flyway
COPY reds/migrations migrations

# Set environment variables for flyway
ENV FLYWAY_LOCATIONS="/home/migrations"
ENV FLYWAY_SCHEMAS="reds"
ENV FLYWAY_CONNECT_RETRIES=5
ENV FLYWAY_BASELINE_ON_MIGRATE=false
ENV FLYWAY_OUT_OF_ORDER=false

# Make postgres startup script run flyway migrations
COPY reds/init.sh /docker-entrypoint-initdb.d/init.sh
RUN chmod +x /docker-entrypoint-initdb.d/init.sh && \
  chown -R postgres /docker-entrypoint-initdb.d

EXPOSE 5432
CMD ["postgres"]

下面是在container启动时执行的脚本

#!/bin/bash
set -eou pipefail

# I've tried localhost, 0.0.0.0 and 127.0.0.1
host="$(hostname -i)"

sudo flyway migrate \
  -url="jdbc:postgresql://$host:5432/$POSTGRES_DB" \
  -schemas="$FLYWAY_SCHEMAS" \
  -locations="$FLYWAY_LOCATIONS" \
  -connectRetries="$FLYWAY_CONNECT_RETRIES" \
  -baselineOnMigrate="$FLYWAY_BASELINE_ON_MIGRATE" \
  -outOfOrder="$FLYWAY_OUT_OF_ORDER" \
  -user="$POSTGRES_USER" \
  -password="$POSTGRES_PASSWORD"

我的生成命令:

$ docker build -t reds-docker:latest -f "Dockerfile.reds" .

我的运行命令:

$ docker run --rm \
  --env POSTGRES_USER="postgres" \
  --env POSTGRES_PASSWORD="postgres" \
  --env POSTGRES_DB="postgres" \
  reds-docker:latest

当我运行container时,flyway尝试连接到数据库时,我得到了以下错误:

  • 警告:连接错误:与172.17.0.2:5432的连接被拒绝。请检查主机名和端口是否正确以及邮局主管是否接受TCP/IP连接。(由连接被拒绝引起(连接被拒绝))*

启动后的完整日志:

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 dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

Success. You can now start the database server using:

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

initdb: 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.
waiting for server to start....2023-02-06 13:36:59.228 UTC [48] LOG:  starting PostgreSQL 12.13 (Debian 12.13-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
2023-02-06 13:36:59.229 UTC [48] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-02-06 13:36:59.237 UTC [49] LOG:  database system was shut down at 2023-02-06 13:36:59 UTC
2023-02-06 13:36:59.239 UTC [48] LOG:  database system is ready to accept connections
 done
server started

/usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.sh
WARNING: This version of Flyway is out of date. Upgrade to Flyway 9.14.1:https://flywaydb.org/documentation/learnmore/staying-up-to-date/?ref=v7.9.2_cmd-line
Flyway Community Edition 7.9.2 by Redgate
WARNING: Connection error: Connection to 172.17.0.2:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections. (Caused by Connection refused (Connection refused)) Retrying in 1 sec...
WARNING: Connection error: Connection to 172.17.0.2:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections. (Caused by Connection refused (Connection refused)) Retrying in 2 sec...
s3fp2yjn

s3fp2yjn1#

需要说明的是,docker-entrypoint-initdb.d中的脚本并不像您所说的那样在容器启动时运行,而是在数据库初始化时运行,因此它们只在初始化新数据库时运行,因此对于通常更改现有数据库的迁移来说并不适用。
话虽如此,您的脚本不工作的原因是,当数据库正在初始化时,Postgres正在不接受TCP/IP连接的状态下运行。您只能使用Unix套接字与它对话。您可以在消息listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"中的日志中看到这一点。
我不知道Flyway是否支持通过Unix套接字连接,但是在数据库初始化脚本中不能通过TCP/IP连接。
启动数据库的代码是container startup script的以下部分:

# start socket-only postgresql server for setting up or running scripts
# all arguments will be passed along as arguments to `postgres` (via pg_ctl)
docker_temp_server_start() {
    if [ "$1" = 'postgres' ]; then
        shift
    fi

    # internal start of server in order to allow setup using psql client
    # does not listen on external TCP/IP and waits until start finishes
    set -- "$@" -c listen_addresses='' -p "${PGPORT:-5432}"

    PGUSER="${PGUSER:-$POSTGRES_USER}" \
    pg_ctl -D "$PGDATA" \
        -o "$(printf '%q ' "$@")" \
        -w start
}

正如你所看到的,它将listen_addresses设置为一个空字符串,这导致Postgres不监听任何TCP/IP端口。如果不使用修改后的启动脚本创建自己的映像,似乎没有办法修改这种行为。

相关问题