prisma: Prisma doesn't resolve the names of docker containers from within other containers in OSX Docker

Bug description

Prisma works if I give it an ip address, but not a resolvable service name of a container

How to reproduce

docker-compose:

services:
  app:
    image: app
    platform: linux/arm64/v8
    ports:
      - "3000:3000"
    depends_on:
      - postgres
    environment:
      - "DATABASE_URL=postgresql://test:test@postgres:5432/test?schema=public"
    entrypoint: ["/usr/bin/dumb-init", "--", "./utils/wait-for-it.sh", "postgres:5432", "--"]
    command: [
        "/bin/bash",
        "-c",
        "pnpm run prisma-generate
        && pnpm exec prisma migrate dev
        && pnpm run dev -w",
      ]
    volumes:
      - $HOME/.aws:/root/.aws
  postgres:
    hostname: postgres
    image: postgres:14
    restart: always
    volumes:
      - postgres:/var/lib/postgresql/data
    environment:
      - "POSTGRES_PASSWORD=test"
      - "POSTGRES_DATABASE=test"
      - "POSTGRES_USER=test"
    ports:
      - "5432:5432"
volumes:
  postgres:
    name: db

This doesn’t work.

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "test", schema "public" at "postgres:5432"

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

BUT if I do an ip lookup in a shell and set DATABASE_URL=postgresql://test:test@172.23.0.2:5432/test?schema=public, it works. Lit export DATABASE_HOST=$(nslookup ${DATABASE_HOST?} | awk '/^Address: / { print $2 ; exit }')

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "test", schema "public" at "172.23.0.2:5432"

Already in sync, no schema change or pending migration was found.

And psql resolves this perfectly.

app# psql postgresql://test:test@postgres:5432/test
psql (14.2 (Debian 14.2-1.pgdg100+1))
Type "help" for help.

test=#

Expected behavior

Prisma needs to resolve my docker container’s hostname to a valid ip address or I need a workaround that isn’t hard-coding IP’s all over the place.

Prisma information

Environment & setup

  • OS: OSX Monterey 12.3 running a Node:16-based Docker image. Tried to replicate on Ubuntu 20.04 running latest Docker and I could not replicate at all.
  • Database: PostgreSQL
  • Node.js version: v16.14.2

Prisma Version

prisma                  : 3.8.1
@prisma/client          : 3.8.1
Current platform        : linux-arm64-openssl-1.1.x
Query Engine (Node-API) : libquery-engine 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at ../../node_modules/.pnpm/@prisma+engines@3.8.0-43.34df67547cf5598f5a6cd3eb45f14ee70c3fb86f/node_modules/@prisma/engines/libquery_engine-linux-arm64-openssl-1.1.x.so.node)
Migration Engine        : migration-engine-cli 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at ../../node_modules/.pnpm/@prisma+engines@3.8.0-43.34df67547cf5598f5a6cd3eb45f14ee70c3fb86f/node_modules/@prisma/engines/migration-engine-linux-arm64-openssl-1.1.x)
Introspection Engine    : introspection-core 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at ../../node_modules/.pnpm/@prisma+engines@3.8.0-43.34df67547cf5598f5a6cd3eb45f14ee70c3fb86f/node_modules/@prisma/engines/introspection-engine-linux-arm64-openssl-1.1.x)
Format Binary           : prisma-fmt 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at ../../node_modules/.pnpm/@prisma+engines@3.8.0-43.34df67547cf5598f5a6cd3eb45f14ee70c3fb86f/node_modules/@prisma/engines/prisma-fmt-linux-arm64-openssl-1.1.x)
Default Engines Hash    : 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f
Studio                  : 0.452.0
Preview Features        : interactiveTransactions

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 8
  • Comments: 29 (5 by maintainers)

Most upvoted comments

I was facing the same problem. I am using node 16.13. I tried multiple options including the ones mentioned above.

Placing static up in mysql container did solve the problem but I didn’t like that solution.

If you add network_mode: host in docker-compose file and then using localhost instead of container name in the connection string, prisma migration and seed works but you cannot access your application from host.

What worked for me simply use 172.17.0.1 instead of container name in connection string which works.

- docker-compose -f docker-compose-db.yml up -d
- export DB_URL=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.Gateway}}{{end}}' db)
- DB_HOST=${DB_URL} docker-compose -f docker-compose.yml up --abort-on-container-exit
- docker-compose down --remove-orphans -v

