ECONNREFUSED for Postgres on nodeJS with dockers
ECONNREFUSED for Postgres on nodeJS with dockers
我正在使用 postgresql 在 NodeJS 上构建应用 运行ning。
我正在使用 SequelizeJS 作为 ORM。
为了避免使用真正的 postgres 守护进程并在我自己的设备上安装 nodejs,我正在使用带有 docker-compose.
的容器
当我运行docker-compose up
它启动 pg 数据库
database system is ready to accept connections
和 nodejs 服务器。
但是服务器无法连接到数据库。
Error: connect ECONNREFUSED 127.0.01:5432
如果我尝试 运行 服务器而不使用容器(在我的机器上使用真正的 nodejs 和 postgresd)它会工作。
但我希望它能与容器一起正常工作。我不明白我做错了什么。
这里是 docker-compose.yml
文件
web:
image: node
command: npm start
ports:
- "8000:4242"
links:
- db
working_dir: /src
environment:
SEQ_DB: mydatabase
SEQ_USER: username
SEQ_PW: pgpassword
PORT: 4242
DATABASE_URL: postgres://username:pgpassword@127.0.0.1:5432/mydatabase
volumes:
- ./:/src
db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: username
POSTGRES_PASSWORD: pgpassword
有人可以帮我吗?
(有人喜欢 docker :))
你的DATABASE_URL
指的是127.0.0.1
,也就是loopback adapter (more here)。这意味着“连接到我自己”。
当 运行 两个应用程序(不使用 Docker)在同一台主机上时,它们都可以在同一适配器上寻址(也称为 localhost
)。
当 运行 两个应用程序都在容器中时,它们不像以前那样都在本地主机上。相反,您需要将 web
容器指向 docker0
适配器上 db
容器的 IP 地址 - docker-compose
为您设置。
变化:
127.0.0.1
到 CONTAINER_NAME
(例如 db
)
示例:
DATABASE_URL: postgres://username:pgpassword@127.0.0.1:5432/mydatabase
到
DATABASE_URL: postgres://username:pgpassword@db:5432/mydatabase
这要归功于 Docker 链接:web
容器有一个文件 (/etc/hosts
),其中 db
条目指向 db
容器已打开。这是系统(在本例中为容器)在尝试解析主机名时首先查找的位置。
如果您单独发送数据库变量。您可以分配数据库主机。
DB_HOST=<POSTGRES_SERVICE_NAME> #in your case "db" from docker-compose file.
对于更多读者,如果您使用 Docker desktop for Mac
,请使用 host.docker.internal
而不是 localhost
或 127.0.0.1
,如 doc 中所建议的那样。我遇到了同样的 connection refused...
问题。后端 api-service
无法使用 localhost/127.0.0.1
连接到 postgres
。下面是我的docker-compose.yml和环境变量作为参考:
version: "2"
services:
api:
container_name: "be"
image: <image_name>:latest
ports:
- "8000:8000"
environment:
DB_HOST: host.docker.internal
DB_USER: <your_user>
DB_PASS: <your_pass>
networks:
- mynw
db:
container_name: "psql"
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_DB: <your_postgres_db_name>
POSTGRES_USER: <your_postgres_user>
POSTGRES_PASS: <your_postgres_pass>
volumes:
- ~/dbdata:/var/lib/postgresql/data
networks:
- mynw
我有两个容器,一个叫 postgresdb,另一个叫 node
我更改了我的节点 queries.js 来自:
const pool = new Pool({
user: 'postgres',
host: 'localhost',
database: 'users',
password: 'password',
port: 5432,
})
到
const pool = new Pool({
user: 'postgres',
host: 'postgresdb',
database: 'users',
password: 'password',
port: 5432,
})
我所要做的就是将主机更改为我的容器名称 ["postgresdb"],这为我解决了这个问题。我确信这可以做得更好,但我最近 2 天刚刚学习了 docker compose / node.js 东西。
如果其他解决方案中的 none 对您有效,请考虑手动包装 PgPool.connect()
并在 ECONNREFUSED 时重试:
const pgPool = new Pool(pgConfig);
const pgPoolWrapper = {
async connect() {
for (let nRetry = 1; ; nRetry++) {
try {
const client = await pgPool.connect();
if (nRetry > 1) {
console.info('Now successfully connected to Postgres');
}
return client;
} catch (e) {
if (e.toString().includes('ECONNREFUSED') && nRetry < 5) {
console.info('ECONNREFUSED connecting to Postgres, ' +
'maybe container is not ready yet, will retry ' + nRetry);
// Wait 1 second
await new Promise(resolve => setTimeout(resolve, 1000));
} else {
throw e;
}
}
}
}
};
(请参阅 node-postgres 中的 this issue 进行跟踪。)
我来这里是为了处理这个问题。
正如Andy在他的回应中所说。
- "you need to point the
web
container to the db
container's"
并考虑到有关 docker-compose link's
的官方文档
- "Links are not required to enable services to communicate - by default, any service can reach any other service at that service’s name."
因此,您可以这样保持 docker_compose.yml:
docker_compose.yml
version: "3"
services:
web:
image: node
command: npm start
ports:
- "8000:4242"
# links:
# - db
working_dir: /src
environment:
SEQ_DB: mydatabase
SEQ_USER: username
SEQ_PW: pgpassword
PORT: 4242
# DATABASE_URL: postgres://username:pgpassword@127.0.0.1:5432/mydatabase
DATABASE_URL: "postgres://username:pgpassword@db:5432/mydatabase"
volumes:
- ./:/src
db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: username
POSTGRES_PASSWORD: pgpassword
但在我们编码时,这是一种很酷的冗长方式。所以,你的方法很好。
如前所述here.
Each container can now look up the hostname web
or db
and get back the appropriate container’s IP address. For example, web
’s application code could connect to the URL postgres://db:5432
and start using the Postgres database.
It is important to note the distinction between HOST_PORT
and CONTAINER_PORT
. In the above example, for db
, the HOST_PORT
is 8001
and the container port is 5432
(postgres default). Networked service-to-service communication uses the CONTAINER_PORT
. When HOST_PORT
is defined, the service is accessible outside the swarm as well.
Within the web
container, your connection string to db
would look like postgres://db:5432
, and from the host machine, the connection string would look like postgres://{DOCKER_IP}:8001
.
所以DATABASE_URL
应该是postgres://username:pgpassword@db:5432/mydatabase
我正在使用 postgresql 在 NodeJS 上构建应用 运行ning。 我正在使用 SequelizeJS 作为 ORM。 为了避免使用真正的 postgres 守护进程并在我自己的设备上安装 nodejs,我正在使用带有 docker-compose.
的容器当我运行docker-compose up
它启动 pg 数据库
database system is ready to accept connections
和 nodejs 服务器。 但是服务器无法连接到数据库。
Error: connect ECONNREFUSED 127.0.01:5432
如果我尝试 运行 服务器而不使用容器(在我的机器上使用真正的 nodejs 和 postgresd)它会工作。
但我希望它能与容器一起正常工作。我不明白我做错了什么。
这里是 docker-compose.yml
文件
web:
image: node
command: npm start
ports:
- "8000:4242"
links:
- db
working_dir: /src
environment:
SEQ_DB: mydatabase
SEQ_USER: username
SEQ_PW: pgpassword
PORT: 4242
DATABASE_URL: postgres://username:pgpassword@127.0.0.1:5432/mydatabase
volumes:
- ./:/src
db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: username
POSTGRES_PASSWORD: pgpassword
有人可以帮我吗?
(有人喜欢 docker :))
你的DATABASE_URL
指的是127.0.0.1
,也就是loopback adapter (more here)。这意味着“连接到我自己”。
当 运行 两个应用程序(不使用 Docker)在同一台主机上时,它们都可以在同一适配器上寻址(也称为 localhost
)。
当 运行 两个应用程序都在容器中时,它们不像以前那样都在本地主机上。相反,您需要将 web
容器指向 docker0
适配器上 db
容器的 IP 地址 - docker-compose
为您设置。
变化:
127.0.0.1
到 CONTAINER_NAME
(例如 db
)
示例:
DATABASE_URL: postgres://username:pgpassword@127.0.0.1:5432/mydatabase
到
DATABASE_URL: postgres://username:pgpassword@db:5432/mydatabase
这要归功于 Docker 链接:web
容器有一个文件 (/etc/hosts
),其中 db
条目指向 db
容器已打开。这是系统(在本例中为容器)在尝试解析主机名时首先查找的位置。
如果您单独发送数据库变量。您可以分配数据库主机。
DB_HOST=<POSTGRES_SERVICE_NAME> #in your case "db" from docker-compose file.
对于更多读者,如果您使用 Docker desktop for Mac
,请使用 host.docker.internal
而不是 localhost
或 127.0.0.1
,如 doc 中所建议的那样。我遇到了同样的 connection refused...
问题。后端 api-service
无法使用 localhost/127.0.0.1
连接到 postgres
。下面是我的docker-compose.yml和环境变量作为参考:
version: "2"
services:
api:
container_name: "be"
image: <image_name>:latest
ports:
- "8000:8000"
environment:
DB_HOST: host.docker.internal
DB_USER: <your_user>
DB_PASS: <your_pass>
networks:
- mynw
db:
container_name: "psql"
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_DB: <your_postgres_db_name>
POSTGRES_USER: <your_postgres_user>
POSTGRES_PASS: <your_postgres_pass>
volumes:
- ~/dbdata:/var/lib/postgresql/data
networks:
- mynw
我有两个容器,一个叫 postgresdb,另一个叫 node
我更改了我的节点 queries.js 来自:
const pool = new Pool({
user: 'postgres',
host: 'localhost',
database: 'users',
password: 'password',
port: 5432,
})
到
const pool = new Pool({
user: 'postgres',
host: 'postgresdb',
database: 'users',
password: 'password',
port: 5432,
})
我所要做的就是将主机更改为我的容器名称 ["postgresdb"],这为我解决了这个问题。我确信这可以做得更好,但我最近 2 天刚刚学习了 docker compose / node.js 东西。
如果其他解决方案中的 none 对您有效,请考虑手动包装 PgPool.connect()
并在 ECONNREFUSED 时重试:
const pgPool = new Pool(pgConfig);
const pgPoolWrapper = {
async connect() {
for (let nRetry = 1; ; nRetry++) {
try {
const client = await pgPool.connect();
if (nRetry > 1) {
console.info('Now successfully connected to Postgres');
}
return client;
} catch (e) {
if (e.toString().includes('ECONNREFUSED') && nRetry < 5) {
console.info('ECONNREFUSED connecting to Postgres, ' +
'maybe container is not ready yet, will retry ' + nRetry);
// Wait 1 second
await new Promise(resolve => setTimeout(resolve, 1000));
} else {
throw e;
}
}
}
}
};
(请参阅 node-postgres 中的 this issue 进行跟踪。)
我来这里是为了处理这个问题。
正如Andy在他的回应中所说。
- "you need to point the
web
container to thedb
container's"
并考虑到有关 docker-compose link's
的官方文档- "Links are not required to enable services to communicate - by default, any service can reach any other service at that service’s name."
因此,您可以这样保持 docker_compose.yml:
docker_compose.yml
version: "3"
services:
web:
image: node
command: npm start
ports:
- "8000:4242"
# links:
# - db
working_dir: /src
environment:
SEQ_DB: mydatabase
SEQ_USER: username
SEQ_PW: pgpassword
PORT: 4242
# DATABASE_URL: postgres://username:pgpassword@127.0.0.1:5432/mydatabase
DATABASE_URL: "postgres://username:pgpassword@db:5432/mydatabase"
volumes:
- ./:/src
db:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: username
POSTGRES_PASSWORD: pgpassword
但在我们编码时,这是一种很酷的冗长方式。所以,你的方法很好。
如前所述here.
Each container can now look up the hostname
web
ordb
and get back the appropriate container’s IP address. For example,web
’s application code could connect to the URLpostgres://db:5432
and start using the Postgres database.
It is important to note the distinction between
HOST_PORT
andCONTAINER_PORT
. In the above example, fordb
, theHOST_PORT
is8001
and the container port is5432
(postgres default). Networked service-to-service communication uses theCONTAINER_PORT
. WhenHOST_PORT
is defined, the service is accessible outside the swarm as well.
Within the
web
container, your connection string todb
would look likepostgres://db:5432
, and from the host machine, the connection string would look likepostgres://{DOCKER_IP}:8001
.
所以DATABASE_URL
应该是postgres://username:pgpassword@db:5432/mydatabase