如何在docker中确定postgres数据库的正确连接参数

问题描述 投票:0回答:1

我正在学习 docker 并尝试将节点应用程序与 Postgres 数据库连接。但是当我启动容器时,我无法解决以下错误:

enter image description here

注意:添加 Hans Killian 建议的健康检查部分后出现更新错误。

enter image description here 我已经知道问题出在与 Postgres 的连接上。问题是我不明白应该使用哪些参数或如何获取它们。这就是我的困惑。我一直在关注几个教程,所有这些教程,即使它们提供了丰富的信息,也会跳过这一部分,可能认为它太明显了。我尝试了几种组合(通常的 localhost、0.0.0.0 等),但均无济于事。正如您所看到的,有两个图像,一个用于应用程序,另一个用于 Postgres,因此一个应用程序正在尝试连接到另一个应用程序。

接下来,我将列出所有我认为重要的细节。我会很感激你能给我的任何指导,任何“孩子,你必须看看这个地方”。

文件夹结构如下:

enter image description here

数据库Dockerfile如下:

FROM postgres:16-alpine
COPY 00-init.sql /docker-entrypoint-initdb.d/

来自服务器的 Dockerfile 如下:

FROM node:21

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 8080
CMD ["npm", "run", "dev"]

package.js如下:

{
  "name": "server",
  "version": "0.1.0",
  "description": "Backend",
  "main": "./src/server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node .",
    "dev": "nodemon ."
  },
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.21.0",
    "pg": "^8.13.0"
  },
  "devDependencies": {
    "nodemon": "^3.1.7"
  }
}

最后 docker-compose.yaml 如下:

services:
   database:
    image: postgres
    container_name: ${POSTGRES_HOST}
    build:
      context: ./database
      dockerfile: Dockerfile
    env_file: .env
    ports:
      - ${POSTGRES_PORT}:${POSTGRES_PORT}
    command: "-p ${POSTGRES_PORT}"
    volumes:
      - database-v:/var/lib/postgresql/data
  pgadmin:
    container_name: container-pgadmin
    image: dpage/pgadmin4
    depends_on:
       database:
        condition: service_started
    ports:
      - "5050:80"
    environment:
      PGADMIN_DEFAULT_EMAIL: [email protected]
      PGADMIN_DEFAULT_PASSWORD: root
    restart: unless-stopped
  server:
    image: server:1.0.0
    container_name: ${SERVER_HOST}
    build:
      context: ./server
      dockerfile: Dockerfile
    env_file: .env
    ports:
      - ${SERVER_PORT}:${SERVER_PORT}
    volumes:
      - server-v-node-modules:/server/node_modules
    depends_on:
      database:
        condition: service_started
  volumes:
    database-v:
      name: "database-v"
    server-v-node-modules:
      name: "server-v-node-modules"

包含环境变量的.env文件如下:

SERVER_HOST="server-c"
SERVER_PORT="3000"

POSTGRES_HOST="postgres-c"
POSTGRES_PORT="5432"
POSTGRES_USER="[email protected]"
POSTGRES_PASSWORD="root"
POSTGRES_DB="app-db"

以及 server/src 文件夹中的 server.js,以这种方式连接到数据库:

const express = require("express")
const app = express()
const bodyParser = require('body-parser')
const cors = require("cors")
const PORT = 3000;
        
const Pool = require('pg').Pool
const pool = new Pool({
  host: process.env.POSTGRES_HOST,
  port: process.env.POSTGRES_PORT,
  user: process.env.POSTGRES_USER,
  password: process.env.POSTGRES_PASSWORD,
  database: process.env.POSTGRES_DB
})
        
async function connectToDatabase() {
  const client = await pool.connect();
    try {
      const response = await client.query("SELECT * FROM users");
      const { rows } = response;
      console.log(rows)
    } catch(err){
      console.log(err)
    } finally {
      client.release();
    }
  }
       
app.listen(PORT, () => {
  console.log(`Vianni Server started on port ${PORT}`);
  connectToDatabase()
  .then(() => console.log("Connected to Postgres!"))
  .catch(err => console.error("Error connection to Postgres!", err));
});

最后我用来启动应用程序的命令是

docker compose up

另外,如果您发现任何其他错误或我可以改进的地方,如果您提到它,我将非常感激。

我最诚挚的问候。

postgresql docker docker-compose
1个回答
0
投票

这已经在评论中提到了,但是您遇到了依赖性问题:您的应用程序在数据库准备好接受连接之前尝试连接到数据库。您已声明以下依赖项:

    depends_on:
      database:
        condition: service_started

但这完全没用,因为只要 postgres 容器启动,条件就满足了;它不知道数据库是否准备好处理连接,因此您的依赖容器会在 postgres 准备好之前启动。

要纠正该问题,您需要:

  1. 向 postgres 容器添加运行状况检查以识别其何时准备就绪,并且
  2. 将您的依赖关系从
    service_started
    更改为
    service_healthy

健康检查应该看起来像这样:

    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5

依赖关系应该如下所示:

    depends_on:
      database:
        condition: service_healthy

完整的

compose.yaml
看起来像:

volumes:
  database-v:
    name: database-v
  server-v-node-modules:
    name: server-v-node-modules

services:
  database:
    image: postgres
    container_name: ${POSTGRES_HOST}
    build:
      context: ./database
      dockerfile: Dockerfile
    env_file: .env
    ports:
      - ${POSTGRES_PORT}:${POSTGRES_PORT}
    command: -p ${POSTGRES_PORT}
    volumes:
      - database-v:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
  pgadmin:
    container_name: container-pgadmin
    image: dpage/pgadmin4
    depends_on:
      database:
        condition: service_healthy
    ports:
      - 5050:80
    environment:
      PGADMIN_DEFAULT_EMAIL: [email protected]
      PGADMIN_DEFAULT_PASSWORD: root
    restart: unless-stopped
  server:
    image: server:1.0.0
    container_name: ${SERVER_HOST}
    build:
      context: ./server
      dockerfile: Dockerfile
    env_file: .env
    ports:
      - ${SERVER_PORT}:${SERVER_PORT}
    volumes:
      - server-v-node-modules:/server/node_modules
    depends_on:
      database:
        condition: service_healthy

运行

docker compose up
会导致您的应用程序成功连接到数据库:

$ docker compose up
.
.
.
postgres-c         | The files belonging to this database system will be owned by user "postgres".
postgres-c         | This user must also own the server process.
.
.
.
postgres-c         | 2024-10-11 14:08:51.080 UTC [1] LOG:  database system is ready to accept connections
server-c           |
server-c           | > [email protected] dev
server-c           | > nodemon .
.
.
.
server-c           | Connected to Postgres!
.
.
.
© www.soinside.com 2019 - 2024. All rights reserved.