为 NodeJS + PostgreSQL Web 应用程序创建 Docker 映像

Posted

技术标签:

【中文标题】为 NodeJS + PostgreSQL Web 应用程序创建 Docker 映像【英文标题】:Create Docker image for NodeJS + PostgreSQL web application 【发布时间】:2016-08-21 01:46:38 【问题描述】:

我一直在阅读 Docker 的文档,但无法创建一个可以工作的镜像。

我有一个使用 PostgreSQL 作为数据库的 NodeJS 应用程序:

var connectionString = process.env.DATABASE_URL || 'postgres://localhost:5432/db';
var pg = require('pg');
var pgp = require('pg-promise')();
var db = pgp(connectionString);
db.func('some_storedProcedure').then(//...)
//...

我先根据Node's documentation为它创建了一个Dockerfile:

FROM node:argon

# Create app directory
RUN mkdir -p /app
WORKDIR /app

# Install app dependencies
COPY package.json /app
RUN npm install

# Bundle app source
COPY . /app

EXPOSE 5000

CMD [ "npm", "start" ]

然后我关注this post 使用 docker-compose 将数据库连接到它。 docker-compose.yml 文件看起来像:

web:


 build: .
  ports:
    - "5000:5000"
  volumes:
    - .:/app
  links:
    - db
  environment:
    DATABASE_URL: postgres://myuser:mypass@db:5432/db
db:
  image: postgres
  environment:
    POSTGRES_USER: myuser
    POSTGRES_PASSWORD: mypass

这是创建图像后使用这些文件运行 docker-compose up 时返回的(部分)内容。

npm info ok 
 ---> 87dbbae35721
Removing intermediate container c73f826a0b3d
Step 6 : COPY . /app
 ---> ec56bfc11d3c
Removing intermediate container 745ddf82d742
Step 7 : EXPOSE 5000
 ---> Running in b2be5aecd9d6
 ---> a7d126a7ea5e
Removing intermediate container b2be5aecd9d6
Step 8 : CMD npm start
 ---> Running in 0379d512c688
 ---> 266517f47311
Removing intermediate container 0379d512c688
Successfully built 266517f47311
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Starting imagename_db_1
Creating imagename_web_1
Attaching to imagename_db_1, imagename_web_1
web_1  | npm info it worked if it ends with ok
web_1  | npm info using npm@2.15.1
web_1  | npm info using node@v4.4.3
web_1  | npm info prestart SharedServer@5.8.0
web_1  | npm info start SharedServer@5.8.0
web_1  | 
web_1  | > SharedServer@5.8.0 start /app
web_1  | > node index.js
web_1  | 
web_1  | Wed, 27 Apr 2016 00:41:19 GMT body-parser deprecated bodyParser: use individual json/urlencoded middlewares at index.js:13:9
web_1  | Wed, 27 Apr 2016 00:41:19 GMT body-parser deprecated undefined extended: provide extended option at node_modules/body-parser/index.js:105:29
web_1  | Node app is running on port 5000
db_1   | LOG:  database system was interrupted; last known up at 2016-04-25 00:17:59 UTC
db_1   | LOG:  database system was not properly shut down; automatic recovery in progress
db_1   | LOG:  invalid record length at 0/17076E8
db_1   | LOG:  redo is not required
db_1   | LOG:  MultiXact member wraparound protections are now enabled
db_1   | LOG:  database system is ready to accept connections
db_1   | LOG:  autovacuum launcher started

当我访问 http://localhost:5000 时,我看到 Web 应用程序正在运行,但每当我启动尝试访问数据库的东西时,我都会收到 HTTP 500 错误,正文如下

code: "28P01"
file: "auth.c"
length: 98
line: "285"
name: "error"
routine: "auth_failed"
severity: "FATAL"

我做错了什么?我不确定我是否了解我在使用 Docker 做什么,我唯一的文档是构建特定环境的简单配方(或者至少,这是我所理解的)

谢谢。

【问题讨论】:

该错误表明您对数据库服务器的身份验证详细信息失败。您可以从您的应用程序成功连接到服务器吗?你可以检查这个:***.com/questions/36120435/…。如果运气不好,你可以试试这个:***.com/questions/35807792/…。此外,当您已经获得 pg-promise 时,您不需要包含 pg ;) @vitaly:如果我在我的主机系统中运行我的应用程序,我完全没有连接问题。它正在通过引发此问题的图像运行应用程序 可能是 docker 配置的问题。您没有指定数据库端口,可能是您的用户名或密码错误。 5000 是 node.js 应用程序端口,对吧?您是否构建了 postgres 数据库 docker,它是否正在侦听 5432 端口? @ThanhNguyenVan:不,我认为 PostgreSQL 已经使用 docker-compose 安装在映像中 【参考方案1】:

检查 $PGDATA 中的 pg_hba.conf 是否允许来自 node.js 的连接。

默认情况下 pg_hba.conf 是这样的:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust

这对于通过操作系统所有者的标准 psql 连接来说很好,因为它允许本地连接受信任的本地连接 IP 地址 127.0.0.1。但是,如果您在服务器上设置了 IP 地址,我猜您这样做了,那么您需要允许一个条目,因为在您的 node.js 配置中,您指的是“DB”主机。因此 ping "DB" 并添加该 IP 地址:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
host    db              myuser          <ip-for-db-host>        md5

更改该文件后,您需要执行 pg_ctl 重新加载。

【讨论】:

如何在图像中检查?例如,在 Ubuntu 中安装 PostgreSQL 时,配置文件的路径是否与我可以找到的路径相同? 是的,一旦您使用 initdb 创建了一个实例,pg_hba.conf 始终位于数据目录中。默认情况下,如果你没有明确告诉它安装在哪里,它可能会在 /var/lib/pgsql-9.5/data 之类的地方。

以上是关于为 NodeJS + PostgreSQL Web 应用程序创建 Docker 映像的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PostgreSQL 将数据从 AngularJS 前端传递到 Nodejs 后端?

NodeJS,将来自 MySQL 和 PostgreSQL 的数据存储在 SQLite 中

nodejs之我的开源module 使用express搭建web服务器,代码即文档的实现。

nodejs中的RXJS PostgreSQL背压

如何以正确的方式将 PostgreSQL 连接到 NodeJS? [复制]

使用 PostgreSQL/NodeJS 获取 JOIN 表作为结果数组