【问题标题】:Integrating liquibase into a custom postgres container image将 liquibase 集成到自定义 postgres 容器映像中
【发布时间】:2020-12-15 19:30:52
【问题描述】:

我正在尝试基于官方 postgres 图像 + 我的数据库模式创建一个容器图像,该模式当前定义为 liquibase XML。

这就是我的 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 吗?如果有,是否有此类流程的最佳实践指南?

【问题讨论】:

    标签: postgresql docker liquibase


    【解决方案1】:

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

    对于像 Liquibase 这样的迁移工具,它们通常与应用程序一起打包,而不是与数据库一起打包。例如,如果您的应用程序是使用 Spring Boot 构建的,则它支持Execute Liquibase Database Migrations on Startup

    如果您需要使用 Docker 机制运行迁移,一种模式是在容器启动时使用入口点包装脚本来执行此操作。您的应用程序映像需要包含 Liquibase,如此处所示。让脚本运行liquibase 命令,然后exec "$@" 运行主容器应用程序; COPY 将其添加到您的图像中并使其成为 ENTRYPOINT(必须使用 JSON 数组语法),并保留 CMD java -jar ... 原样。 (您可能会使用 Python 的 Django 框架寻找类似的示例。)

    【讨论】:

    • 感谢大卫的详细解答!!我最终通过 liquibase 创建了一个 sql 转储文件,然后将其放在 PG 映像中的预定义目录中,PG 在第一个容器启动时自动执行脚本。
    猜你喜欢
    • 2021-09-22
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    相关资源
    最近更新 更多