通过 Docker 的 Liquibase - 更新日志未写入磁盘

Liquibase via Docker - Changelog is not written to disk

我想在本地(而不是在容器中)为 PostgreSQL 数据库 运行 设置 Liquibase(使用 Docker)。我遵循了多个教程,包括 Docker Hub.

上的教程

按照建议,我在 <PATH TO CHANGELOG DIR>

中创建了一个 liquibase.docker.properties 文件
classpath: /liquibase/changelog
url: jdbc:postgresql://localhost:5432/mydb?currentSchema=public
changeLogFile: changelog.xml
username: myuser
password: mypass

能够运行docker run --rm --net="host" -v <PATH TO CHANGELOG DIR>:/liquibase/changelog liquibase/liquibase --defaultsFile=/liquibase/changelog/liquibase.docker.properties <COMMAND>.

当我 运行 [...] generateChangeLog 我得到以下输出(带有选项 --logLevel info):

[2021-04-27 06:08:20] INFO [liquibase.integration] No Liquibase Pro license key supplied. Please set liquibaseProLicenseKey on command line or in liquibase.properties to use Liquibase Pro features.
Liquibase Community 4.3.3 by Datical
####################################################
##   _     _             _ _                      ##
##  | |   (_)           (_) |                     ##
##  | |    _  __ _ _   _ _| |__   __ _ ___  ___   ##
##  | |   | |/ _` | | | | | '_ \ / _` / __|/ _ \  ##
##  | |___| | (_| | |_| | | |_) | (_| \__ \  __/  ##
##  \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___|  ##
##              | |                               ##
##              |_|                               ##
##                                                ## 
##  Get documentation at docs.liquibase.com       ##
##  Get certified courses at learn.liquibase.com  ## 
##  Free schema change activity reports at        ##
##      https://hub.liquibase.com                 ##
##                                                ##
####################################################
Starting Liquibase at 06:08:20 (version 4.3.3 #52 built at 2021-04-12 17:08+0000)
BEST PRACTICE: The changelog generated by diffChangeLog/generateChangeLog should be inspected for correctness and completeness before being deployed.
[2021-04-27 06:08:22] INFO [liquibase.diff] changeSets count: 1
[2021-04-27 06:08:22] INFO [liquibase.diff] changelog.xml does not exist, creating and adding 1 changesets.
Liquibase command 'generateChangeLog' was executed successfully.

它看起来像命令 运行“成功”,但是 我在我挂载的本地目录 中找不到文件 changelog.xml,即 <PATH TO CHANGELOG DIR>。但是安装必须正常工作,因为它成功连接到数据库,即容器能够访问和读取 liquibase.docker.properties.

首先我想我可能不得不“说”Docker允许它写入我的磁盘但似乎应该支持[根据Docker集线器上的描述] :

The /liquibase/changelog volume can also be used for commands that write output, such as generateChangeLog

我错过了什么?在此先感谢您的帮助!


附加信息

docker inspect 的输出:

"Mounts": [
    {
        "Type": "bind",
        "Source": "<PATH TO CHANGELOG DIR>",
        "Destination": "/liquibase/changelog",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    },
    ...
],

TL;DR

在变更日志文件名前加上/liquibase/changelog/前缀并将其作为命令行参数传递:

[...] --changeLogFile /liquibase/changelog/changelog.xml generateChangelog

有关详细信息,请参阅

说明

我用 -it 启动了容器并覆盖了入口点以在容器内获得交互式 shell(参见 this post):

docker run --net="host" -v <PATH TO CHANGELOG DIR>:/liquibase/changelog -it --entrypoint /bin/bash liquibase/liquibase -s

执行 ls 产生以下结果:

liquibase@ubuntu-rafael:/liquibase$ ls
ABOUT.txt            UNINSTALL.txt  docker-entrypoint.sh  liquibase
GETTING_STARTED.txt  changelog      examples              liquibase.bat
LICENSE.txt          changelog.txt  lib                   liquibase.docker.properties
README.txt           classpath      licenses              liquibase.jar

这里值得注意的是 docker-entrypoint.sh,它实际执行了 liquibase 命令,文件夹 changelog 挂载到我的本地 <PATH TO CHANGELOG DIR>(我的 .properties 文件在那里).

现在我 运行 使用与以前相同的命令,但现在 容器内:

sh docker-entrypoint.sh --defaultsFile=/liquibase/changelog/liquibase.docker.properties --logLevel info generateChangeLog

我得到了与上面相同的输出,但猜猜当 运行 ls 再次出现时会显示什么:

ABOUT.txt            changelog             examples       liquibase.docker.properties
GETTING_STARTED.txt  changelog.txt         lib            liquibase.jar
LICENSE.txt          changelog.xml         ...

更新日志确实存在!但是它是在错误的目录中创建的...

如果您在变更日志文件名前加上 /liquibase/changelog/,容器能够将其写入您的本地(已安装)磁盘。

P.S。这意味着使用 here is not working. I will open an Issue 中的“属性文件”对“完整示例”的描述。

更新

只有写入新文件的命令才需要指定绝对路径,例如generateChangeLog(参见 )。但更好的做法是通过命令行传递绝对路径,以便您可以将设置保留在默认文件中。

当您 运行 generateChangeLog 时,文件路径应指定为 /liquibase/changelog/changelog.xml,即使 update 需要指定为 changelog.xml

示例:

docker run --rm --net="host" -v <PATH TO CHANGELOG DIR>:/liquibase/changelog liquibase/liquibase --defaultsFile=/liquibase/changelog/liquibase.docker.properties --changeLogFile=/liquibase/changelog/changelog.xml generateChangeLog

对于 generateChangeLog,changeLogFile 参数是要输出的文件的特定路径,相对于更新和其他命令使用的 classpath 设置的路径。

当您像上面那样包含命令行参数和 defaultsFile 时,命令行参数会胜出。这让您可以利用相同的默认设置,同时在特定命令需要 more/different 时替换特定设置。

详情

创建文件的操作和读取现有文件的操作之间存在区别。

使用 Liquibase,您几乎总是希望使用与类路径中的目录相关的文件路径,就像示例中那样。指定的 changelogFile 存储在跟踪系统中,因此如果您 运行 相同的 changelog 但以不同的方式引用(因为您移动了根目录或 运行 从不同的机器)然后 Liquibase会将其视为一个新文件并尝试重新 运行 已经 运行 变更集。

这就是文档具有 classpath: /liquibase/changelogchangeLogFile: com/example/changelog.xml 的原因。 update 操作在 /liquibase/changelog 目录中查找名为 com/example/changelog.xml 的文件并找到它并将路径存储为 com/example/changelog.xml.

GenerateChangeLog 是“并不总是相对于类路径”的情况之一,因为它需要知道将文件存储在何处。如果您只是将输出 changeLogFile 指定为 changelog.xml,它只会创建相对于您进程的工作目录的文件,这不是您 needing/expecting.