如何将节点 docker 容器与 postgres docker 容器连接起来

Posted

技术标签:

【中文标题】如何将节点 docker 容器与 postgres docker 容器连接起来【英文标题】:How to connect a node docker container with postgres docker container 【发布时间】:2020-03-08 13:34:23 【问题描述】:

我的本​​地机器上有一个在节点上运行的 CRUD 应用程序。它在节点上运行,使用 postgres 作为数据库,使用 knex.js 作为查询构建器等。

我已经创建了一个 docker 文件和一个 docker-compose 文件,并且容器启动了,但是节点容器无法到达 postgres 容器。我怀疑它与环境变量有关,但我不确定。这是我的 docker 文件:

FROM node:12
# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm ci --only=production

# Bundle app source
COPY . .

ENV PORT=8080
EXPOSE 8080

CMD [ "npm", "start" ]

这是 docker-compose 文件:

version: '2'
services:
  postgres:
    image: postgres:alpine
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: app
      POSTGRES_DB: db

  app:
    build: .
    depends_on:
      - "postgres"
    links:
      - "postgres"
    environment:
      DB_PASSWORD: 'password'
      DB_USER: 'app'
      DB_NAME: 'db'
      DB_HOST: 'postgres'
      PORT: 8080
    ports:
      - '8080:8080'
    command: npm start

另外,这是根目录下的 knex.js 文件,它根据环境处理数据库连接:

// Update with your config settings.

module.exports = 

  development: 
    client: 'pg',
    connection: 'postgres://localhost/db'
  ,
  test: 
    client: 'pg',
    connection: 'postgres://localhost/test-db'
  
;

此外,当我检查 docker 内节点应用程序上的主机文件时,我没有看到任何提及 postgres 容器链接的内容。任何帮助将不胜感激,谢谢。

【问题讨论】:

【参考方案1】:

Docker-compose 创建一个内部网络,由它启动的不同容器共享。 由于apppostgres 是2 个独立的容器,因此它们被视为2 个主机。当您将其指向 localhost 而不是 postgres 容器时,这会导致应用程序在同一容器上查找 postgres。

您可以通过在 knex.js 文件中将 localhost 更改为 postgres 来解决此问题。

【讨论】:

【参考方案2】:

您的节点应用程序未连接的原因是因为它在您引用localhost 时尝试连接到自身。您的数据库位于非本地的第二个容器中,因此您需要通过服务名称来引用它,即postgres

所以假设您的应用程序以另一种方式处理身份验证,您的配置将是这样的:

// Update with your config settings.

module.exports = 

  development: 
    client: 'pg',
    connection: 'postgres://postgres/db'
  ,
  test: 
    client: 'pg',
    connection: 'postgres://postgres/test-db'
  
;

如果可以,您应该使用分配给app 容器的环境变量。

【讨论】:

谢谢,这就是我的想法,但我不知道应该如何更新连接文件。我会尝试您建议的编辑。假设这可行,那么理论上我可以从节点容器运行迁移,并且它应该像往常一样迁移/播种数据库? 看起来您的 Dockerfile 会将整个源代码复制到映像中,因此只需确保您运行 docker-compose build 然后运行 ​​docker-compose down; docker-compose up -d 即可更新新文件。您可以通过docker-compose exec app cat /path/to/knex.js 进行验证以查看它是否有编辑。是的,只要您成功建立了连接,您的迁移就应该可以工作。也就是说,我没有看到您将任何凭据传递到连接字符串的任何位置,因此可能需要先修复。 我确实尝试尝试从连接字符串传递凭据,但我认为格式错误,因为我遇到了一些奇怪的错误。我正在寻找文档来向我展示字符串的格式应该是什么样的,如果我没有尽快找到它,你能告诉我正确的格式是什么吗?我假设我需要传递 docker-compose 文件中的凭据? 我确实让它工作了,connection: 'postgres://app:password@postgres/db' 现在我需要弄清楚如何在我的 docker-compose 中添加第二个测试数据库 好。我不认为您可以使用开箱即用的入口点创建第二个数据库。您可能需要手动创建它或修改入口点(例如,github.com/docker-library/postgres/blob/…)。

以上是关于如何将节点 docker 容器与 postgres docker 容器连接起来的主要内容,如果未能解决你的问题,请参考以下文章

如何将现有的 postgres 数据文件夹复制并使用到 docker postgres 容器中

节点服务器无法通过 Docker 连接到 Postgres,使用 TypeORM

docker-compose:nodejs容器不与postgres容器通信

如何在 docker 中从一个容器获取数据到另一个容器?我收到 ECONNREFUSED 错误

Docker - 如何在postgres容器中运行psql命令?

如何将docker容器添加到现有docker网络