如何既将容器上的端口公开给本地主机,又将持久性数据绑定到容器上?

时间:2019-06-15 07:49:38

标签: node.js docker

我正在使用dockerode创建一个新的PostgreSQL Docker容器。我希望能够:

  1. 在本地主机上暴露端口5432
  2. 让容器使用本地主机上的目录作为持久数据存储

我已经能够使用以下代码获得一个可行的实现,该实现创建一个Docker容器并在本地主机上公开端口5432

docker.createContainer({
      Image: "postgres",
      Env: [`POSTGRES_PASSWORD=postgres`],
      HostConfig: {
        PortBindings: {
          "5432/tcp": [{ HostPort: "5432" }]
        },
      },
      ExposedPorts: {
        "5432/tcp": {}
      },
      name: "container-name"
})
  • 在此实现中,数据不是持久性的-重新启动容器将始终从“新”数据库开始
    • 我需要持久数据

通过阅读Docker REST API文档(以及阅读大量社区帖子),我发现我需要使用Binds参数。我将代码更新为以下内容:

docker.createContainer({
      Image: "postgres",
      Env: [`POSTGRES_PASSWORD=postgres`],
      HostConfig: {
        PortBindings: {
          "5432/tcp": [{ HostPort: "5432" }]
        },
        // NEW CODE
        Binds: [
          "/path/on/host/machine:/path/on/container"
        ],
      },
      ExposedPorts: {
        "5432/tcp": {}
      },
      name: "container-name"
})
  • 但是,添加了Binds参数后, 我不再能够从主机连接到数据库

有人可以告诉我我在做什么错吗?我无法弄清楚在此特定设置中需要Binds是什么。最终,我不需要将数据库公开给本地计算机,但就目前而言,我需要能够进行测试。预先感谢!

更新1-6/15/2019

我使用与建议的类似的设置对它进行了重新测试,这实际上与我已经做的没什么不同。但是,这些建议帮助我走上了正确的道路,并了解了我的错误所在。

似乎发生了问题,因为我试图重用本地主机上已经用于其他数据库设置的目录。我以为这得到了支持;我猜有什么我想念的吗?

无论哪种情况,我现在都可以使用,但是我不明白为什么我不能在从命令行启动容器时重用主机上使用的同一目录。

澄清

我没有提到我可以通过从命令行启动容器来使它正常工作。问题是尝试使用dockerode时-但是,我认为这不是Dockerode的问题,而是我对Docker REST API的一些误解。

可以对所有数据库使用相同的目录如果,我是从命令行启动容器的,但如果我是使用Docker REST启动容器的,则不能API(在我的情况下为dockerode

更新2-6/15/2019

我的代码生成的路径似乎出了点问题。经过一段时间后,看来我只是忽略了该错误。奇怪的是,当我检查日志时,我在容器中没有任何错误-这就是为什么我认为路径没有任何问题的原因。

因此,对于那些遇到此问题的人来说,可能需要修复您在主机上引用的路径很简单。

话虽如此,我已经用mchawre标记了可接受的解决方案-他的解决方案对我提出的原始问题是正确的。看来,我剩下的其他问题都是由于错误引起的。

(我确实希望Docker日志在启动时会为容器说类似“没有这样的目录”之类的东西-这样会导致更快速的解决方案)

相关信息 我在这里找到了以下信息:

  

警告:仅当您使用空的数据目录启动容器时,特定于Docker的变量才有效。容器启动时,所有现有数据库都将保持不变。

  • 我认为这就是我遇到此问题的原因,但还不能100%确定

1 个答案:

答案 0 :(得分:3)

我从头开始尝试了此操作,一切正常。请参考以下步骤:

  1. 首先我在机器dockerode上安装了npm install dockerode
  2. 找出我的machine ipport,其中暴露了docker守护程序。
  3. 已创建的run.js文件,其中包含用于运行带有外部卷的postgres容器的代码。
var Docker = require('dockerode');
var dockerHostIP = "192.168.0.33"
var dockerHostPort = 2375

var docker = new Docker({ host: dockerHostIP, port: dockerHostPort });

docker.createContainer({
Image: "postgres",
Env: [`POSTGRES_PASSWORD=postgres`],
HostConfig: {
PortBindings: {
  "5432/tcp": [{ HostPort: "5432" }]
  },
  // NEW CODE
  Binds: [
    "/root/dir:/tmp"
    ],
    },
    ExposedPorts: {
    "5432/tcp": {}
    },
    name: "container-name"
}).then(function(container) {
  return container.start();
})

注意:/root/dir是主机上的目录,/tmp是容器中的主机。

  1. 运行js文件node run.js
  2. Postgres似乎正在运行,并且可以从我的主机连接到它
$ psql postgresql://postgres:postgres@localhost:5432/postgres
psql (11.3)
Type "help" for help.

postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(3 rows)

postgres=#
  1. 还检查了主机上/root/dir目录的内容,以查看其是否正确安装。
$ ls /root/dir/
test.txt
$

请尽力尝试一下,让我知道。