Installing a specific version of PostgreSQL in your Dockerfile
It happened to me again today, pg_dump: error: aborting because of server version mismatch
.
It is an error I know well. I know the reason and I know the remedy, but the specific steps
aren’t something that sticks in my memory so I’m writing this for future me to consume as
much as anything.
I run into this mostly with Python based projects, typically using the official Python Docker images which are Debian based.
The reason
The reason is that you have installed say version 15 or 17 of PostgreSQL in your Docker container, but are communicating with a server that is running 16.x.
The psql
tool is more forgiving and can often operate just fine with several major versions of
drift, but pg_dump
is another story.
The remedy
The remedy is simple enough, install the right version in your Docker container. Easy, right?
Well sort of. It’s possible to do for sure, but the steps are a little more complicated than your average issue.
To be clear, we’re not trying to run PostgreSQL as a server process here. If you’re wanting to do that you should run the official PostgreSQL docker image for the version you want.
What we are trying to do is install specific versions of the PostgreSQL client tools that are compatible with PostgreSQL running somewhere remotely.
The fix
The steps to do this are pretty straight forward.
- Install some tools we need such as curl, gnupg2, lsb-release, etc.
- Create a new apt repository in
/etc/apt/sources.list.d/
specific to the PGDG (PostgreSQL Development Group) - Download and trust the PostgreSQL team’s GPG key
- apt install the version you want.
Here are the details:
FROM python:3.12-slim
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt \
apt update && \
apt install --no-install-recommends -y libpq-dev curl gnupg2 lsb-release apt-transport-https ca-certificates
# Add the PGDG apt repo
RUN echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
# Trust the PGDG gpg key
RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc| gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt \
apt update \
&& apt -y install postgresql-16 \
&& rm -rf /var/lib/apt/lists/*
Two things that might be confusing to you are the use of --mount-type=cache
which is just
a fancy way to cache apt package downloads so rebuilding locally is faster and the use of lsb_release -cs
.
The output for lsb_release -cs
in this python 3.12 image is bookworm
which makes the second command
add the text:
deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main
to the file. You could chose to hard code this instead and skip using lsb_release
but I find this
easier and more portable across Python versions which often use different Debian versions.
Frank Wiles
Founder of REVSYS and former President of the Django Software Foundation . Expert in building, scaling and maintaining complex web applications. Want to reach out? Contact me here or use the social links below.