Services and Builds

Services, Images and Build Contexts

A service is one container definition, which Compose 514 can run as one or more containers. BookNest has two: api, built from the Dockerfile of Multi-Stage and BuildKit and Buildx and Multi-Platform, and db, the official PostgreSQL 18 1,289 image. Save this as compose.yaml in the project root:

compose.yaml: BookNest's API and PostgreSQL 18YAML
# BookNest: the API and PostgreSQL 18. Settings come from the environment or a .env file.
name: booknest
services:
  api:
    build: .
    ports:
      - "${API_PORT:-3000}:3000"
    environment:
      PGHOST: db
      PGUSER: ${POSTGRES_USER:-booknest}
      PGPASSWORD: ${POSTGRES_PASSWORD:-booknest}
      PGDATABASE: ${POSTGRES_DB:-booknest}
    depends_on:
      - db
    restart: on-failure
  db:
    image: postgres:18
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-booknest}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-booknest}
      POSTGRES_DB: ${POSTGRES_DB:-booknest}
    ports:
      - "127.0.0.1:${DB_PORT:-5432}:5432"
    volumes:
      - pgdata:/var/lib/postgresql
volumes:
  pgdata:

image: runs an existing image; build: builds one, here from the current directory as the context. The long form, build: {context: ., dockerfile: Dockerfile, target: test, args: {...}}, selects a stage and passes build arguments, and when a service has both keys, image: names the built image. Without it Compose tags the result <project>-<service>, so this project's API image is booknest-api. The API reads the same PG* variables as before, with the service name db as its host, and PostgreSQL is published on the loopback interface only, so a host-side npm 2,036 test still reaches it. While the old docker-compose.yml exists too, every command warns "Found multiple config files" and uses compose.yaml; Env Files deletes the old file.