skip to Main Content

I have a Postgres database running in a Docker container and a Python application running in another Docker container. When I try to connect to the Postgres database from the Python app using SQLAlchemy, I get the following error:

sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 5432?

I have checked that the Postgres container is running and I can connect to it from my host machine using DBeaver. However, when I try to connect from the Python app container, I get the above error.

this is the Postgres set up in docker compose


version: "3.7"
services:
  postgresql_database:
    container_name: postgresql_database
    image: postgres:13.8
    environment:
      POSTGRES_HOST: localhost
      POSTGRES_PASSWORD: MyPassword
      POSTGRES_USER: MyUsername
      POSTGRES_DB: "MyDatabase"
    volumes:
      - source: ../configs/postgresql
        target: /docker-entrypoint-initdb.d/
        type: bind
    networks:
      - default
      - app_network
    healthcheck:
      test:
        [
          "CMD",
          "pg_isready",
          "-q",
          "-U",
          "MyUsername",
          "-d",
          "MyDatabase"
        ]
      interval: 5s
      timeout: 1s
      retries: 2
    restart: unless-stopped


the ../configs/postgresql directory has all database sql scripts

This is the python setup


version: "3.7"
services:
  flask_app:
    image: https://not_allowed_to_share/flask_app:latest
    container_name: flask_app
    volumes:
      - source: ../configs/flask_app/config.yaml
        target: /config/config.yaml
        type: bind
    environment:
      CONTENT_CONNECTIONSTRING: DRIVER={PostgreSQL Unicode};SERVER=localhost;Port=5432;UID=MyUsername;PWD=MyPassword;Connect Timeout=5;DATABASE=MyDatabase;
      CONTENT_DBTYPE: postgresql_odbc
    networks:
      - app_network
    depends_on:
      - "postgresql_database"

    restart: "no"

The ../configs/flask_app/config.yaml contains configuration such as the connection string, is debug mode, etc

This is the connection string
DRIVER={PostgreSQL Unicode};SERVER=localhost;Port=5432;UID=MyUsername;PWD=MyPassword;Connect Timeout=5;DATABASE=MyDatabase;

I have also tried replacing ‘localhost’ with the name of the Postgres service but still get the same error.

How can I fix this issue and connect to the Postgres database from my Python app running in a Docker container?

2

Answers


  1. The "localhost" of your python container, and the "localhost" of the postgres container are not the same.

    Ways to fix this:

    • I don’t perfectly remember how DNS works in a docker network, but it might be possible to use the hostname "postgresql_database" in the connection string of your python container
    • alternatively, you can define fixed ip addresses and use those in the connection string instead. See networks
    • tunnel the postgres port with a SSH tunnel (this is the bandaid workaround)
    Login or Signup to reply.
  2. When you start two Docker compose deployments, both of them will have a different network, even if you name it app_network in each of them, like in your example.

    Start both deployments and then check your networks with docker network list. You should see two different networks.

    I’d suggest to put both services inside the same docker-compose.yml, as database and app belong together. This will start them together and they will be on the same network.

    In the flask_app service you can then set the name of the database service instead of localhost. localhost would be the flask_app Docker container itself, but the database runs in a different container.

    So in CONTENT_CONNECTIONSTRING you should use host name postgresql_database instead of localhost.

    If you really want to use two different Docker compose files, you need to mark networks as external. This way it will not create two different networks but use an existing one.

    1. Create the network with docker network create app_network.

    2. Then in both Docker compose files, set the network as you already did:

        services:
          [service_name]:
             networks:
               - app_network
      
    3. And at the end of the Docker compose files, define app_network as external network:

      networks:
        app_network:
          external: true
          name: app_network
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search