I had a set of services built with Docker Compose. In this set, I had a PostgreSQL service coupled with a PgBouncer instance that pooled requests from the other services of my application to the database. The PostgreSQL was at version 13 and I wanted to upgrade to the next version, at the time of this writing, 14.

The Docker Compose service settings initially looked like this:

db:
    image: postgres:13-alpine
    volumes:
      - pg_data:/var/lib/postgresql/data/
    env_file:
      - ./.env
    networks:
      - app-network

  pgb:
    image: edoburu/pgbouncer:1.15.0
    depends_on:
      - db
    networks:
      - app-network
    env_file:
      - ./.env
...
    

The next version tag for the db service was 14-alpine. So I changed the docker-compose.yml respectively:

db:
    image: postgres:14-alpine
    volumes:
      - pg_data:/var/lib/postgresql/data/
    env_file:
      - ./.env
    networks:
      - app-network
...

Once the new configuration is applied and the services are re-built and restarted I get the following error message:

FATAL:  database files are incompatible with server
DETAIL:  The data directory was initialized by PostgreSQL version 13, which is not compatible with this version 14

The solution was to remove the database volume pg_data, re-build the service, and restore the database backup.

The next problem, I encountered was the incompatibility of the authentication method. The PgBouncer service I was running used md5 and I had these errors from the pgb service:

 ERROR: srv/username@181.55.0.2:5432 cannot do SCRAM authentication: wrong password type
 LOG: srv/username@181.55.0.1:53604 closing because: server login failed: wrong password type (age=0s)
 WARNING: srv/username@181.55.0.1:53604 pooler error: server login failed: wrong password type

My solution was to change the authentication method on the PostgreSQL side, in my service db. To do that I needed to set the server setting password_encryption to md5. This can be done by adding the command line to the service settings in the file docker-compose.yaml:

  db:
    image: postgres:14-alpine
    volumes:
      - pg_data:/var/lib/postgresql/data/
    env_file:
      - ./.env
    command: postgres -c password_encryption=md5

Next, I needed the db service to use a custom file pg_hba.conf. In the project root, I created a copy of the original pg_hba.conf and modified the last line to use trust as METHOD. Originally the line looked like this:

...
#line to modify
host all all all md5

After the modification the same line:

#line to modify
host all all all trust

Finally, I mount the custom file as a volume to the service and tell PostgreSQL to use it instead of the default pg_hba.conf file:

db:
  image: postgres:14-alpine
  volumes:
    - pg_data:/var/lib/postgresql/data/
    - ./compose/local/db/:/var/lib/postgresql/custom/
  env_file:
    - ./.env
  command: postgres -c password_encryption=md5 -c hba_file=/var/lib/postgresql/custom/pg_hba.conf

The command section is in one line, with no line breaks.

I recreated the db container and the PgBouncer pooling service was now able to connect to the database.


1 Comment

Sven · November 15, 2022 at 4:46 pm

It would be nice to warn readers that this works for quick hack only:
– downgrading password encryption from pg14 default scram-sha-256 to md5. New default was selected in PG14 because it was considered as insecure
– host all all all trust – this opens up db for whole world without database

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *