Connecting to Databases in Docker Containers

Build connection strings for databases running in Docker. Covers host-to-container, container-to-container, docker-compose networking, and port mapping.

Best Practices

Detailed Explanation

Docker Database Networking

When running databases in Docker containers, the connection string depends on where the client is running relative to the container.

Scenario 1: Host to Container

Your app runs on the host machine, the database runs in a container with published ports:

# docker-compose.yml
services:
  postgres:
    image: postgres:16
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb

Connection string from the host:

postgresql://myuser:secret@localhost:5432/mydb

The key here is localhost with the published port (the left side of the ports mapping).

Scenario 2: Container to Container (same network)

Both app and database run in Docker on the same network:

services:
  app:
    build: .
    depends_on:
      - postgres
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb

Connection string from the app container:

postgresql://myuser:secret@postgres:5432/mydb

Use the service name (postgres) as the host. Docker Compose creates a DNS entry for each service. Use the container port (the right side of any ports mapping, or the default if no ports are published).

Scenario 3: Custom Network

docker network create mynet
docker run -d --name mydb --network mynet -e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name myapp --network mynet myapp-image

Connection string from myapp:

postgresql://postgres:secret@mydb:5432/postgres

Common Pitfalls

  1. Using localhost inside a container — Inside a container, localhost refers to the container itself, not the host. Use the service name or container name instead.

  2. Port confusion — Published ports are for host access. Containers on the same network use the internal port (e.g., 5432 for PostgreSQL, not the mapped port).

  3. Waiting for readiness — Use depends_on with health checks to ensure the database is ready before your app tries to connect:

services:
  postgres:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myuser"]
      interval: 5s
      timeout: 5s
      retries: 5
  app:
    depends_on:
      postgres:
        condition: service_healthy

Use Case

Setting up a local development environment with Docker Compose, running integration tests against containerized databases, or configuring microservices that communicate with database containers on a shared Docker network.

Try It — Connection String Builder

Open full tool