0

I want the following flow.

  • PostgreSQL runs startup script with the values from .env file
  • PostgreSQL runs successfully
  • App runs successfully
  • Run migration commands. I have already created the scripts for migration commands. This is done using node-pg-migrate module, and I simply need to run npm run migrate up after the app runs successfully.

I have the following startup scripts for my PostgreSQL.

First file (./initdb.d/001_create_database.sql)

CREATE DATABASE ${PGDATABASE};

Second file (./initdb.d/002_create_user.sql)

CREATE USER ${PGUSER} WITH ENCRYPTED PASSWORD '${PGPASSWORD}';
GRANT ALL PRIVILEGES ON DATABASE ${PGDATABASE} TO ${PGUSER};
GRANT USAGE, CREATE ON SCHEMA public to ${PGUSER};

I have the following .env file.

#db config
PGUSER={something}
PGHOST={something}
PGPASSWORD={something}
PGDATABASE={something}
PGPORT={something}

I have the following Dockerfile for my Node.js app.

FROM node:14
RUN apt-get update && apt-get install -y gettext-base
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN git clone https://github.com/vishnubob/wait-for-it.git
EXPOSE 5000
CMD [ "npm", "run", "start-dev" ]

Then, I have the following docker-compose.yml file.

version: "3.7"
services:
  app:
    build: .
    ports:
      - "${PORT}:${PORT}"
    env_file:
      - .env
    depends_on:
      - postgres
      - redis
      - rabbitmq
    restart: on-failure
  postgres:
    image: postgres:13
    env_file:
      - .env
    ports:
      - "${PGPORT}:${PGPORT}"
    volumes:
      - "./initdb.d:/docker-entrypoint-initdb.d"
      - musicapidata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: root
      POSTGRES_DB: root
      POSTGRES_USER: root
  redis:
    ...
  rabbitmq:
    ...
  migration:
    build:
      context: .
    command:
      [
        "./wait-for-it/wait-for-it.sh",
        "postgres:5432",
        "--",
        "npm",
        "run",
        "migrate",
        "up"
      ]
    links:
      - postgres
    depends_on:
      - postgres
    env_file:
      - .env
volumes:
  musicapidata:

I have tried using envsubst in my Dockerfile, but it doesn't work as the PostgreSQL service will copy the SQL script files with the placeholder values. Could someone guide me on how to do this?

EDIT

I have tried the following as well. I think I'm close.

docker-compose.yml

  postgres:
    build:
      context: .
      args:
        - pgversion=13
      dockerfile: Dockerfile-postgres
    env_file:
      - .env
    ports:
      - "${PGPORT}:${PGPORT}"
    volumes:
      - "./initdb.d:/docker-entrypoint-initdb.d"
      - musicapidata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: root
      POSTGRES_DB: root
      POSTGRES_USER: root

Dockerfile-postgres

ARG pgversion
FROM postgres:$pgversion

RUN apt-get update && apt-get install -y gettext-base
COPY initdb.d /docker-entrypoint-initdb.d
RUN chmod +x /docker-entrypoint-initdb.d/*
WORKDIR /docker-entrypoint-initdb.d
COPY .env ./

RUN envsubst < ./001_create_database.sql
RUN envsubst < ./002_create_user.sql

Unfortunately, it is copying the .env just right, but it si not running the envsubst yet.

Richard
  • 7,037
  • 2
  • 23
  • 76
  • The [`postgres` image](https://hub.docker.com/_/postgres) has standard environment variables to create a user and a database; how are your scripts different from what _e.g._ `POSTGRES_DB` creates automatically? – David Maze Jan 23 '23 at 12:33
  • @DavidMaze Because I don't want my env variables to be visible in the `docker-compose.yml` file (which I will commit to Github) so I want it to be in an `.env` file. – Richard Jan 24 '23 at 07:55
  • That's not a problem, you can use a Compose [`env_file:`](https://docs.docker.com/compose/compose-file/compose-file-v3/#env_file) directive to inject per-container environment variables from an external file. Trying to `RUN envsubst` is arguably worse because it will persist the credentials in the image in clear text. – David Maze Jan 24 '23 at 12:35
  • @DavidMaze I see. Do you have a link (doc/reading article) that mentions how I can use `env_file` from Compose to inject per-container environment variables, and then use it to create a database and a user with the privileges mentioned in the question? – Richard Jan 25 '23 at 05:19
  • @DavidMaze Hey, I got it to work. Turns out I just need to use the same environment variable name in the `.env` file. However, when I check the container's environment variables by printing out the env, it seems that all is visible in the container's environment. Is this normal? – Richard Jan 25 '23 at 05:45

0 Answers0