Skip to main content

[SOLVED] ECONNREFUSED for Postgres on nodeJS with dockers - docker

[SOLVED] Resolving ECONNREFUSED Errors for PostgreSQL on Node.js with Docker

In this chapter, we talk about the common problem of ECONNREFUSED errors. This happens when we try to connect to a PostgreSQL database from a Node.js app that runs inside a Docker container. This error often means the connection was refused. It can happen due to different mistakes in our Docker setup or PostgreSQL settings. We will look at some simple solutions to help us fix this issue. This way, our Node.js app can connect to PostgreSQL in a Docker environment without problems.

Solutions We Will Discuss:

  • Solution 1: Check Docker Container Status
  • Solution 2: Verify PostgreSQL Connection Settings
  • Solution 3: Ensure Network Configuration in Docker Compose
  • Solution 4: Set Proper Environment Variables
  • Solution 5: Increase Connection Timeout
  • Solution 6: Use Docker Health Checks

By following these steps, we can reduce the ECONNREFUSED error. This will help our Node.js app connect better with the PostgreSQL database. If we want to learn more about connecting to PostgreSQL in Docker or fixing Docker containers, this article will give us good information. Let’s go into each solution to understand it better.

Solution 1 - Check Docker Container Status

To fix the ECONNREFUSED error when we try to connect to PostgreSQL from a Node.js app in Docker, we should first check if our Docker containers are running. If our PostgreSQL container is not running or it crashed, then the connection will be refused.

Steps to Check Docker Container Status:

  1. List Running Containers: We can use this command to see the status of our Docker containers:

    docker ps

    This command shows all containers that are running now. We need to find our PostgreSQL container in the list. If it is not there, it means it is not running or has stopped.

  2. Check All Containers: If we want to see all containers, even the stopped ones, we use:

    docker ps -a

    This shows us the status of all containers. If our PostgreSQL container is stopped, we should note the exit code. This code can help us understand why it stopped.

  3. Inspect Container Logs: If our PostgreSQL container is not running, we can check the logs to find issues. We need to replace your_postgres_container_name with the real name or ID of our PostgreSQL container:

    docker logs your_postgres_container_name

    We should look for error messages or signs of what went wrong. Common problems can be configuration errors, lack of resources, or missing things we need.

  4. Restart the Container: If we see that the PostgreSQL container is stopped or crashed, we can try to restart it:

    docker start your_postgres_container_name

    After we restart, we should check the status again with docker ps.

  5. Check Health Status: If we set up health checks in our Docker, we need to make sure they are passing. We can check the health status by looking at the container:

    docker inspect --format='{{json .State.Health}}' your_postgres_container_name

    If the health check is not passing, we might need to change the health check settings or fix the PostgreSQL setup.

By doing these steps to check the Docker container status, we can find out if the PostgreSQL container is working well. If it is not, we need to fix the issues from the logs to solve the ECONNREFUSED error. For more help on troubleshooting Docker containers, we can look at how to get into Docker.

Solution 2 - Verify PostgreSQL Connection Settings

To fix the ECONNREFUSED error when we connect to PostgreSQL from a Node.js app in a Docker container, we need to check our PostgreSQL connection settings. Often, wrong settings cause these connection problems.

1. Check Connection Parameters

First, we must make sure our database connection settings are right. Look at these details in our Node.js app:

  • Host: Make sure we use the correct hostname or IP address. If PostgreSQL runs in another container, we should use the service name from our docker-compose.yml file.

  • Port: The default port for PostgreSQL is 5432. We need to check that this matches the port in our PostgreSQL container.

  • User: Confirm that the username we use exists and has the correct permissions.

  • Password: Make sure the password is right.

  • Database Name: We should check that the database name in our connection string is correct and exists.

Here is an example of a connection string with the pg library in Node.js:

const { Client } = require("pg");

const client = new Client({
  user: "your_username",
  host: "postgres_service", // Use the service name we define in docker-compose
  database: "your_database",
  password: "your_password",
  port: 5432,
});

