3

I have a CRUD app working on node, on my local machine. It is running on node, with postgres as the database, using knex.js as a query builder, etc.

I have created a docker file, and a docker-compose file, and the containers start, but the node container can't reach the postgres container. I suspect it has to do with the enviornment variables but I am not sure. here is my docker file:

FROM node:12
# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm ci --only=production

# Bundle app source
COPY . .

ENV PORT=8080
EXPOSE 8080

CMD [ "npm", "start" ]

This is the docker-compose file:

version: '2'
services:
  postgres:
    image: postgres:alpine
    environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: app
      POSTGRES_DB: db

  app:
    build: .
    depends_on:
      - "postgres"
    links:
      - "postgres"
    environment:
      DB_PASSWORD: 'password'
      DB_USER: 'app'
      DB_NAME: 'db'
      DB_HOST: 'postgres'
      PORT: 8080
    ports:
      - '8080:8080'
    command: npm start

also, here is the knex.js file on root that handles the db connections based on the environment:

// Update with your config settings.

module.exports = {

  development: {
    client: 'pg',
    connection: 'postgres://localhost/db'
  },
  test: {
    client: 'pg',
    connection: 'postgres://localhost/test-db'
  }
};

additionally when I check the hosts file on the node app inside the docker i don't see anything mentioning the link to postgres container. Any help would be appreciated, thanks.

2 Answers 2

3

The reason why your node application is not connecting is because it is trying to connect to itself as you are referencing localhost. Your database is in a second container which is not local so you need to reference it by service name which would be postgres.

So assuming your application is handling authentication another way, your config would be something like this:

// Update with your config settings.

module.exports = {

  development: {
    client: 'pg',
    connection: 'postgres://postgres/db'
  },
  test: {
    client: 'pg',
    connection: 'postgres://postgres/test-db'
  }
};

If you can, you should use the environment variables you assigned to the app container.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, this is what I was figuring, I was not sure how I should update the connection file though. I will try your suggested edits. Assuming this works, I can then theoretically run migrations from the node container and and it should migrate/seed the database as it normally would?
It looks like your Dockerfile will copy the entire source into the image so just ensure you run docker-compose build then docker-compose down; docker-compose up -d which should update the new file. You can verify by docker-compose exec app cat /path/to/knex.js to see if it has the edits. Yes, as long as you have successfully established the connection your migrations should work. That said, I don't see you passing in any credentials anywhere into the connection string so that may need to be fixed first.
I did attempt to try to pass the credentials from the connection string, but i believe the format was wrong as I was getting some strange errors. I am looking for docs to show me what the string should be formatted like, if I don't find it soon enough, would you be so kind as to tell me what the proper format is? I assume I need to pass the credentials from the docker-compose file?
I did end up getting it to work, connection: 'postgres://app:password@postgres/db' now i need to figure out how to add the second test database in my docker-compose
Good. I don't think you can create a second db with the out of the box entrypoint though. You may need to either manually create it or modify the entrypoint (E.g., github.com/docker-library/postgres/blob/…).
|
2

Docker-compose creates an internal network shared by the different containers it launches.
Since app and postgres are 2 separate containers, they are considered as 2 hosts. This causes app to look for postgres on the same container when you point it at localhost instead of the postgres container.

You can solve this by just changing localhost with postgres in your knex.js file.

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.