How to create postgres database and run migration when docker-compose up - postgresql

I'm setting up a simple backend that perform CRUD action with postgres database and want to create database and migration automatically when the docker-compose up runs.
I have already tried to add below code to Dockerfile or entrypoint.sh but none of them work.
createdb --host=localhost -p 5432 --username=postgres --no-password pg_development
createdb db:migrate
This code will work if run separately after docker is fully up
I have already tried to add - ./db-init:/docker-entrypoint-initdb.d to the volumes but that didn't work either
This is the Dockerfile
FROM node:10.12.0
# Create app directory
RUN mkdir -p /restify-pg
WORKDIR /restify-pg
EXPOSE 1337
ENTRYPOINT [ "./entrypoint.sh" ]
This is my docker-compose.yml
version: '3'
services:
db:
image: "postgres:11.2"
ports:
- "5432:5432"
volumes:
- ./pgData:/var/lib/psotgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD:
POSTGRES_DB: pg_development
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
volumes:
- .:/restify-pg
environment:
DB_HOST: db
entrypoint.sh (in here I get createdb: command not found)
#!/bin/bash
cd app
createdb --host=localhost -p 5432 --username=postgres --no-password pg_development
sequelize db:migrate
npm install
npm run dev
I expect that when I run docker, the migration and the db creation would happen.

entrypoint.sh (in here I get createdb: command not found)
Running createdb in the nodejs container will not work because it is postgres specific command and it's not installed by default in the nodejs image.
If you specify POSTGRES_DB: pg_development env var on postgres container, the database will be created automatically when the container starts. So no need to run createdb anyway in entrypoint.sh that is mounted in the nodejs container.
In order to make sequelize db:migrate work you need to:
add sequelize-cli to dependencies in package.json
run npm install so it gets installed
run npx sequelize db:migrate
Here is a proposal:
# docker-compose.yml
version: '3'
services:
db:
image: "postgres:11.2"
ports:
- "5432:5432"
volumes:
- ./pgData:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD:
POSTGRES_DB: pg_development
app:
working_dir: /restify-pg
entrypoint: ["/bin/bash", "./entrypoint.sh"]
image: node:10.12.0
ports:
- "3000:3000"
volumes:
- .:/restify-pg
environment:
DB_HOST: db
# package.json
{
...
"dependencies": {
...
"pg": "^7.9.0",
"pg-hstore": "^2.3.2",
"sequelize": "^5.2.9",
"sequelize-cli": "^5.4.0"
}
}
# entrypoint.sh
npm install
npx sequelize db:migrate
npm run dev

If you can run your migrations from nodejs instead of docker then consider this solution instead

Related

PrismaORM PostgreSQL create migration error inside Docker container

I have my NestJS application that use PrismaORM for connection to PostgreSQL. But building of docker file crashes after executing npx prisma migrate dev --name init with error Can't reach database server at postgres:5432
My docker-compose.yml
version: "3.8"
services:
api:
build:
dockerfile: Dockerfile
context: .
depends_on:
- postgres
env_file:
- ./.env
ports:
- "8080:5000"
postgres:
image: postgres:10.4
ports:
- "5432:5432"
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: db
volumes:
- ./postgres-data:/var/lib/postgresql/data
env_file:
- ./.env
**My Dockerfile
**
FROM node:16
WORKDIR /qmessanger/src/server
COPY package*.json ./
COPY prisma ./prisma/
COPY .env ./
COPY . .
RUN npm install
RUN npm run build
RUN npx prisma generate
RUN npx prisma migrate dev --name init
EXPOSE 8080
CMD [ "node", "dist/main" ]
My .env config
DATABASE_URL="postgresql://user:password#postgres:5432/db"
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_DB=db
My prisma config
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
The issue is that you're trying to run the migration before the postgres service is running. You would need to run the migration as part of your startup command or entrypoint.
Here is an example of a similar problem in Django and they used an entrypoint script to run the migration:
How do you perform Django database migrations when using Docker-Compose?

Can't reach database server at `postgres`:`5432`

Trying to dockerize, nests, and Prisma.
Nest is responding correctly to curl requests and and I can connect to the Postgres server fine with this command
--- docker compose exec postgres psql -h localhost -U postgres -d webapp_dev
Everything works until i try to run
npx prisma migrate dev --name init
then i get back
Error: P1001: Can't reach database server at `postgres`:`5432`
Here is my code:
docker-compose.yml
version: "2"
services:
backend:
build: .
ports:
- 3000:3000
- 9229:9229 # debugger port
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
command: yarn start:debug
restart: unless-stopped
depends_on:
- postgres
environment:
DATABASE_URL: postgres://postgres#postgres/webapp_dev
PORT: 8000
postgres:
image: postgres:14-alpine
ports:
- 5432:5432
environment:
POSTGRES_DB: webapp_dev
POSTGRES_HOST_AUTH_METHOD: trust
DockerFile
FROM node:16
# Create app directory, this is in our container
WORKDIR /usr/src/app
# Install app dependencies
# Need to copy both package and lock to work
COPY package.json yarn.lock ./
RUN yarn install
COPY prisma/schema.prisma ./prisma/
RUN npx prisma generate
# Bundle app source
COPY . .
RUN yarn build
EXPOSE 8080
CMD ["node": "dist/main"]
.env
//.env
DATABASE_URL=postgres://postgres#postgres/webapp_dev
not sure if this is the only issue but your db url does not contain the db secret in it
DATABASE_URL: postgres://postgres:mysecret#postgres/webapp_dev?schema=public
I got the same error I solved it after adding ?connect_timeout=300 at my DATABASE_URL

