将 liquibase 集成到自定义 postgres 容器映像中
Integrating liquibase into a custom postgres container image
我正在尝试基于官方 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.lambda$run[=11=](Main.java:361)
at liquibase.Scope.lambda$child[=11=](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.run(Main.java:360)
at liquibase.integration.commandline.Main.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
我做错了什么?此时数据库还没有准备好接收连接吗?只有在容器 运行ning 之后,我才需要 运行 liquibase 吗?如果是这样,是否有针对此类流程的最佳实践指南?
在 Docker 文件中,您永远无法连接到数据库。如果您正在尝试扩展数据库映像,则数据库在 docker build
序列期间永远不会 运行ning;如果数据库位于单独的容器中,则调用数据库的网络设置的 none 已经完成。标准 Docker Hub 数据库图像的配置方式也会阻止创建带有预加载数据的图像。
对于像 Liquibase 这样的迁移工具,它们通常与应用程序而不是数据库打包在一起。如果您的应用程序是使用 Spring Boot 构建的,例如,它支持 Execute Liquibase Database Migrations on Startup.
如果您需要使用 Docker 机制 运行 迁移,一种模式是在您的容器启动时使用入口点包装器脚本来执行此操作。如您在此处所示,您的应用程序图像需要包含 Liquibase。有脚本 运行 liquibase
命令,然后 exec "$@"
到 运行 主容器应用程序; COPY
将其放入您的图像中并使其成为 ENTRYPOINT
(必须使用 JSON-array 语法),并保持 CMD java -jar ...
不变。 (您可能会使用 Python 的 Django 框架查找类似示例。)
我正在尝试基于官方 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.lambda$run[=11=](Main.java:361)
at liquibase.Scope.lambda$child[=11=](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.run(Main.java:360)
at liquibase.integration.commandline.Main.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
我做错了什么?此时数据库还没有准备好接收连接吗?只有在容器 运行ning 之后,我才需要 运行 liquibase 吗?如果是这样,是否有针对此类流程的最佳实践指南?
在 Docker 文件中,您永远无法连接到数据库。如果您正在尝试扩展数据库映像,则数据库在 docker build
序列期间永远不会 运行ning;如果数据库位于单独的容器中,则调用数据库的网络设置的 none 已经完成。标准 Docker Hub 数据库图像的配置方式也会阻止创建带有预加载数据的图像。
对于像 Liquibase 这样的迁移工具,它们通常与应用程序而不是数据库打包在一起。如果您的应用程序是使用 Spring Boot 构建的,例如,它支持 Execute Liquibase Database Migrations on Startup.
如果您需要使用 Docker 机制 运行 迁移,一种模式是在您的容器启动时使用入口点包装器脚本来执行此操作。如您在此处所示,您的应用程序图像需要包含 Liquibase。有脚本 运行 liquibase
命令,然后 exec "$@"
到 运行 主容器应用程序; COPY
将其放入您的图像中并使其成为 ENTRYPOINT
(必须使用 JSON-array 语法),并保持 CMD java -jar ...
不变。 (您可能会使用 Python 的 Django 框架查找类似示例。)