client
  .connect()
  .then(() => console.log("Connected to PostgreSQL"))
  .catch((err) => console.error("Connection error", err.stack));

2. Docker Compose Example

If we use Docker Compose, we need to make sure our docker-compose.yml file is set up correctly. Here is a simple example:

version: "3.8"
services:
  postgres:
    image: postgres:latest
    environment:
      POSTGRES_USER: your_username
      POSTGRES_PASSWORD: your_password
      POSTGRES_DB: your_database
    ports:
      - "5432:5432"

  app:
    build: .
    depends_on:
      - postgres
    environment:
      DB_CONNECTION_STRING: postgres://your_username:your_password@postgres:5432/your_database

3. Test Connection from the Application

To check if our app can connect to PostgreSQL, we can run a simple test command in our Node.js app. Here is how we do it:

client.query("SELECT NOW()", (err, res) => {
  if (err) {
    console.error("Error executing query", err.stack);
  } else {
    console.log("Current timestamp:", res.rows[0]);
  }
  client.end();
});

4. Verify PostgreSQL Logs

If the connection problems still happen, we should check the PostgreSQL logs for error messages. We can see the logs by running:

docker logs <postgres_container_name>

We need to look for any authentication errors or connection refusals. These may show us that something is wrong with our settings.

For more help, we can look at this guide on connecting to PostgreSQL in Docker to make sure our setup is correct.

Solution 3 - Ensure Network Configuration in Docker Compose

When we see the ECONNREFUSED error while trying to connect to PostgreSQL in a Node.js app running in Docker, we need to check the network setup in our Docker Compose. Good networking lets our Node.js service talk to the PostgreSQL database container.

Step 1: Define a Network in Docker Compose

First, we have to make sure that our Node.js and PostgreSQL services use the same network. We can create a custom bridge network in our docker-compose.yml file like this:

version: "3.8"

services:
  postgres:
    image: postgres:latest
    restart: always
    environment:
      POSTGRES_USER: exampleuser
      POSTGRES_PASSWORD: examplepass
      POSTGRES_DB: exampledb
    networks:
      - mynetwork

  nodejs:
    build: .
    restart: always
    depends_on:
      - postgres
    networks:
      - mynetwork

networks:
  mynetwork:
    driver: bridge

In this example, both the nodejs service and the postgres service connect to the mynetwork network. This setup helps them to communicate using their service names as hostnames.

Step 2: Use the Correct Hostname

In our Node.js application, we need to make sure we use the right hostname to connect to the PostgreSQL database. We should use the service name from our Docker Compose file:

const { Pool } = require("pg");

const pool = new Pool({
  user: "exampleuser",
  host: "postgres", // Use the service name here
  database: "exampledb",
  password: "examplepass",
  port: 5432,
});

pool
  .connect()
  .then(() => console.log("Connected to PostgreSQL"))
  .catch((err) => console.error("Connection error", err.stack));

Step 3: Check Network Connectivity

To check if our Node.js container can reach the PostgreSQL container, we can run a shell command inside the Node.js container to ping the PostgreSQL service:

  1. First, we get into our Node.js container:

    docker-compose exec nodejs /bin/sh
  2. Then, inside the container, we ping the PostgreSQL service:

    ping postgres

If the ping works, it means our network setup is correct.

Step 4: Inspect Network Configuration

We can check the network settings to make sure both containers are in the same network:

docker network inspect mynetwork

This command shows us the containers that are connected to the network. We can confirm that both our Node.js and PostgreSQL containers are in the list.

By checking and setting the network settings right in our Docker Compose file, we can fix the ECONNREFUSED error when connecting to PostgreSQL from our Node.js application. For more details on connecting to PostgreSQL in Docker, we can look at this guide on connecting to PostgreSQL in Docker.

Solution 4 - Set Proper Environment Variables

