To do this, you need to start the container like with a shell and without the postgresql server process starting as pid=1, which is how the container normally works. It seems like you are trapped: you can't stop the postgresql server without killing the container.
You need the database volume because roles are stored with the database. So you also need to discover how the database volume is mounted to your container (it may be obvious if you have a named volume, but I use ansible for deployment, so I don't have a named volume.)
So with the docker container running normally (my container when running normally is named django_api_sync_db and the postgres image is postgres:10
The owner user which lost superuser role due to bad ansible copy and paste is django_api_sync_db)
docker inspect django_api_sync_db
and search for the Mounts section.
In my case, I see a bind mount:
"Mounts": [
{
"Type": "bind",
"Source": "/var/docker/django_api_sync/db",
"Destination": "/var/lib/postgresql/data",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
}
],
stop the container, and then restart it with an interactive shell like this (in my case with postgresql v 10):
docker run --mount type=bind,source="/var/docker/django_api_sync/db",target="/var/lib/postgresql/data" -it postgres:10 /bin/bash
now, postgresql is not running. If curious, do
apt-get update && apt-get install -y procps
and
ps -ef
(aside: The default entry point of the postgres image means the postgresql server is pid 1, so you can't go into single user mode without immediately terminating the container.)
Since we are now in the container, discover the directory with the binaries.
Note: we are root.
# which postgres
my output is: /usr/lib/postgresql/10/bin/postgres
Change user and go into postgres single user mode:
su postgres
/usr/lib/postgresql/10/bin/postgres --single -D /var/lib/postgresql/data
and from the backend:
backend> alter user django_api_sync with superuser;
You are finished. Exit and do whatever you need to do to get the database container running normally again (e.g. systemctl restart docker)