使用 Knex.js 和 PostgreSQL 设置 Docker

Posted

技术标签:

【中文标题】使用 Knex.js 和 PostgreSQL 设置 Docker【英文标题】:Setting up Docker with Knex.js and PostgreSQL 【发布时间】:2018-07-22 21:28:05 【问题描述】:

今天我一直在尝试为我的 GraphQL API 设置 Docker,该 API 与 Knex.js、PostgreSQL 和 Node.js 一起运行。我面临的问题是 Knex.js 在尝试访问我的数据库中的数据时超时。我相信这是由于我尝试将它们链接在一起的方式不正确。

我真的尝试过自己做这件事,但我想不通。我想浏览每个参与完成这项工作的文件,以便(希望)有人能发现我的错误并帮助我。

knexfile.js

在我的 knexfile 中,我有一个 connection 键,以前看起来像这样:

connection: 'postgres://localhost/devblog'

这工作得很好,但如果我想使用 Docker,这将不起作用。所以我稍微修改了一下,结果是这样的:

connection: 
  host: 'db' || 'localhost',
  port: process.env.DB_PORT || 5432,
  user: process.env.DB_USER || 'postgres',
  password: process.env.DB_PASSWORD || undefined,
  database: process.env.DATABASE // DATABASE = devblog

我注意到host 有问题。因为当我有其他东西(在本例中为db)而不是localhost 时,它总是超时。

Dockerfile

我的 Dockerfile 如下所示:

FROM node:9
WORKDIR /app
COPY package-lock.json /app
COPY package.json /app
RUN npm install
COPY dist /app
COPY wait-for-it.sh /app
CMD node index.js
EXPOSE 3010

docker-compose.yml

这个文件看起来像这样:

version: "3"
services:
  redis:
    image: redis
    networks:
      - webnet
  db:
    image: postgres
    networks:
      - webnet
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: martinnord
      POSTGRES_DB: devblog
  web:
    image: node:8-alpine
    command: "node /app/dist/index.js"
    volumes:
      - ".:/app"
    working_dir: "/app"
    depends_on:
      - "db"
    ports:
      - "3010:3010"
    environment:
      DB_PASSWORD: password
      DB_USER: martinnord
      DB_NAME: devblog
      DB_HOST: db
      REDIS_HOST: redis
networks:
  webnet:

当我尝试使用 docker-compose up 运行它时,我得到以下输出:

Starting backend_db_1 ... done
Starting backend_web_1 ... done
Attaching to backend_db_1, backend_redis_1, backend_web_1
redis_1  | 1:C 12 Feb 16:05:21.303 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 12 Feb 16:05:21.303 # Redis version=4.0.8, bits=64, commit=00000000, modified=0, pid=1, just started
db_1     | 2018-02-12 16:05:21.337 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
redis_1  | 1:C 12 Feb 16:05:21.303 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 12 Feb 16:05:21.311 * Running mode=standalone, port=6379.
db_1     | 2018-02-12 16:05:21.338 UTC [1] LOG:  listening on IPv6 address "::", port 5432
redis_1  | 1:M 12 Feb 16:05:21.311 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 12 Feb 16:05:21.314 # Server initialized
redis_1  | 1:M 12 Feb 16:05:21.315 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
db_1     | 2018-02-12 16:05:21.348 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1     | 2018-02-12 16:05:21.367 UTC [20] LOG:  database system was shut down at 2018-02-12 16:01:17 UTC
redis_1  | 1:M 12 Feb 16:05:21.317 * DB loaded from disk: 0.002 seconds
redis_1  | 1:M 12 Feb 16:05:21.317 * Ready to accept connections
db_1     | 2018-02-12 16:05:21.374 UTC [1] LOG:  database system is ready to accept connections
web_1    | DB_HOST db
web_1    |
web_1    |       App listening on 3010
web_1    |       Env: undefined

但是当我尝试使用 GraphQL 进行查询时,我得到: "message": "Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?"

我真的不知道为什么这对我不起作用并且让我发疯。如果有人可以帮助我,我会很高兴。我还在下面添加了一个指向我的项目的链接。

非常感谢您的阅读!干杯。

项目链接:https://github.com/Martinnord/DevBlog/tree/master/backend

更新了 docker-compose 文件:

version: "3"
services:
  redis:
    image: redis
    networks:
      - webnet
  db:
    image: postgres
    networks:
      - webnet
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: martinnord
      POSTGRES_DB: devblog
    ports:
      - "15432:5432"
  web:
    image: devblog-server
    ports:
      - "3010:3010"
    networks:
      - webnet
    environment:
      DB_PASSWORD: password
      DB_USER: martinnord
      DB_NAME: devblog
      DB_HOST: db
      REDIS_HOST: redis
    command: ["./wait-for-it.sh", "db:5432", "--", "node", "index.js"]
networks:
    webnet:

【问题讨论】:

【参考方案1】:

可能是这样的:

version: "3"
services:
  redis:
    image: redis
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: martinnord
      POSTGRES_DB: devblog
    ports:
      - "15432:5432"
  web:
    image: node:8-alpine
    command: "node /app/dist/index.js"
    volumes:
      - ".:/app"
    working_dir: "/app"
    depends_on:
      - "db"
    ports:
      - "3010:3010"
    links:
      - "db"
      - "redis"
    environment:
      DB_PASSWORD: password
      DB_USER: martinnord
      DB_NAME: devblog
      DB_HOST: db
      REDIS_HOST: redis

您应该能够通过以下方式从 webapp 连接到 postgres: postgres://martinnord:password@db/devblog

connection: 
  host: process.DB_HOST,
  port: process.env.DB_PORT || 5432,
  user: process.env.DB_USER || 'postgres',
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME || 'postgres'

我还添加了将在 docker 中运行的 postgres 公开到端口 15432 的行,因此您可以尝试首先直接从主机连接它

psql postgres://martinnord:password@localhost:15432/devblog

【讨论】:

感谢您的回答。我注意到我无法让服务器以docker-compose 文件开头。因此对其进行了一些更改(请参阅更新的问题)。现在服务器正在运行,但是当我尝试进行查询时得到了这个,我得到了这种类型的错误:"select * from \"users\" where \"email\" = $1 - relation \"users\" does not exist"。我也尝试直接在终端内连接到数据库,我可以连接,但我看不到任何数据。再次感谢您的回答。 即使数据库在容器中,您仍然需要持久化数据库文件。您需要像这样将本地 db 文件映射到您的实例: volumes: - "/tmp/pgdata:/var/lib/postgresql/data" @Scott true,我只为那些使用 docker 数据库,我总是在启动时再次初始化以进行测试等。所以在我的情况下,我不需要保留我的数据。 我们能解决这个问题吗?我有同样的问题 @MeiyappanKannappa 如果你想在 linux 和 mac 中为 docker 持久化卷,你可以通过将本地目录映射到你的容器来做到这一点,正如@Scott 所说,在 Windows 上你需要在 docker 中为里面的数据创建卷docker-compose.yml volumes: 部分并将其映射到容器内的/var/lib/postgresql/data

以上是关于使用 Knex.js 和 PostgreSQL 设置 Docker的主要内容,如果未能解决你的问题,请参考以下文章

Alter table modify enum in Knex js for Postgresql 给出错误

如何在 Knex.js 中正确设置“updatedAt”时间戳?

Knex.js 会阻止 sql 注入吗?

使用具有多个搜索条件的 Knex.js 和 SQL 的条件过滤器

使用 Knex.js 进行多行插入

Knex.js:加入 'select' 和 'where' 子句