I'm trying to create a database and connect to it within my container network. I don't want to have to ssh into a box to create users/databases etc, as this is not a scalable or easily distributable process.
This is what I have so far:
# docker-compose.yml
db:
image: postgres:9.4
volumes:
- ./db/init.sql:/docker-entrypoint-initdb/10-init.sql
environment:
- PGDATA=/tmp
- PGDATABASE=web
- PGUSER=docker
- PGPASSWORD=password
This is my init.sql
file:
CREATE DATABASE web;
CREATE USER docker WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE web TO docker;
When I start up the container and try to connect to it, I get this error:
db_1 | FATAL: role "docker" does not exist
db_1 | done
db_1 | server started
db_1 | FATAL: database "web" does not exist
db_1 | psql: FATAL: database "web" does not exist
The first time this happened, I tried to create a role like this:
CREATE ROLE docker with SUPERUSER PASSWORD password;
GRANT web TO docker;
But it did not have any effect. To make matters even more confusing, when I use node-postgres
to connect to the db, I get this error:
Error: connect ECONNREFUSED
But how can the connection be refused if the db service isnt even up??
In a nutshell, these are the questions I'm trying to solve:
Thank you in advance.
If you're working on a small project, and are deploying to a single machine, it's completely okay to run your database in a Docker container. Be sure to mount a volume to make the data persistent, and have backup processes in place. Try to restore them every once in a while to make sure your backups are any good.
It's pretty fast to set up a new database using this Docker process, compared to installing a database on your operating system. Different versions. It's easier to have different versions of the same database running in different containers (e.g. SQL Server 2017 and 2019) if you need to test different features.
How can I create a database using only the files in my project (i.e. no manual commands)?
The minimal docker-compose.yml
config for you defined user and database is:
postgres:
image: postgres:9.4
environment:
- POSTGRES_DB=web
- POSTGRES_USER=myuser
How do I create a user/role using only the files in my project?
To execute scripts on database initialization take a look at the official docs for initdb.
To get you started with a quick and dirty solution create a new file e.g. init_conf.sh
in the same directory as your docker-compose.yml
:
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" <<-EOSQL
CREATE ROLE docker with SUPERUSER PASSWORD 'password';
EOSQL
And add the volumes
directive to your docker-compose.yml
.
volumes:
- .:/docker-entrypoint-initdb.d
Recreate your container because otherwise, you wouldn't trigger a new database initialization. That means, docker stop
and docker rm
the old one first before executing docker-compose up
again. STDOUT gives you now some information about our newly introduced script.
How do I connect to this database?
To connect to your database with docker exec
via the terminal:
docker exec -ti folder_postgres_1 psql -U myuser -d web
A docker-compose.yml
in one of my production environments looks like the following:
services:
postgres:
logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "5"
build: ./docker/postgres # path to custom Dockerfile
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env
restart: always
# ... other services like web, celery, redis, etc.
Dockerfile
:
FROM postgres:latest
# ...
COPY *.sh /docker-entrypoint-initdb.d/
# ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With