如何将一个node Docker容器与一个Postgres Docker容器连接

3

我有一个在本地机器上运行的基于Node的CRUD应用程序。它在Node上运行,使用Postgres作为数据库,使用Knex.js作为查询构建器等等。

我创建了一个Docker文件和一个docker-compose文件,容器已经启动,但是Node容器无法访问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内部检查节点应用程序的hosts文件时,我没有看到任何提及与Postgres容器链接的内容。非常感谢您的帮助。谢谢。
2个回答

3
你的 Node 应用程序无法连接的原因是它试图连接自身,因为你正在引用 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容器的环境变量。


谢谢,这正是我在考虑的事情,不过我不确定我应该如何更新连接文件。我会尝试你建议的修改。假设这样可以成功,那么我理论上可以从节点容器中运行迁移,并且它应该像平常一样迁移/填充数据库,对吗? - jdix87
看起来你的Dockerfile会将整个源代码复制到镜像中,所以只需确保运行docker-compose build然后docker-compose down; docker-compose up -d,这样应该会更新新文件。你可以通过docker-compose exec app cat /path/to/knex.js来验证是否已经进行了编辑。是的,只要你成功建立了连接,迁移应该可以工作。话虽如此,我没有看到你在连接字符串中传递任何凭据,所以可能需要先修复这个问题。 - leeman24
我尝试过从连接字符串中传递凭据,但是我认为格式可能有误,因为我遇到了一些奇怪的错误。我正在寻找文档,以便了解字符串应该如何格式化。如果我找不到相关信息,您能否告诉我正确的格式?我猜想我需要从docker-compose文件中传递凭据吗? - jdix87
1
我最终搞定了,connection: 'postgres://app:password@postgres/db'。现在我需要弄清楚如何在我的docker-compose中添加第二个测试数据库。 - jdix87
好的。我认为你不能使用开箱即用的入口点创建第二个数据库。你可能需要手动创建它或修改入口点(例如,https://github.com/docker-library/postgres/blob/0a66d53fface5ccc8274f99712ba2f382a1caf42/12/alpine/docker-entrypoint.sh)。 - leeman24
我从吃了亏才明白,现在我的想法是只使用两个独立的容器,一个用于开发,另一个用于测试。因为我在本地有两个数据库专门用于这些目的,并且它运行良好。 - jdix87

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接