Setting the right environment variables is very important when we want to connect a Node.js application to a PostgreSQL database in a Docker container. If we get these variables wrong, we may see the ECONNREFUSED error. Let’s follow the steps below to set the environment variables correctly.

Step 1: Define Environment Variables

The environment variables for PostgreSQL usually include the database name, user, password, host, and port. We can define these variables in our Docker Compose file or use a .env file. Here is an example of how to set them in our docker-compose.yml:

version: "3"

services:
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: yourusername
      POSTGRES_PASSWORD: yourpassword
      POSTGRES_DB: yourdatabase
    ports:
      - "5432:5432"

  app:
    image: your-nodejs-app
    environment:
      DATABASE_URL: postgres://yourusername:yourpassword@db:5432/yourdatabase
    depends_on:
      - db
    ports:
      - "3000:3000"

Step 2: Use a .env File (Optional)

If we want to keep sensitive information away from our docker-compose.yml, we can use a .env file. We create a file named .env in the same place as our docker-compose.yml:

POSTGRES_USER=yourusername
POSTGRES_PASSWORD=yourpassword
POSTGRES_DB=yourdatabase
DATABASE_URL=postgres://yourusername:yourpassword@db:5432/yourdatabase

Next, we reference these variables in our docker-compose.yml:

version: "3"

services:
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    ports:
      - "5432:5432"

  app:
    image: your-nodejs-app
    environment:
      DATABASE_URL: ${DATABASE_URL}
    depends_on:
      - db
    ports:
      - "3000:3000"

Step 3: Access Environment Variables in Node.js

In our Node.js application, we can access the environment variables using process.env. Here is an example of how to connect to PostgreSQL using the pg library:

const { Pool } = require("pg");

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

pool
  .connect()
  .then(() => console.log("Connected to PostgreSQL"))
  .catch((err) => console.error("Connection error", err.stack));

Step 4: Verify Environment Configuration

To check that our Node.js application is using the correct environment variables, we can log them:

console.log("Database URL:", process.env.DATABASE_URL);

This will help us see if the application is using the right values.

Additional Tips

  • We should restart our Docker containers after changing the docker-compose.yml or .env file. We do this using docker-compose down and then docker-compose up -d.
  • For more information on connecting to PostgreSQL in Docker, we can check this guide.
  • Always make sure our database service is running before starting the application to avoid any connection problems.

By following these steps, we can set proper environment variables for our Node.js application that connects to a PostgreSQL database in Docker. This will help us fix the ECONNREFUSED error.

Solution 5 - Increase Connection Timeout

When we see the ECONNREFUSED error while connecting to PostgreSQL from a Node.js app in Docker, one way to fix this is to increase the connection timeout settings. The default timeout might be too low. This is common in containerized setups where services may take longer to start.

