7

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:

  1. How can I create a database using only the files in my project (i.e. no manual commands)?
  2. How do I create a user/role using only the files in my project?
  3. How do I connect to this database?

Thank you in advance.

2
  • Please consider to upvote, accept or comment the answer if this solved your problem. It's The best way to say thanks to other people here at SO after they invested some time in posting them. Thanks! Commented Mar 2, 2018 at 8:56
  • Why dont you go ahead and accept an answer? Commented Dec 16, 2020 at 22:23

2 Answers 2

10

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/
# ...
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for this detailed answer. Is adding POSTGRES_DB to my compose file enough to create a database from nothing?
Yes, in fact, you could also leave this out because it defaults to POSTGRES_USER which defaults to postgres.
2

The environment variable you are using are wrong. Try this

version: '3.3'

services:  

  db:
    image: postgres:9.4
    restart: always
    environment: 
        - POSTGRES_USER=docker
        - POSTGRES_PASSWORD=password
        - POSTGRES_DB=web
    volumes:
      - db_data:/var/lib/postgresql/data
    # optional port
    ports: ["5555:5432"]

volumes:
  db_data:

then from any other docker-compose service you can access the DB at db:5432 and from your host machine you can access postgres on localhost:5555 if you also add the ports

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.