Home Explore Blog CI



docker

3rd chunk of `content/guides/pre-seeding.md`
0e21a8c174fbf4d86b3e0866c9ccfbd9296ad55a01d974b6000000010000109d
                                                List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    | ICU Locale | Locale Provider |   Access privileges
   -----------+----------+----------+------------+------------+------------+-----------------+-----------------------
   postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            |
   sampledb  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            |
   template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | =c/postgres          +
             |          |          |            |            |            |                 | postgres=CTc/postgres
   template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | =c/postgres          +
             |          |          |            |            |            |                 | postgres=CTc/postgres
   (4 rows)
   ```

   To retrieve all the data from the users table, enter the following query:

   ```console
   sampledb=# SELECT * FROM users;
   id | name  |       email
   ----+-------+-------------------
    1 | Alpha | alpha@example.com
    2 | Beta  | beta@example.com
    3 | Gamma | gamma@example.com
   (3 rows)
   ```
  
   Use `\q` or `\quit` to exit from the Postgres interactive shell.

## Pre-seed the database by bind-mounting a SQL script

In Docker, mounting refers to making files or directories from the host system accessible within a container. This let you to share data or configuration files between the host and the container, enabling greater flexibility and persistence.

Now that you have learned how to launch Postgres and pre-seed the database using an SQL script, it’s time to learn how to mount an SQL file directly into the Postgres containers’ initialization directory (`/docker-entrypoint-initdb.d`). The `/docker-entrypoint-initdb.d` is a special directory in PostgreSQL Docker containers that is used for initializing the database when the container is first started

Make sure you stop any running Postgres containers (along with volumes) to prevent port conflicts before you follow the steps:

```console
$ docker container stop postgres
```

1. Modify the `seed.sql` with the following entries:

   ```sql
   CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(50),
    email VARCHAR(100) UNIQUE
   );

   INSERT INTO users (name, email) VALUES
    ('Alpha', 'alpha@example.com'),
    ('Beta', 'beta@example.com'),
    ('Gamma', 'gamma@example.com')
   ON CONFLICT (email) DO NOTHING;
   ```
   
2. Create a text file named `Dockerfile` and copy the following content.

   ```plaintext
   # syntax=docker/dockerfile:1
   FROM postgres:latest
   COPY seed.sql /docker-entrypoint-initdb.d/
   ```

   This Dockerfile copies the `seed.sql` script directly into the PostgreSQL container's initialization directory.
   

3. Use Docker Compose.
   
   Using Docker Compose makes it even easier to manage and deploy the PostgreSQL container with the seeded database. This compose.yml file defines a Postgres service named `db` using the latest Postgres image, which sets up a database with the name `sampledb`, along with a user `postgres` and a password `mysecretpassword`. 

   ```yaml
   services:
     db:
       build:
         context: .
         dockerfile: Dockerfile
       container_name: my_postgres_db
       environment:
         POSTGRES_USER: postgres
         POSTGRES_PASSWORD: mysecretpassword
         POSTGRES_DB: sampledb
       ports:
         - "5432:5432"
       volumes:
         - data_sql:/var/lib/postgresql/data   # Persistent data storage

   volumes:
     data_sql:
    ```
  
    It maps port `5432` on the host to the container's `5432`, let you access to the Postgres database from outside the container. It also define `data_sql` for persisting the database data, ensuring that data is not lost when the container is stopped.

    It is important to note that the port mapping to the host is only necessary if you want to connect to the database from non-containerized programs. If you containerize the service that connects to the DB, you should connect to the database over a custom bridge network.

Title: Pre-seeding Postgres by Bind-Mounting a SQL Script
Summary
This section explains how to pre-seed a Postgres database by bind-mounting a SQL script using Docker. It covers modifying the `seed.sql` file with `CREATE TABLE IF NOT EXISTS` and `ON CONFLICT` clauses. It then introduces a Dockerfile that copies the `seed.sql` script to the `/docker-entrypoint-initdb.d/` directory within the Postgres container. Furthermore, it details how to use Docker Compose to define and manage the Postgres container, including setting environment variables, mapping ports, and defining a volume for persistent data storage. The section emphasizes that port mapping to the host is necessary for connecting from non-containerized programs and recommends using a custom bridge network when containerizing the service that connects to the database.