Step-by-Step Guide to Increase Connection Timeout

  1. Change Connection String: If we use a connection string to connect to PostgreSQL, we can add a timeout parameter in the string. The parameter we need is connect_timeout. Here is an example:

    const { Client } = require("pg");
    
    const client = new Client({
      connectionString:
        "postgres://username:password@postgres_container:5432/mydatabase?connect_timeout=30",
    });
    
    client
      .connect()
      .then(() => console.log("Connected successfully"))
      .catch((e) => console.error("Connection error", e.stack));

    In this case, the connection timeout is set to 30 seconds. We can change this value as needed.

  2. Using Environment Variables: If we manage our database settings with environment variables, we should add the connect_timeout parameter in our connection string. For example, if we have a variable for our database URL, we can change it like this:

    export DATABASE_URL='postgres://username:password@postgres_container:5432/mydatabase?connect_timeout=30'

    In our Node.js app, we can get the variable like this:

    const { Client } = require("pg");
    
    const client = new Client({
      connectionString: process.env.DATABASE_URL,
    });
    
    client
      .connect()
      .then(() => console.log("Connected successfully"))
      .catch((e) => console.error("Connection error", e.stack));
  3. Check Sequelize Settings (if we use it): If we use an ORM like Sequelize, we can increase the connection timeout in its settings like below:

    const { Sequelize } = require("sequelize");
    
    const sequelize = new Sequelize("mydatabase", "username", "password", {
      host: "postgres_container",
      dialect: "postgres",
      dialectOptions: {
        connectTimeout: 30000, // Timeout in milliseconds
      },
    });
    
    sequelize
      .authenticate()
      .then(() => console.log("Connection has been established successfully."))
      .catch((err) => console.error("Unable to connect to the database:", err));
  4. Docker-Compose Settings: In our Docker Compose file, we should make sure that the PostgreSQL service has enough time to start before our Node.js app tries to connect. We can do this by adding a depends_on condition with a health check. Here is an example:

    version: "3.8"
    services:
      postgres:
        image: postgres:latest
        environment:
          POSTGRES_USER: username
          POSTGRES_PASSWORD: password
          POSTGRES_DB: mydatabase
        healthcheck:
          test: ["CMD", "pg_isready", "-U", "username"]
          interval: 10s
          timeout: 5s
          retries: 5
    
      app:
        build: .
        depends_on:
          postgres:
            condition: service_healthy

    This setup checks if PostgreSQL is ready before the Node.js app tries to connect. This helps reduce the chance of seeing ECONNREFUSED.

By using these methods, we can increase the connection timeout and lower the chances of getting the ECONNREFUSED error in our Node.js app when connecting to PostgreSQL in Docker. For more info on connecting to PostgreSQL in Docker, we can check this link.

Solution 6 - Use Docker Health Checks

We need to make sure that our PostgreSQL container is running well and ready to accept connections. Using Docker health checks is very important. Health checks can help us avoid connection errors like ECONNREFUSED. They make sure our application only tries to connect to the database when it is fully working.

Implementing Docker Health Checks

We can define a health check in our Dockerfile or in our docker-compose.yml file. Here are examples for both setups.

Using Dockerfile

To set the health check in a Dockerfile, we can use this command:

FROM postgres:latest

# Other Dockerfile instructions...

HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD pg_isready -U your_username -h localhost || exit 1

In this example:

  • pg_isready checks if PostgreSQL is accepting connections.
  • -U your_username means the user we want to connect as.
  • --interval=30s shows how often we run the health check.
  • --timeout=10s sets the maximum time for the check.
  • --retries=5 tells how many failures we can have before the container is unhealthy.

Using Docker Compose

If we use docker-compose.yml, we can set the health check like this:

version: "3.8"

services:
  postgres:
    image: postgres:latest
    environment:
      POSTGRES_USER: your_username
      POSTGRES_PASSWORD: your_password
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "your_username", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 5

In this setup:

  • The healthcheck section lets us define the command for the health check.
  • It uses the same settings as in the Dockerfile example, keeping it simple.

Benefits of Health Checks

  • Prevents Connection Errors: By making sure the PostgreSQL server is ready before our Node.js app connects, we lower the chance of getting ECONNREFUSED errors.
  • Improved Reliability: Health checks help keep our app reliable. Docker can restart containers that are not healthy.
  • Monitoring and Logging: Health checks give us information about our containers. This is useful for monitoring and fixing problems.

Conclusion

Using Docker health checks is a good practice when we work with containers. It is especially helpful when we connect services like PostgreSQL with Node.js applications. For more details on connecting to PostgreSQL in Docker, check this guide. Adding these checks will make our application’s stability and performance much better.

Conclusion

In this article, we looked at the common problem of ECONNREFUSED for PostgreSQL on Node.js when using Docker. We shared different solutions. We checked the Docker container status. We verified connection settings. We made sure the network setup is correct.

Using these solutions can really help improve our Docker setup and PostgreSQL connection. For more information, we can check out our guide on connecting to PostgreSQL in Docker. We can also learn how to get into Docker.

Comments