25

I am new to docker. I have extended PostgreSQL image and able to create new DB instance while running the image.I need to create tables in that DB from shell script that will execute .sql file. While running PostgreSQL image it says server not started ? how we can execute script only after the PostgreSQL server starts in docker container?

Dockerfile:

FROM postgres:9.3
ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker
ENV POSTGRES_DB docker 
RUN apt-get update && apt-get install -y postgresql-9.3 postgresql-client-9.3 postgresql-contrib-9.3
ADD initialize.sh /home/MM0312/docker-entrypoint-initdb.d/initialize.sh
CMD ["/home/MM0312/docker-entrypoint-initdb.d/initialize.sh"]

initialize.sh

#!/bin/bash
set -e
set -x

echo "******PostgreSQL initialisation******"
gosu docker psql -h localhost -p 5432 -U docker -d $docker -a -f createDatabase.sql

createDatabase.sql file

CREATE TABLE web_origins (
    client_id character varying(36) NOT NULL,
    value character varying(255)
);
klefevre
  • 8,595
  • 7
  • 42
  • 71
Vaibhav Kumar
  • 759
  • 2
  • 9
  • 14

1 Answers1

60

In the docker-entrypoint.sh script of the official docker image of postgres is written:

psql+=( --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" )

        echo
        for f in /docker-entrypoint-initdb.d/*; do
            case "$f" in
                *.sh)     echo "$0: running $f"; . "$f" ;;
                *.sql)    echo "$0: running $f"; "${psql[@]}" < "$f"; echo ;;
                *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;;
                *)        echo "$0: ignoring $f" ;;
            esac
            echo
done

So every .sql file you want to execute inside your docker image can just be placed inside that folder. So my dockerfile looks like

FROM postgres:9.3
ENV POSTGRES_USER docker
ENV POSTGRES_PASSWORD docker
ENV POSTGRES_DB docker
ADD CreateDB.sql /docker-entrypoint-initdb.d/

And the content of my CreateDB.sql:

CREATE TABLE web_origins (
    client_id character varying(36) NOT NULL,
    value character varying(255)
);

So I just start my container with:

docker run -d my-postgres

To check:

docker exec -it 6250aee43d12 bash
root@6250aee43d12:/# psql -h localhost -p 5432 -U docker -d docker
psql (9.3.13)
Type "help" for help.

docker=# \c
You are now connected to database "docker" as user "docker".
docker=# \dt
           List of relations
 Schema |    Name     | Type  | Owner
--------+-------------+-------+--------
 public | web_origins | table | docker
(1 row)

You can find the details for mysql here in this blog.

lvthillo
  • 28,263
  • 13
  • 94
  • 127
  • How to handle this with docker compose? – kamal Mar 06 '18 at 09:46
  • 1
    Do we just need to copy this, as I can see in my case db.sql is copied in docker-entrypoint-initdb.d directory, but sql commands did not run. – kamal Mar 06 '18 at 11:32
  • 1
    @kamal If you use docker compose and the official postgres image and you want to create a resource at runtime (not in the image) you have to use: `- ./init.sql:/docker-entrypoint-initdb.d/init.sql` as described here https://gist.github.com/onjin/2dd3cc52ef79069de1faa2dfd456c945 – lvthillo Mar 06 '18 at 11:39
  • I did it, ```postgres: image: onjin/alpine-postgres:9.5 volumes: - ./testdata/db.sql:/docker-entrypoint-initdb.d/db.sql restart: unless-stopped ports: - "5432:5432"```, but still not executing. – kamal Mar 06 '18 at 11:41
  • @kamal If you're using the `-d` flag you can remove it to find more logs for debugging. In my case I found the 4th case `"$0: ignoring $f"` being echoed and I was able to trace the root cause from there. – akki Feb 08 '19 at 03:33