docker-compose ECONNREFUSED 用于 nodeJS 上的 Postgres

Posted

技术标签:

【中文标题】docker-compose ECONNREFUSED 用于 nodeJS 上的 Postgres【英文标题】:docker-compose ECONNREFUSED for Postgres on nodeJS 【发布时间】:2018-01-16 09:47:46 【问题描述】:

此错误与ECONNREFUSED 相同。但是实现方式不同,那我这里再问一个问题。

这是docker-compose.yml 文件

version: '3'

services:
  server:
    build:
      context: .
    volumes:
      # Mounts the project directory on the host to /app inside the container,
      # allowing you to modify the code without having to rebuild the image.
      - .:/app
      # Just specify a path and let the Engine create a volume.
      # Data present in the base image at the specified mount point will be copied
      # over to the new volume upon volume initialization.
      # node_modules from this new volume will be used and not from your local dev env.
      - /app/node_modules/

    # Expose ports [HOST:CONTAINER
    ports:
      - "4040:4040"

    # Set environment variables from this file
    env_file:
      - .env

    # Overwrite any env var defined in .env file (if required)
    environment:
      - NODE_ENV=development

    # Link to containers in another service.
    # Links also express dependency between services in the same way as depends_on,
    # so they determine the order of service startup.
    links:
      - postgres
  postgres:
    image: "postgres:9.6"
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: 123456
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres

这是我用来存储数据库信息的database.json文件


"development": 
    "username": "postgres",
    "password": "123456",
    "database": "mydb",
    "host": "127.0.0.1",
    "dialect": "postgres",
    "pool": 
        "max": 100,
        "min": 0,
        "idle": 10000
    
,
"test": 
    "username": "postgres",
    "password": "123456",
    "database": "mytestdb",
    "host": "127.0.0.1",
    "dialect": "postgres"
,
"production": 
    "username": "postgres",
    "password": "123456",
    "database": "mydb",
    "host": "127.0.0.1",
    "dialect": "postgres"


并使用Sequelize连接DB

import database from '../../config/database.json'

const sequelize = new Sequelize(dbConfig.database, dbConfig.username, dbConfig.password, dbConfig)

我知道,当我在容器中运行应用程序时,它们并不都在 locahost 上,那么我必须更改 host,但是我可以在这里如何更改。我通过将host 更新为postgres 来解决问题。它有效,但解决方案不是我想要找到的。

顺便问一下,我如何在这里创建数据库。

postgres_1 | FATAL: database "starflow" does not exist

【问题讨论】:

那么你想要什么解决方案?因为把host改成postgres是最好的办法 我需要为 docker 创建一个新环境吗?只想使用开发在本地运行服务器。 Docker 在一个新的环境中运行。并且您需要在容器第一次运行时配置该环境。 【参考方案1】:

您需要做两件事。一种是将您的应用程序移动到数据库的网络上,这样数据库就可以在主机上使用。这需要向您的服务添加 network_mode。查看更新的 yaml

version: '3'

services:
  server:
    build:
      context: .
    volumes:
      # Mounts the project directory on the host to /app inside the container,
      # allowing you to modify the code without having to rebuild the image.
      - .:/app
      # Just specify a path and let the Engine create a volume.
      # Data present in the base image at the specified mount point will be copied
      # over to the new volume upon volume initialization.
      # node_modules from this new volume will be used and not from your local dev env.
      - /app/node_modules/

    # Expose ports [HOST:CONTAINER
    # ports:
    #   - "4040:4040"
    
    network_mode: service:postgres

    # Set environment variables from this file
    env_file:
      - .env

    # Overwrite any env var defined in .env file (if required)
    environment:
      - NODE_ENV=development

    # Link to containers in another service.
    # Links also express dependency between services in the same way as depends_on,
    # so they determine the order of service startup.
    links:
      - postgres
  postgres:
    image: "postgres:9.6"
    ports:
      - "5432:5432"
      - "4040:4040"
    environment:
      POSTGRES_PASSWORD: 123456
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres

请注意,端口已移至提供网络的服务。我们在postgres 网络上运行server 服务。这样,两者都可以在 localhost 上相互访问,并且无需更改您的环境配置。

仅建议在开发或测试环境中使用,而不是在生产环境中使用。因此,如果您正在开发将在生产中使用的 docker 部署,请不要使用这种方法

接下来要自定义 postgres 图像以创建不同的数据库,请遵循以下图像文档

如何扩展此图像

如果您想在从该镜像派生的镜像中进行额外的初始化,请在 /docker-entrypoint-initdb.d 下添加一个或多个 *.sql、*.sql.gz 或 *.sh 脚本(创建必要时目录)。在入口点调用 initdb 创建默认的 postgres 用户和数据库后,它将运行任何 *.sql 文件并获取该目录中找到的任何 *.sh 脚本,以在启动服务之前进行进一步的初始化。

例如,要添加额外的用户和数据库,请将以下内容添加到 /docker-entrypoint-initdb.d/init-user-db.sh:

#!/bin/bash
set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
    CREATE USER docker;
    CREATE DATABASE docker;
    GRANT ALL PRIVILEGES ON DATABASE docker TO docker;
EOSQL

更多详情请参考https://hub.docker.com/_/postgres/

【讨论】:

【参考方案2】:

您的host 不必在不同的环境中更改。它应该被分配给您的 pgsql 服务的名称,如您在 docker-compose.yaml 中定义的那样,在这种情况下,它是 postgres

也就是说,如果您希望不必在 database.json 文件中硬编码任何特定于环境的参数,您可以将它们拆分为不同的 database.json 文件,并使用其他环境扩展您的 docker-compose.yml - 特定的撰写文件。

例如,您可以将database.json 拆分为db-dev.jsondb-staging.jsondb-prod.json

然后您定义特定环境的 Compose 文件以挂载不同的文件。例如,

# dbconfig-dev.yml
services:
  server:
      volumes:    
        - ./config/db-dev.json:/app/

# dbconfig-staging.yml
services:
  server:
      volumes:    
        - ./config/db-staging.json:/app/

# dbconfig-prod.yml
services:
  server:
      volumes:    
        - ./config/db-prod.json:/app/

请注意,这些 Compose 文件不是完整的 Compose 定义,因为它们仅包含相关的 volumes 片段。

然后您可以通过以下方式扩展您原来的docker-compose.yaml

$ docker-compose -f docker-compose.yaml -f dbconfig-dev.yaml up

您可以在 Compose docs 中阅读更多相关信息。

【讨论】:

以上是关于docker-compose ECONNREFUSED 用于 nodeJS 上的 Postgres的主要内容,如果未能解决你的问题,请参考以下文章

Docker-compose容器

Docker-compose容器

Docker-compose容器

docker-compose.yml文件

Docker-Compose介绍,安装和使用

“docker-compose”命令为 docker-compose.yml 文件设置路径