Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 无法从应用程序容器访问postgres容器_Node.js_Postgresql_Docker_Docker Compose - Fatal编程技术网

Node.js 无法从应用程序容器访问postgres容器

Node.js 无法从应用程序容器访问postgres容器,node.js,postgresql,docker,docker-compose,Node.js,Postgresql,Docker,Docker Compose,我有一个docker-composer.yml,它正在设置两个服务:服务器和数据库。Node.js服务器是服务器服务,使用pg连接到PostgreSQL数据库;db服务是一个PostgreSQL映像 在服务器启动时,它尝试连接到数据库,但超时 docker-compose.yml 版本:“3.8” 服务: 服务器: 图片:myapi 生成:。 容器名称:服务器 环境文件:.env 环境: -端口=80 -数据库地址=postgres://postgres:postgres@db:15432/my

我有一个docker-composer.yml,它正在设置两个服务:服务器和数据库。Node.js服务器是服务器服务,使用pg连接到PostgreSQL数据库;db服务是一个PostgreSQL映像

在服务器启动时,它尝试连接到数据库,但超时

docker-compose.yml

版本:“3.8” 服务: 服务器: 图片:myapi 生成:。 容器名称:服务器 环境文件:.env 环境: -端口=80 -数据库地址=postgres://postgres:postgres@db:15432/mydb -REDIS_URL=redis://redis 端口: - 3000:80 取决于: -分贝 命令:node script.js 重新启动:除非停止 db: 图片:博士后 容器名称:db 环境: POSTGRES\u用户:POSTGRES POSTGRES_密码:POSTGRES 博士后数据库:mydb 端口: - 15432:15432 卷数: -数据库数据:/var/lib/postgresql/data 命令:-P15432 重新启动:除非停止 卷数: 数据库数据: 编辑:上面的代码更改为删除链接并公开

数据库服务输出:

