skip to Main Content

I’m trying to attach a db to my python API. I use Windows 11, docker-compose, fastAPI.
Not sure what is missing.
In the logs I see the following:

docker-compose logs -f
time="2024-05-17T16:01:30+04:00" level=warning msg="\code\docker-compose.yml: `version` is obsolete"
postgres-1  |
postgres-1  | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-1  |
postgres-1  | 2024-05-17 12:01:15.238 UTC [1] LOG:  starting PostgreSQL 16.3 (Debian 16.3-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
postgres-1  | 2024-05-17 12:01:15.241 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres-1  | 2024-05-17 12:01:15.241 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres-1  | 2024-05-17 12:01:15.407 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-1  | 2024-05-17 12:01:15.791 UTC [31] LOG:  database system was shut down at 2024-05-17 11:54:26 UTC
postgres-1  | 2024-05-17 12:01:16.170 UTC [1] LOG:  database system is ready to accept connections
fastapi-1   | main folder created at: /app
fastapi-1   | files folder created at: /app/pickle_files
fastapi-1   | pdfs folder created at: /app/test_upload_pdfs
fastapi-1   | persist folder created at: /app/vector_db_for_sim/chroma
fastapi-1   | cwd folder created at: /app/load_and_qa
fastapi-1   | Traceback (most recent call last):
fastapi-1   |   File "/usr/local/lib/python3.9/site-packages/tenacity/__init__.py", line 470, in __call__
fastapi-1   |     result = fn(*args, **kwargs)
fastapi-1   |   File "/app/load_and_qa/config.py", line 69, in connect_to_postgres
fastapi-1   |     raise e
fastapi-1   |   File "/app/load_and_qa/config.py", line 60, in connect_to_postgres
fastapi-1   |     conn = psycopg2.connect(
fastapi-1   |   File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 122, in connect
fastapi-1   |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
fastapi-1   | psycopg2.OperationalError: connection to server at "172.29.0.2", port 5432 failed: Connection refused

Here’s the Dockerfile:

# Use an appropriate base image
FROM python:3.9

COPY ./load_and_qa/requirements.txt /app/requirements.txt

RUN pip install --no-cache-dir  -r /app/requirements.txt

# Install SQLite3 version 3.35.0 or higher
RUN pip install pysqlite3-binary
RUN pip install python-dotenv

WORKDIR /app
COPY ./user_simulation_data /app/user_simulation_data
COPY ./vector_db_for_sim /app/vector_db_for_sim
COPY ./pickle_files /app/pickle_files
COPY ./test_upload_pdfs /app/test_upload_pdfs

COPY ./load_and_qa /app/load_and_qa

CMD ["python", "./load_and_qa/config.py"]

# Expose the port your application runs on
EXPOSE 8000

# Wait for PostgreSQL to be ready
CMD ["sh", "-c", "sleep 10 && cd ./load_and_qa && uvicorn app_fastapi:app --host 0.0.0.0 --port 8000"]

The docker-compose.yml:

version: '3.8'

services:
  fastapi:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - ./load_and_qa:/app/load_and_qa
    depends_on:
      postgres:
        condition: service_healthy
    links:
      - postgres:postgres_db
    networks:
      - my_network
    environment:
      SQLALCHEMY_DATABASE_URL: postgresql://myuser:mypassword@postgres:5432/my_db

  postgres:
    image: postgres:latest
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: my_db
      POSTGRES_INITDB_ARGS: "-EnableNextPgSocket"
    networks:
      - my_network
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
      - ./create-db.sql:/docker-entrypoint-initdb.d/create_database.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myuser"]
      interval: 10s
      timeout: 5s
      retries: 5


networks:
  my_network:

I try to connect to the db in config.py as follows:

load_dotenv()

DB_USER = os.environ.get("POSTGRES_USER")
DB_PASSWORD = os.environ.get("POSTGRES_PASSWORD")
DB_NAME = os.environ.get("POSTGRES_DB")
DB_HOST = "172.29.0.2"
# DB_HOST = os.environ.get("POSTGRES_HOST")



@retry(
    stop=stop_after_delay(120),  # Stop retrying after 30 seconds
    wait=wait_fixed(1)  # Wait 1 second between retries
)
def connect_to_postgres():
    try:
        conn = psycopg2.connect(
            dbname=DB_NAME,
            user=DB_USER,
            password=DB_PASSWORD,
            host=DB_HOST
        )
        return conn
    except psycopg2.OperationalError as e:
        # Raise an exception to trigger a retry
        raise e

conn = connect_to_postgres()
db_cursor = conn.cursor()

Then I import db_cursor in app_fastapi.py and try to register users and their data in the database.

Permissions are fine
postgresql.conf is fine

2

Answers


  1. I’m guessing you’re getting that IP from docker inspect ... but that’s brittle (as I suspect you’re experiencing) and you should be able to communicate with the container using its Compose service name (postgres) via Compose’s networking stack. If you changed the name of the Postgres Compose service to database-server, you’d be able to use that instead.

    From the docs:

    By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by the service’s name.

    For instance, I’m able to communicate between services when using a simplified version of your Compose config and a contrived startup script which installs psql and tries to connect to the DB using postgres as the hostname:

    docker-compose.yml

    version: '3.8'
    
    services:
      ubuntu:
        image: ubuntu:latest
        links:
          - postgres
        ports:
          - "8000:8000"
        networks:
          - my_network
        command: ["/scripts/start.sh"]
        entrypoint: "/bin/sh"
        volumes:
          - ./start.sh:/scripts/start.sh
    
      postgres:
        image: postgres:latest
        ports:
          - "5432:5432"
        environment:
          POSTGRES_USER: myuser
          POSTGRES_PASSWORD: mypassword
          POSTGRES_DB: my_db
          POSTGRES_INITDB_ARGS: "-EnableNextPgSocket"
        networks:
          - my_network
    
    networks:
      my_network:
    

    start.sh

    sleep 5
    apt-get update
    apt-get install -y postgresql-client
    PGPASSWORD=mypassword psql -h postgres -U myuser # won't work but you'll see an error in the PG logs
    

    enter image description here

    Login or Signup to reply.
  2. think the db URL is wrong. it should look like this

    and I added the extra host to make sure the db is visible to all your containers.

    jdbc:postgresql://myuser:mypassword@postgres:5432/my_db
    

    try with this docker file

    version: '3.8'
    
    services:
      fastapi:
        build: .
        ports:
          - "8000:8000"
        volumes:
          - ./load_and_qa:/app/load_and_qa
        depends_on:
          postgres:
            condition: service_healthy
        links:
          - postgres:postgres_db
        networks:
          - my_network
        environment:
          SQLALCHEMY_DATABASE_URL: jdbc:postgresql://postgres:5432/my_db?user=myuser&password=mypassword
    
      postgres:
        image: postgres:14-alpine
        ports:
          - "5432:5432"
        extra_hosts:
          - "host.docker.internal:host-gateway"
        volumes:
          - ~/apps/postgres:/var/lib/postgresql/data
        environment:
          - POSTGRES_PASSWORD=mypassword
          - POSTGRES_USER=myuser
          - POSTGRES_DB=my_db
        networks:
          - my_network
    
    
    networks:
      my_network:
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search