I'm running the command:
docker exec -it db psql --user $(< postgres_user.txt)
and I'm getting the error:
/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "my_postgres_user" does not exist
This is my compose.yaml file:
services:
db:
container_name: db
image: postgres:16
environment:
POSTGRES_USER_FILE: /run/secrets/postgres_user
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
POSTGRES_DB_FILE: /run/secrets/postgres_db
secrets:
- postgres_user
- postgres_password
- postgres_db
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
secrets:
postgres_user:
file: postgres_user.txt
postgres_password:
file: postgres_password.txt
postgres_db:
file: postgres_db.txt
volumes:
pgdata: {}
The secrets files are in the same directory as the compose.yaml file. Their contents each look like this postgres_user.txt
file (with no additional spaces or newline characters):
my_postgres_user
The example for secrets in the Docker docs looks like this:
services:
db:
image: mysql:latest
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: db_password.txt
db_root_password:
file: db_root_password.txt
volumes:
db_data:
and in the Docker Postgres docs, there is this example using secrets:
docker run --name some-postgres -e POSTGRES_PASSWORD_FILE=/run/secrets/postgres-passwd -d postgres
but this is a run command and password secret and things don't seem to translate (i.e. using the -e flag) when using an exec command needing a user secret.
I've tried both having the secrets files as the are now, in the same directory as the compose.yaml as well as in a /secrets
directory, e.g. /secrets/postgres_user.text
and ./secrets/postgres_user.txt
, but the result is the same.
Looking at Inspect in Docker Desktop, I see this:
"Config": {
"Hostname": "c974321g8365",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"ExposedPorts": {
"5432/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"POSTGRES_USER_FILE=/run/secrets/postgres_user",
"POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password",
"POSTGRES_DB_FILE=/run/secrets/postgres_db",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/16/bin",
"GOSU_VERSION=1.17",
"LANG=en_US.utf8",
"PG_MAJOR=16",
"PG_VERSION=16.2-1.pgdg120+2",
"PGDATA=/var/lib/postgresql/data"
],
where User
is blank, although I don't know if that represents the problem, i.e. if it should be "User": "my_postgres_user",
.
All three secrets files are listed under Mounts
in Inspect and since the error message uses my_postgres_user
which is from the secrets file postgres_user.txt
, it seems clear it is finding the file. I just can determine why the role isn't being created.
@jjanes pointed out in a comment that the error was saying the "database" doesn't exist, not the "role", which I had overlooked. So I added the secrets file for the database after the user and it worked. The command I ended up with is:
docker exec -it db psql -U $(< postgres_user.txt) $(< postgres_db.txt)
In this way, I should be able to utilize secrets for user, database, and password in place of environment variables.
Update:
If I want to keep my secrets file in a /secrets
directory in the project root directory, I change my compose.yaml file lower secrets section to this:
secrets:
postgres_user:
file: ./secrets/postgres_user.txt
postgres_password:
file: ./secrets/postgres_password.txt
postgres_db:
file: ./secrets/postgres_db.txt
and I change the docker exec
command as follows:
docker exec -it db psql -U $(< ./secrets/postgres_user.txt) $(< ./secrets/postgres_db.txt)
Update 2:
For anyone curious, looking at the Docker Desktop "Inspect" again now that it is working, "Config"
still shows "User": "",
.