db        | 
db        | PostgreSQL Database directory appears to contain a database; Skipping initialization
db        | 
db        | 2020-11-05 20:18:15.865 UTC [1] LOG:  starting PostgreSQL 13.0 (Debian 13.0-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
db        | 2020-11-05 20:18:15.865 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 15432
db        | 2020-11-05 20:18:15.865 UTC [1] LOG:  listening on IPv6 address "::", port 15432
db        | 2020-11-05 20:18:15.873 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.15432"
db        | 2020-11-05 20:18:15.880 UTC [25] LOG:  database system was shut down at 2020-11-05 20:18:12 UTC
db        | 2020-11-05 20:18:15.884 UTC [1] LOG:  database system is ready to accept connections
script.js-由来自服务器服务的命令使用

常数pg=要求“pg”; console.logprocess.env.DATABASE_URL; 常量池=新的pg.池{ connectionString:process.env.DATABASE\u URL, connectionTimeoutMillis:5000, }; pool.connecterr,u,done=>{ 如果出错{ console.error; 多纳尔; } 完成; }; pool.query'SELECT NOW',err,res=>{ console.logerr,res; 池。结束; }; const client=新的pg.client{ connectionString:process.env.DATABASE\u URL, connectionTimeoutMillis:5000, }; client.connectconsole.error; client.query'SELECT NOW',err,res=>{ console.logerr,res; 客户端; }; 服务器服务输出:

db        | 
db        | PostgreSQL Database directory appears to contain a database; Skipping initialization
db        | 
db        | 2020-11-05 20:18:15.865 UTC [1] LOG:  starting PostgreSQL 13.0 (Debian 13.0-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
db        | 2020-11-05 20:18:15.865 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 15432
db        | 2020-11-05 20:18:15.865 UTC [1] LOG:  listening on IPv6 address "::", port 15432
db        | 2020-11-05 20:18:15.873 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.15432"
db        | 2020-11-05 20:18:15.880 UTC [25] LOG:  database system was shut down at 2020-11-05 20:18:12 UTC
db        | 2020-11-05 20:18:15.884 UTC [1] LOG:  database system is ready to accept connections
注意:第一行是script.js的第一个console.log调用的输出

注意:由于服务器服务是使用restart:设置的,除非停止,否则它将永远重复此输出

此输出表示连接成功

总之: 我无法从服务器容器访问db容器,连接超时,但我可以从主机访问db容器,连接成功

考虑 首先,谢谢你迄今为止的回答。针对提出的一些问题:

缺失网络:

它不是必需的,因为docker compose有一个默认网络。A使用自定义网络进行了测试,但也不起作用

初始化顺序:

我使用dependens_on来确保首先启动db容器,但我知道这并不能确保首先初始化数据库,然后再初始化服务器。这不是问题,因为服务器在发生超时时会中断,并且会再次运行,因为它是使用restart:设置的,除非停止。因此,如果数据库在第一次或第二次尝试启动服务器时仍在初始化,则没有问题,因为服务器将继续重新启动,直到连接成功为止,而连接从未发生过

更新:

从服务器容器中,我可以使用psql访问db服务处的数据库。我仍然无法从Node.js应用程序进行连接

数据库URL不是问题所在,因为我在psql命令中使用的URI与script.js使用的URI相同,并由那里的第一个console.log调用打印出来

使用的命令行:

docker exec -it server psql postgres://postgres:postgres@db:15432/mydb

编辑:通过删除Sequelize的依赖项来改进代码。现在它只使用pg,直接调用脚本。

感谢您提供了重现该问题的源代码。 docker compose文件中没有问题,因为您已经排除了这种可能性

问题在于Dockerfile和您正在使用的node pg版本之间

您正在使用节点:14和pg:7.18.2。 事实证明,在node 14和node-pg的早期版本上存在一个漏洞

解决方案是降级到node v12,或者使用node pg的最新版本,该版本目前是v8.0.3上的8.4.2补丁


我已经在您提供的分支上验证了这两种解决方案,它们都有效。

这不是一个完整的答案;我手头没有您的代码,因此无法实际测试compose文件。但是,我想指出一些问题:

links指令已弃用

链接是Docker引入用户定义网络和自动DNS支持之前使用的传统选项。你可以把它扔掉。组合文件中的容器可以通过名称相互引用,而无需使用

expose指令什么也不做。它可以在Dockerfile中提供信息,作为一种说法,此映像将公开此端口上的服务,但实际上不会使任何事情发生。在编写文件时,它几乎完全没有用处

dependens_on指令也没有您想象的那么有用。它确实会导致docker compose首先调出数据库容器,但它会在第一个进程启动后立即考虑调出容器。这不会导致docker公司破产 ose将等待数据库准备好为请求提供服务,这意味着如果应用程序在数据库准备好之前尝试连接,您仍然会遇到错误

最好的解决方案是在应用程序中构建数据库重新连接逻辑,以便在数据库出现故障时(例如,您重新启动postgres容器以激活新配置或升级postgres版本),应用程序将重试连接,直到成功

一个可接受的解决方案是在应用程序启动中包含代码,该代码会一直阻塞,直到数据库响应请求为止


这个问题与docker无关。要对此进行测试,请执行以下操作:

通过使用此docker-compose.yml文件:

版本:“3.8” 服务: 应用程序: 图片:ubuntu 容器名称:app 命令:睡眠8小时 db: 图片:博士后 容器名称:db 环境: POSTGRES\u用户:POSTGRES POSTGRES_密码:POSTGRES 博士后数据库:mydb 揭露: - '15432' 端口: - 15432:15432 卷数: -数据库数据:/var/lib/postgresql/data 命令:-P15432 重新启动:除非停止 卷数: 数据库数据: 执行docker exec-it应用程序bash进入容器应用程序,然后使用apt install-y postgresql client`安装postgresql客户端

命令psql-hdb-p15432-uppostgres-W成功

检查pg配置 您说pg使用环境变量数据库的URL来访问postgresql。我不确定:

从中,我们可以找到以下示例:

$PGUSER=dbuser\ PGHOST=database.server.com\ PGPASSWORD=保密密码\ PGDATABASE=mydb\ PGPORT=3211\ node script.js 这句话:

节点postgres使用与libpq相同的环境变量连接到PostgreSQL服务器

在libpq文档中,没有数据库URL

要将pg文档中提供的示例与docker-compose.yml文件相适应,请尝试使用以下文件I only changed environments变量的应用程序服务:

版本:“3.8” 服务: 服务器: 图片:myapi 生成:。 容器名称:服务器 环境文件:.env 环境: -端口=80 -PGUSER=postgres -PGPASSWORD=postgres -PGHOST=db -PGDATABASE=mydb -PGPORT=15432 -REDIS_URL=redis://redis 端口: - 3000:80 取决于: -分贝 命令:node script.js 重新启动:除非停止 db: 图片:博士后 容器名称:db 环境: POSTGRES\u用户:POSTGRES POSTGRES_密码:POSTGRES 博士后数据库:mydb 端口: - 15432:15432 卷数: -数据库数据:/var/lib/postgresql/data 命令:-P15432 重新启动:除非停止 卷数: 数据库数据:
很长一段时间我没有使用docker,但可能尝试添加:networks:-mynetwork与服务器内部端口和db services处于同一级别。我无法重现您的错误:我重新使用了docker compose文件,用标准ubuntu映像替换了service app,执行了docker compose并安装了postgresql客户端。来自应用容器的命令psql-hdb-p15432-U postgres-W成功!我建议您查看Sequelize的配置,可能是连接字符串中的错误。@NelsonG@jeeves我刚刚试过,我可以从服务器容器使用psql访问db容器。现在我需要找出为什么我无法使用pg从node.js应用程序访问。感谢您的帮助!你能分享你的Dockerfile吗。我已经拿走了你的docker文件和脚本,无法重现你的问题。我使用node:10 alpine作为基本映像,除了使用解决方案更新的pgAnswer之外,没有安装其他lib:我在问题描述的末尾添加了一些注意事项。正如你所说,我也测试了单独启动它们,但问题仍然存在。这就是为什么它在主机上工作,节点版本是12。非常感谢。我在问题描述的末尾添加了一些关于初始化顺序的注意事项。我做了一个测试:我启动了db容器,并通过从主机访问确保数据库已正确初始化,然后启动了服务器容器,但得到了相同的输出:超时。我将删除链接并公开,谢谢。关于这一点,可以肯定地说,端口是可以访问的,因为我可以从主机上完成。我对我的项目进行了一个最小的实现,但你的想法最好是作为最小的项目。我会试试这个,然后带着任何反馈返回。谢谢好的,我只使用pg创建了真正的最小项目,但我仍然有问题,它是: