首页 > 解决方案 > 如何将容器上的端口公开给本地主机并将持久数据绑定到容器?

问题描述

我正在使用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这个特定设置中需要什么。最终,我不需要将数据库暴露给本地机器,但现在,我需要能够用于测试目的。提前致谢!

更新 1 - 2019 年 6 月 15 日

我按照建议使用类似的设置重新测试了它,这与我已经在做的并没有什么不同。然而,这些建议帮助我走上了正确的道路,并了解了我的错误在哪里。

似乎问题正在发生,因为我试图重用本地主机上已用于不同数据库设置的目录。我认为这是支持的;我猜我错过了什么?

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

澄清

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

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

更新 2 - 2019 年 6 月 15 日

我的代码生成的路径似乎有问题。在我经历了一点之后,似乎我只是忽略了这个错误。奇怪的是,当我检查日志时,我没有在容器中发现任何错误——这就是为什么我认为路径没有任何问题。

因此,对于遇到这种情况的人来说,需要修复您在主机上引用的路径可能是一件简单的事情。

话虽如此,我已经标记了 mchawre 接受的解决方案 - 他的解决方案对于我提出的原始问题是正确的。我遇到的其他问题似乎是由于错误造成的。

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

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

警告:Docker 特定变量只有在使用空数据目录启动容器时才会生效;任何预先存在的数据库都将在容器启动时保持不变。

标签: node.jsdocker

解决方案


我从头到尾都试过了,一切正常。请参考以下步骤:

  1. 首先我安装dockerode在我的机器上npm install dockerode
  2. 弄清楚我的machine ip以及port暴露在哪个 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
$

请从你的最后尝试这个,让我知道。


推荐阅读