The docker image needs the POSTGRES_PASSWORD
environment variable to create the database with a password.
node-postgres needs PGPASSWORD.
Both need to be the same password.
I am using .env.local to load the passwords and .env for common environment variables that don't need to be stored securely and can be included in the source code.
Contents of my .env file:
DB_USER=root
# DB_PASSWORD=<PASSWORD>
DB_DBNAME=qr_orders_db
PGUSER=${DB_USER}
PGPASSWORD=${DB_PASSWORD}
PGDATABASE=${DB_DBNAME}
POSTGRES_USER=${DB_USER}
POSTGRES_PASSWORD=${DB_PASSWORD}
POSTGRES_DB=${PGDATABASE}
Contents of my .env.local file:
DB_PASSWORD=root
My docker compose file:
services:
db:
image: postgres
env_file:
- .env
- .env.local
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
pgdata:
Output error when I run docker compose up
:
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
[+] Running 3/3
✔ Network qr_orders_default Created 0.1s
✔ Volume "qr_orders_pgdata" Created 0.0s
✔ Container qr_orders-db-1 Created 0.1s
Attaching to db-1
db-1 | Error: Database is uninitialized and superuser password is not specified.
db-1 | You must specify POSTGRES_PASSWORD to a non-empty value for the
db-1 | superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
db-1 |
db-1 | You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
db-1 | connections without a password. This is *not* recommended.
db-1 |
db-1 | See PostgreSQL documentation about "trust":
db-1 | https://www.postgresql.org/docs/current/auth-trust.html
db-1 exited with code 1
Why doesn't it work? If I put .env.local before .env in the compose yaml file I don't get the error message but the warning keeps appearing:
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
WARN[0000] The "DB_PASSWORD" variable is not set. Defaulting to a blank string.
[+] Running 3/3
✔ Network qr_orders_default Created 0.1s
✔ Volume "qr_orders_pgdata" Created 0.0s
✔ Container qr_orders-db-1 Created 0.1s
Attaching to db-1
db-1 | The files belonging to this database system will be owned by user "postgres".
db-1 | This user must also own the server process.
db-1 |
db-1 | The database cluster will be initialized with locale "en_US.utf8".
db-1 | The default database encoding has accordingly been set to "UTF8".
db-1 | The default text search configuration will be set to "english".
db-1 |
db-1 | Data page checksums are disabled.
db-1 |
db-1 | fixing permissions on existing directory /var/lib/postgresql/data ... ok
db-1 | creating subdirectories ... ok
db-1 | selecting dynamic shared memory implementation ... posix
db-1 | selecting default "max_connections" ... 100
db-1 | selecting default "shared_buffers" ... 128MB
db-1 | selecting default time zone ... Etc/UTC
db-1 | creating configuration files ... ok
db-1 | running bootstrap script ... ok
db-1 | performing post-bootstrap initialization ... ok
db-1 | initdb: warning: enabling "trust" authentication for local connections
db-1 | initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
db-1 | syncing data to disk ... ok
db-1 |
db-1 |
db-1 | Success. You can now start the database server using:
db-1 |
db-1 | pg_ctl -D /var/lib/postgresql/data -l logfile start
db-1 |
db-1 | waiting for server to start....2025-01-28 14:28:10.701 UTC [48] LOG: starting PostgreSQL 17.2 (Debian 17.2-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
db-1 | 2025-01-28 14:28:10.703 UTC [48] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db-1 | 2025-01-28 14:28:10.710 UTC [51] LOG: database system was shut down at 2025-01-28 14:28:10 UTC
db-1 | 2025-01-28 14:28:10.717 UTC [48] LOG: database system is ready to accept connections
db-1 | done
db-1 | server started
db-1 | CREATE DATABASE
db-1 |
db-1 |
db-1 | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
db-1 |
db-1 | 2025-01-28 14:28:10.928 UTC [48] LOG: received fast shutdown request
db-1 | waiting for server to shut down....2025-01-28 14:28:10.930 UTC [48] LOG: aborting any active transactions
db-1 | 2025-01-28 14:28:10.934 UTC [48] LOG: background worker "logical replication launcher" (PID 54) exited with exit code 1
db-1 | 2025-01-28 14:28:10.935 UTC [49] LOG: shutting down
db-1 | 2025-01-28 14:28:10.937 UTC [49] LOG: checkpoint starting: shutdown immediate
db-1 | 2025-01-28 14:28:10.981 UTC [49] LOG: checkpoint complete: wrote 921 buffers (5.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.023 s, sync=0.015 s, total=0.046 s; sync files=301, longest=0.002 s, average=0.001 s; distance=4238 kB, estimate=4238 kB; lsn=0/1908978, redo lsn=0/1908978
db-1 | 2025-01-28 14:28:10.989 UTC [48] LOG: database system is shut down
db-1 | done
db-1 | server stopped
db-1 |
db-1 | PostgreSQL init process complete; ready for start up.
db-1 |
db-1 | 2025-01-28 14:28:11.064 UTC [1] LOG: starting PostgreSQL 17.2 (Debian 17.2-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
db-1 | 2025-01-28 14:28:11.065 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db-1 | 2025-01-28 14:28:11.065 UTC [1] LOG: listening on IPv6 address "::", port 5432
db-1 | 2025-01-28 14:28:11.068 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db-1 | 2025-01-28 14:28:11.075 UTC [64] LOG: database system was shut down at 2025-01-28 14:28:10 UTC
db-1 | 2025-01-28 14:28:11.083 UTC [1] LOG: database system is ready to accept connections
Compose has two layers of environment-variable management. Compose itself uses a .env
file and the host environment to do variable substitution in the Compose file, and then it uses environment:
and env_file:
directives to populate the per-container environment.
I'd probably set this up by writing the credentials in the .env
file, and then selectively importing these into containers.
The first step is to make Compose aware of your .env.local
file. I'd set a COMPOSE_ENV_FILES
environment variable so that you only need to do this once. (The alternative is passing a docker-compose --env-file
option every time you run any Compose command.)
export COMPOSE_ENV_FILES=.env,.env.local
docker-compose up -d
Remove the env_file:
settings, but add environment:
blocks that set the variables to the correct values, renaming them if needed. The $VARIABLE
references will come from the settings in the $COMPOSE_ENV_FILES
.
services:
db:
image: postgres
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE}
app:
build: .
environment:
PGHOST: db
PGUSER: ${DB_USER}
PGPASSWORD: ${DB_PASSWORD}
PGDATABASE: ${DB_DATABASE}
I might use the standard PostgreSQL client variable names in the .env.local
file, in which case there's special Compose syntax to pass through the host-environment value.
services:
db:
environment:
POSTGRES_USER: ${PGUSER}
app:
environment:
PGUSER:
In the last block, $PGUSER
intentionally has an empty (null) value. If you're using YAML list syntax environment: [VAR=value, VAR2=value2]
then specifying just the variable name with no value (just a bare PGUSER
) has the same effect.