Node.js 无法从应用程序容器访问postgres容器
我有一个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 重新启动:除非停止 卷数: 数据库数据: 编辑:上面的代码更改为删除链接并公开 数据库服务输出: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
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创建了真正的最小项目,但我仍然有问题,它是: