Postgresql 将liquibase集成到自定义postgres容器映像中

Postgresql 将liquibase集成到自定义postgres容器映像中,postgresql,docker,liquibase,Postgresql,Docker,Liquibase,我正在尝试创建一个基于官方postgres图像+我的DB模式(当前定义为liquibase XMLs)的容器图像 以下是我的Dockerfile的外观: FROM postgres:13.1 ENV POSTGRES_USER=myuser ENV POSTGRES_PASSWORD=mypass ENV POSTGRES_DB=mydb # Copy the DB and user creation script which will then be automatically ex

我正在尝试创建一个基于官方postgres图像+我的DB模式(当前定义为liquibase XMLs)的容器图像

以下是我的Dockerfile的外观:

FROM postgres:13.1


ENV POSTGRES_USER=myuser
ENV POSTGRES_PASSWORD=mypass
ENV POSTGRES_DB=mydb



# Copy the DB and user creation script which will then be automatically executed during the DB creation
ADD ./db_init.sql /docker-entrypoint-initdb.d/

# Temporary copy liquibase
ADD ./liquibase/ /liquibase/

# Copy and extract OpenJDK for liquibase 
ADD ./openjdk-11+28_linux-x64_bin.tar.gz /liquibase/

ENV JAVA_HOME=/liquibase/jdk-11


# Copy the changelog for the creation of the schema
ADD ./changelog/liquibase/ /liquibase/

# Execute liquibase
RUN /liquibase/liquibase --changeLogFile=/changelog/liquibase/index.xml --url=jdbc:postgresql://localhost:5432/$POSTGRES_DB --username=$POSTGRES_USER --password=$POSTGRES_PASSWORD --logLevel=info update


RUN rm -rf /liquibase

USER postgres
生成失败,原因是:

[2020-12-15 10:37:23] SEVERE [liquibase.integration] Unexpected error running Liquibase: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql://localhost:5432/sisdb with driver org.postgresql.Driver.  Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql://localhost:5432/sisdb with driver org.postgresql.Driver.  Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:131)
    at liquibase.integration.commandline.Main.doMigration(Main.java:1409)
    at liquibase.integration.commandline.Main$1.lambda$run$0(Main.java:361)
    at liquibase.Scope.lambda$child$0(Scope.java:160)
    at liquibase.Scope.child(Scope.java:169)
    at liquibase.Scope.child(Scope.java:159)
    at liquibase.Scope.child(Scope.java:138)
    at liquibase.Scope.child(Scope.java:222)
    at liquibase.Scope.child(Scope.java:226)
    at liquibase.integration.commandline.Main$1.run(Main.java:360)
    at liquibase.integration.commandline.Main$1.run(Main.java:193)
    at liquibase.Scope.child(Scope.java:169)
    at liquibase.Scope.child(Scope.java:145)
    at liquibase.integration.commandline.Main.run(Main.java:193)
    at liquibase.integration.commandline.Main.main(Main.java:156)
Caused by: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql://localhost:5432/sisdb with driver org.postgresql.Driver.  Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at liquibase.database.DatabaseFactory.openConnection(DatabaseFactory.java:216)
    at liquibase.database.DatabaseFactory.openConnection(DatabaseFactory.java:175)
    at liquibase.database.DatabaseFactory.openDatabase(DatabaseFactory.java:140)
    at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:96)
    ... 14 more
Caused by: liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql://localhost:5432/sisdb with driver org.postgresql.Driver.  Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at liquibase.database.ConnectionServiceFactory.create(ConnectionServiceFactory.java:36)
    at liquibase.database.DatabaseFactory.openConnection(DatabaseFactory.java:213)
    ... 17 more
Caused by: liquibase.exception.DatabaseException: Connection could not be created to jdbc:postgresql://localhost:5432/sisdb with driver org.postgresql.Driver.  Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at liquibase.database.jvm.JdbcConnection.open(JdbcConnection.java:43)
    at com.datical.liquibase.ext.database.jvm.ProJdbcConnection.open(Unknown Source)
    at liquibase.database.ConnectionServiceFactory.create(ConnectionServiceFactory.java:33)
    ... 18 more

我做错了什么?此时数据库是否尚未准备好接收连接?只有在容器运行后,我才能运行liquibase吗?如果是这样的话,有这样一个流程的最佳实践指南吗?

在Dockerfile中,您永远不能连接到数据库。如果您试图扩展数据库映像,则在
docker build
序列期间,数据库永远不会运行;如果数据库位于单独的容器中,则构建调用数据库的网络设置尚未完成。标准Docker Hub数据库映像的配置方式也可以防止创建带有预加载数据的映像

对于像Liquibase这样的迁移工具,它们通常与应用程序一起打包,而不是与数据库一起打包。例如,如果您的应用程序是使用SpringBoot构建的,那么它支持


如果需要使用Docker机制运行迁移,一种模式是在容器启动时使用entrypoint包装器脚本。您的应用程序映像需要包括Liquibase,如您在此处所示。让脚本运行
liquibase
命令,然后
exec“$@”
运行主容器应用程序
将其复制到图像中,并使其成为
入口点(必须使用JSON数组语法),并保持
CMD java-jar…
不变。(您可以使用Python的Django框架查找类似的示例。)

感谢您提供的详细答案,David!!我最终通过liquibase创建了一个sql转储文件,然后将其放置在PG映像中的预定义目录中,PG在第一个容器启动时自动从该目录执行脚本。