Docker-compose postgresql password authentication failed

I'm trying to get a setup going with a webservice that consumes a postgres database. Should be simple to setup, but I'm getting errors. So, first thing I want to make sure is that the database I set up is actually there and running.
To test this I substitute the "consumer" or "client" for an alpine interactive shell like so:
version: '3'
services:
db:
image: postgres:10.1-alpine
container_name: db
expose:
- 5432
volumes:
- "dbdata:/var/lib/postgresql/data"
environment:
- POSTGES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=db
web:
image: alpine:latest
stdin_open: true
tty: true
entrypoint: /bin/sh
depends_on:
- db
volumes:
dbdata:
Then I run the following command to get into the interactive shell:
docker-compose run web
and the following command to get in the database:
apk --update add postgresql-client && rm -rf /var/cache/apk/*
psql -h db -U user db
I get a plain denial from postgresql:
psql: FATAL: password authentication failed for user "user"
Same error message for each combo of username/password/databasename I try. Not much helpful.
What am I doing wrong here?
You have a typo in your docker-compose file. You mispelled POSTGRES here:
POSTGES_USER=user
That means the user user isn't being created. If I correct that typo, so that I have:
version: '3'
services:
db:
image: postgres:10.1-alpine
expose:
- 5432
volumes:
- "dbdata:/var/lib/postgresql/data"
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=db
web:
image: alpine:latest
stdin_open: true
tty: true
entrypoint: /bin/sh
depends_on:
- db
volumes:
dbdata:
Start the environment:
docker-compose up -d
Attach to the web contained and install the postgresql client:
$ docker attach project_web_1
/ # apk add --update postgresql-client
Then I can connect without a problem:
/ # psql -h db -U user db
Password for user user:
psql (11.2, server 10.1)
Type "help" for help.
db=#

docker faild to restore postgres backup

I'm trying to create and restore postgres backup using docker.
the docker failed to do it and gives me the following error:
/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
dockerfile:
FROM postgres:11
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD postgres
ENV POSTGRES_DB dbName
COPY backup.backup /
COPY initdb.sh /docker-entrypoint-initdb.d
initdb.sh:
pg_restore --username=postgres --create --exit-on-error --verbose --dbname=dbName backup.backup
docker-compose.yml:
version: '2'
services:
db:
image: postgres:11
expose:
- "5432"
ports:
- "15432:5432"
volumes:
- dock-volume:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD= postgres
- POSTGRES_DB= dbName
volumes:
dock-volume:
I tried to add the environment variables to docker-compose.yml but it doesnt help..
You should not create a Dockerfile for the Postgres because you already have the definition in your Dockercompose file. The variables that you define under environment are visible inside Postgres. If you want to have a backup and make sure that is running when you initialize you can do:
volumes:
- ~/Downloads/data/my_buckup.psql:/docker-entrypoint-initdb.d/stage.sql
Then when Postgres initialize this script will be run. You can see the documentation here under the section How to extend this image
I hope it makes sense

Knex Migration with Docker Compose Psql

I have a problem migrating using Knex js inside my docker-compose container.
the problem is that npm run db (knex migrate:rollback && knex migrate:latest && knex seed:run) would run right before the database is even created. Is there anyway to say that I would only like to run npm run db after the database has been created?
NOTE : if I do this npm commands on the docker terminal after it has been built everything works fine. just fyi
here is my docker-compose.yml
version: '3.6'
services:
#Backend api
server:
container_name: server
build: ./
command: npm run db
working_dir: /user/src/server
ports:
- "5000:5000"
volumes:
- ./:/user/src/server
environment:
POSTGRES_URI: postgres://test:test#192.168.99.100:5432/interapp
links:
- postgres
# PostgreSQL database
postgres:
environment:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: interapp
POSTGRES_HOST: postgres
image: postgres
ports:
- "5432:5432"
and here is my Dockerfile
FROM node:10.14.0
WORKDIR /user/src/server
COPY ./ ./
RUN npm install
CMD ["/bin/bash"]
on the docker-compose.yml file, using sh (bash) for a contained environment context for your command to run in. ie. sh -c 'npm run db'
your docker-compose file would now be
secondly, use the depends_on step to wait for the database to start
services:
#Backend api
server:
container_name: server
build: ./
command: sh -c 'npm run db'
working_dir: /user/src/server
depends_on:
-postgres
ports:
- "5000:5000"
volumes:
- ./:/user/src/server
environment:
POSTGRES_URI: postgres://test:test#192.168.99.100:5432/interapp
links:
- postgres
Simply adding depends_on to server service should do the trick here.
services:
server:
depends_on:
- postgres
...
This will cause docker-compose to start postgres container before the server container. It will not however wait for postgres to be ready. In this case it shouldn't be problem, because postgres starts really quickly.
If you want something more solid, or depends_on doesn't do the trick, you can add entrypoint wrapping script to your container. See https://docs.docker.com/compose/startup-order/, where you can read more about it. There are also links to tools, so you don't have to write your own script from scratch.