简体   繁体   English

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

[英]Integrating liquibase into a custom postgres container image

I am trying to create a container image based on the official postgres image + my DB schema currently defined as liquibase XMLs.我正在尝试基于官方 postgres 图像 + 我的数据库模式创建一个容器图像,该模式当前定义为 liquibase XML。

This is how my Dockerfile looks:这就是我的 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

The build fails with:构建失败:

[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

What am I doing wrong?我究竟做错了什么? Is the database not yet ready to receive connections at this point?此时数据库还没有准备好接收连接吗? Will I have to run liquibase only after the container is running?只有在容器运行后我才需要运行 liquibase 吗? If so, is there a best practices guide for such a flow?如果是这样,是否有此类流程的最佳实践指南?

Inside a Dockerfile, you can never connect to a database.在 Dockerfile 中,您永远无法连接到数据库。 If you're trying to extend a database image, the database is never running during the docker build sequence;如果您尝试扩展数据库映像,则数据库在docker build序列期间永远不会运行; if the database is in a separate container, none of the networking setup for the build to call the database has been done.如果数据库位于单独的容器中,则构建调用数据库的网络设置尚未完成。 The standard Docker Hub database images are also configured in a way that prevents creating an image with data preloaded.标准 Docker Hub 数据库映像的配置方式也可以防止创建预加载数据的映像。

For migration tools like Liquibase, they're typically packaged with the application, not the database.对于像 Liquibase 这样的迁移工具,它们通常与应用程序一起打包,而不是与数据库一起打包。 If your application is built using Spring Boot, for example, it has support to Execute Liquibase Database Migrations on Startup .例如,如果您的应用程序是使用 Spring Boot 构建的,则它支持在启动时执行 Liquibase 数据库迁移

If you need to run migrations using Docker mechanics, one pattern is to use an entrypoint wrapper script to do it when your container starts up.如果您需要使用 Docker 机制运行迁移,一种模式是在容器启动时使用入口点包装脚本来执行此操作。 Your application image needs to include Liquibase as you've shown here.您的应用程序映像需要包含 Liquibase,如此处所示。 Have the script run the liquibase command, then exec "$@" to run the main container application;让脚本运行liquibase命令,然后exec "$@"运行主容器应用程序; COPY it into your image and make it be the ENTRYPOINT (must use JSON-array syntax), and leave CMD java -jar... as is.将其COPY到您的图像中并使其成为ENTRYPOINT (必须使用 JSON 数组语法),并保留CMD java -jar...原样。 (You might look for similar examples using Python's Django framework.) (您可能会使用 Python 的 Django 框架寻找类似的示例。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM