node.js - 如何将容器上的端口公开给本地主机并将持久数据绑定到容器?
问题描述
我正在使用dockerode
创建一个新的 PostgreSQL docker 容器。我希望能够:
5432
在本地主机上公开端口- 让容器使用本地主机上的目录作为持久数据存储
我已经能够获得一个工作实现,它创建一个 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 - 2019 年 6 月 15 日
我按照建议使用类似的设置重新测试了它,这与我已经在做的并没有什么不同。然而,这些建议帮助我走上了正确的道路,并了解了我的错误在哪里。
似乎问题正在发生,因为我试图重用本地主机上已用于不同数据库设置的目录。我认为这是支持的;我猜我错过了什么?
无论哪种情况,我现在都有这个工作,但我不太明白为什么我不能在我的主机上重用我从命令行启动容器时使用的同一个目录。
澄清
我没有提到我可以通过从命令行启动容器来完成这项工作。问题在于尝试使用时dockerode
- 但是,我认为这不是 Dockerode 的问题,而是我对 Docker REST API 有一些误解。
如果我从命令行启动容器,我可以对所有数据库使用相同的目录,但如果我使用 Docker REST API(在我的情况下)启动容器,则不能。dockerode
更新 2 - 2019 年 6 月 15 日
我的代码生成的路径似乎有问题。在我经历了一点之后,似乎我只是忽略了这个错误。奇怪的是,当我检查日志时,我没有在容器中发现任何错误——这就是为什么我认为路径没有任何问题。
因此,对于遇到这种情况的人来说,需要修复您在主机上引用的路径可能是一件简单的事情。
话虽如此,我已经标记了 mchawre 接受的解决方案 - 他的解决方案对于我提出的原始问题是正确的。我遇到的其他问题似乎是由于错误造成的。
(不过,我确实希望 Docker 日志在容器启动时对容器说“没有这样的目录”之类的东西 - 这会导致更快的解决方案)
相关信息 我在这里找到了以下信息:
警告:Docker 特定变量只有在使用空数据目录启动容器时才会生效;任何预先存在的数据库都将在容器启动时保持不变。
- 我认为这就是我遇到这个问题的原因,但还不是 100% 确定
解决方案
我从头到尾都试过了,一切正常。请参考以下步骤:
- 首先我安装
dockerode
在我的机器上npm install dockerode
。 - 弄清楚我的
machine ip
以及port
暴露在哪个 docker 守护进程上。 - 创建
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
是容器内的目录。
- 运行js文件
node run.js
- 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=#
- 还检查了
/root/dir
我主机上目录的内容,看看它是否正确安装。
$ ls /root/dir/
test.txt
$
请从你的最后尝试这个,让我知道。
推荐阅读
- c# - 无法在 IIS 上发布 Asp.Net Core 应用程序
- mysql - MySQL HAVING 给了我不同的结果
- c# - 带有密码迭代功能的 AES CBC 端口从 C# 到 Node
- video - FFmpeg 在视频顶部添加标题,如模因
- javascript - Javascript 浏览器 SOAP HTTP 标头
- python-3.x - 用户令牌不适用于 sonarqube6.4 api?
- pointers - Go 中指向结构或数组值的指针如何工作?
- vuejs2 - VueJS v-for在索引数组的第一个元素
- sql-server - 作为存储过程输入的列值
- php - PHP数组到带有换行符的字符串