Recommended Docker Compose Folder Structure

Based on Docker documentation and best practices, here's a recommended folder structure for a Docker Compose application involving multiple services, environment-specific configurations, and profiles.

Recommended Folder Structure

my-app/
├── docker/                     # Docker related files
│   ├── common/                 # Shared Dockerfile stages/components
│   │   └── base.Dockerfile     # Base image definitions (optional)
│   ├── development/            # Development-specific Dockerfiles
│   │   ├── service1/
│   │   │   └── Dockerfile      # Dev Dockerfile for service1
│   │   └── service2/
│   │       └── Dockerfile      # Dev Dockerfile for service2
│   └── production/             # Production-specific Dockerfiles
│       ├── service1/
│       │   └── Dockerfile      # Prod Dockerfile for service1
│       └── service2/
│           └── Dockerfile      # Prod Dockerfile for service2
├── services/                   # Application code for each service
│   ├── service1/
│   │   ├── src/                # Service1 source code
│   │   └── .dockerignore       # Service-specific dockerignore
│   └── service2/
│       ├── src/                # Service2 source code
│       └── .dockerignore       # Service-specific dockerignore
├── compose.yaml                # Base Compose file (common services/config)
├── compose.dev.yaml            # Development environment overrides
├── compose.prod.yaml           # Production environment overrides
└── .dockerignore               # Root dockerignore (applies to all builds by default)

This structure is inspired by examples like those provided for Laravel in the Docker documentation. [Laravel Production] [Laravel Development]

Key Components Explained

Docker Configuration Files (docker/ directory)

Docker Compose Files (Root directory)

Application Code (services/ directory)

Using Profiles

Profiles allow you to selectively enable groups of services, ideal for optional tools or specific run modes (e.g., debugging, testing).

Define profiles within your Compose file(s):

services:
  frontend:
    build: ./services/frontend
    profiles: [frontend, dev] # Belongs to 'frontend' and 'dev' profiles
    # ... other frontend config

  phpmyadmin:
    image: phpmyadmin
    profiles: [debug] # Only runs when 'debug' profile is active
    # ... other phpmyadmin config

  backend:
    build: ./services/backend
    # No 'profiles' key means this service is always enabled by default
    # ... other backend config

Activate specific profiles using the --profile flag:

# Run default services + services with the 'dev' profile
docker compose --profile dev up

# Run only services with the 'debug' profile (and defaults if not specified otherwise)
docker compose --profile debug up -d

# Run multiple profiles
docker compose --profile frontend --profile debug up

[Using profiles with Compose]

.dockerignore Files

Use .dockerignore files to exclude files and directories from the build context sent to the Docker daemon, speeding up builds and reducing image size.

Handling Multiple Environments

Combine the base and environment-specific Compose files using the -f flag:

# Run Development Environment (merges compose.yaml and compose.dev.yaml)
docker compose -f compose.yaml -f compose.dev.yaml up -d --build

# Run Production Environment (merges compose.yaml and compose.prod.yaml)
docker compose -f compose.yaml -f compose.prod.yaml up -d

This structure helps manage configuration overrides and keeps relative paths within the Compose files consistent, addressing potential issues mentioned in the documentation regarding merging files from different directories. [Merge Compose files]