Рассмотрим пример классического docker-compose.yml докера для простого современного PHP приложения который кочует из проекта в проект и цитируется на разнообразных ресурсах как эталонный для старта:

version: '2'
services:
 mysql:
   image: mysql:5.7
   environment:
     MYSQL_ROOT_PASSWORD: 12345
   volumes:
     - ./db:/var/lib/mysql # сохранение файлов БД на хосте
   ports:
     - 3306:3306

 fpm:
   build:
     context: ./
     dockerfile: Dockerfile.fpm
   depends_on: [mysql]
   ports:
     - 9000
   volumes:
     - ./:/var/www

 nginx:
   build:
     context: ./
     dockerfile: Dockerfile.nginx
   depends_on: [fpm]
   ports:
     - 80:80
     - 443:443
   volumes_from:
     - fpm

3 сервисных контейнера - вроде все нормально, в духе Docker но почему я считаю что это плохо?

  1. Современное PHP-приложение в 99% случаев использует composer (если ваше нет - мне вас очень жаль, возможно стоит пока не поздно уходить во фронтенд). Вспомним как звучит основной тезис Docker "Docker enables developers and IT admins to build, ship and run any application, anywhere". Что будет если фронтендер захочет развернуть ваше приложения для работы над версткой - git clone, docker-compose up и что он получает? Он получает 404 и неработающее приложение, потому как vendors в гите нет, а про attach fpm и composer install вы ему не сказали.
  2. Ваш фронтендер, пришел к вам и говорит "емае, де батут?" Вы хватаетесь за голову, вспоминаете про то что ваше приложение надо-бы вообще развернуть перед использованием, присоединяетесь к fpm контейнеру в надежде сделать composer install, может даже добавляете команду в docker-compose.yml . Стоп! Какой такой composer? какой такой консольный php? В fpm сервисе? Слишком много противоречий в одном простом действии и не входит в компетенцию fpm.
  3. Сложно представить себе современное приложение чуть большее чем Hello-world которое тесно не работает с командной строкой, запускать CLI команды вашего приложения в fpm контейнере по меньшей мере странно, а кроме того ограничивает вас в части экспериментов с версиями.

Резюмируя, приложению необходим дополнительный специальный контейнер который бы имел консольный php, composer. Авторы composer благо озаботились этими проблемами - https://hub.docker.com/r/composer/composer/

Пример того как может выглядеть Docker файл нашего composer приложения (Docker.app):

FROM composer/composer:php5

RUN apt-get update && \
 apt-get install -y php5-intl libicu-dev default-jre && \
 rm -rf /var/lib/apt/lists/*

RUN docker-php-ext-install pdo
RUN docker-php-ext-enable pdo

RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-enable pdo_mysql

RUN docker-php-ext-install pcntl
RUN docker-php-ext-enable pcntl

RUN docker-php-ext-install gettext
RUN docker-php-ext-enable gettext

RUN pecl install intl
RUN docker-php-ext-install intl
RUN docker-php-ext-enable intl

RUN touch /usr/local/etc/php/conf.d/999-custom.ini
RUN echo date.timezone="Europe/Kiev" >> /usr/local/etc/php/conf.d/999-custom.ini

WORKDIR /var/www

COPY composer.json composer.lock ./

RUN composer install --prefer-source --no-interaction

ENTRYPOINT /bin/bash
CMD ["true"]

Результирующий базовый docker-compose.yml

version: '2'
services:
 mysql:
   image: mysql:5.7
   environment:
     MYSQL_ROOT_PASSWORD: 12345
   volumes:
     - ./db:/var/lib/mysql # сохранение файлов БД на хосте
   ports:
     - 3306:3306
app:
  build:
    context: ./
    dockerfile: Dockerfile.app
  depends_on: [mysql]
  tty: true
  volumes:
     - ./:/var/www

fpm:
   build:
     context: ./
     dockerfile: Dockerfile.fpm
   depends_on: [app]
   ports:
     - 9000
   volumes_from:
     - app

nginx:
   build:
     context: ./
     dockerfile: Dockerfile.nginx
   depends_on: [app, fpm]
   ports:
     - 80:80
     - 443:443
   volumes_from:
     - app

Обратите внимание что кроме решения проблем расписанных ранее - введение дополнительного слоя сделало зависимости более естественными (fpm не зависит от mysql и т.п.) Теперь проект можно разворачивать без PHP на хосте, можно гибко пробовать переходить на семерку только fpm не ломая CLI, можно fpm горизонтально масштабировать

DISCLAIMER - описанный способ один из возможных, например вы можете запускать composer install из command fpm но фактор жирного fpm в таком случае не устраняется

ПС. Фоточка отсюда https://blog.engineyard.com/2014/composer-its-all-about-the-lock-file