I am using these commands for my CI. It starts the container of MySQL in a separate compose file named docker-compose-db, extracts the IP for that container and then passes the IP as an env variable for the next compose file.

Update: it works on node 16.17.0 if I use ?connect_timeout=300 at the end of my DB connection string.

My solution to this was to define a bridge network and assign a static IP to the mysql container. Previously the containers were using the default bridge network, so there’s really no change to networking other than to specify the IP for the mysql container.

I had mixed results with defining hostnames and chanding the service name from mysql. Sometimes it would work, sometimes not.

I noticed some inconsistencies with node’s dns.lookup which leads me to think this is an issue with Node & Docker’s dns rather than an issue with Prisma itself, although I can’t be certain. Ping worked consistently, and a test script in C with getaddrinfo also worked consistently.

I’m on macOS 12.2.1 (M1 Pro), Prisma 3.12.0 running on a node 16.13 container with a mysql:5.7 container.

I can confirm this is happening on Windows as well. Running npx prisma generate in my Dockerfile seems to succeed, but actually trying to connect to the database later on fails.

I am getting:

Error: Can't reach database server at `mysql`:`3306

It is definitely Prisma-specific because I tried basic code using TypeORM, same exact credentials and it works without issues.

Adding ?connect_timeout=300 to the end of the connection string does not resolve my issue, either.

Adding connect_timeout=300 as in this StackOverflow issue worked for me, but I have no idea why that works.

I disagree with the closing answer. Sharing the same network (bridged internal OR external) and having the services in the same dockerfile both do not work. When passing in the environment value (DATABASE_URL) for Prisma Schema generation:

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

via docker-compose:

  depends_on:
      mongodb:
        condition: service_healthy
    container_name: api
    build:
      dockerfile: ../../apps/api/Dockerfile
      context: ../../apps/api
      cache_from:
        - nx-base-image:latest
      args:
        NODE_ENV: "development"
        BUILD_FLAG: ""
        DATABASE_URL: "mongodb://XX:XX@mongodb:27017/XX?authSource=admin"
        

Prisma will always fail to resolve the Docker DNS. This has nothing todo with incorrect docker configurations. I can confirm this as I have a setup with were both mongo-express and an api service that calls prisma generate have environment values injected with a docker service name in the URL values. mongo-express parses it correctly, prisma fails todo this just like other users have mentioned already in this thread.

Same as all the others (OSX M1). The workaround is to provide static IP addresses to the containers instead of relying on name lookup resolution.

See https://stackoverflow.com/questions/39493490/provide-static-ip-to-docker-containers-via-docker-compose for understanding how to configure your docker-compose file.

Same issue on windows WSL docker as well. Cannot connect to postgres docker container from nestjs/prisma container.

I got around this by writing a new entrypoint script for the containers:

#!/bin/bash
export PSQL_CONTAINER_HOST=$(dig psql +short)
export DATABASE_URL="postgresql://postgres:${POSTGRES_PASSWORD}@${PSQL_CONTAINER_HOST}:${POSTGRES_PORT}/dev"
/bin/bash $@

Though this is not used by our VSCode devcontainer, so used a .bashrc and helper script file to set them on every shell:

# ~/.bashrc
. ~/set_database_url.sh

set_database_url.sh

export PSQL_CONTAINER_HOST=$(dig psql +short)
export DATABASE_URL="postgresql://postgres:${POSTGRES_PASSWORD}@${PSQL_CONTAINER_HOST}:${POSTGRES_PORT}/dev"

It also seems to have been an issue even into last year, with the suggestion that it is M1 specific (I am also using an M1 mac).

Well, it works with a single compose file if you drop it into your the top of the scripts you’re using to run things. With if-statements, I could drop it into my /etc/profile

@meyerkev I was facing the same issue. For now, what I have done is that I have created 2 docker compose files: one of db and the other one for my backend service. I first run the db container, gets it’s gateway and sends it backend container as an argument. But still, I believe this is an open issue for prisma.

export DATABASE_HOST=$(nslookup ${DATABASE_HOST?} | awk '/^Address: / { print $2 ; exit }') cd "$(dirname $(dirname $0) )" also works.

Does this work with a single compose file?

In the bash script we’re using to run things yes. When I get some free time, I’ll try it in the /etc/profile with some if-statements to avoid the double-lookup problem.