Если файлы, которые должны поступать из вашего образа, исчезают после docker compose up на macOS, проверьте, не перекрывает ли каталог контейнера монтирование привязкой (bind mount). Bind mount делает содержимое папки на хосте видимым в точке монтирования, скрывая файлы, уже находящиеся в образе. Найдите нужное сопоставление путей, исправьте путь на стороне хоста или контейнера (либо удалите его, если в нем нет необходимости) и пересоздайте соответствующий сервис. Согласно документации Docker, пересоздание контейнера без монтирования — это способ снова сделать видимыми оригинальные файлы образа. (Bind mounts)

Почему bind mount скрывает файлы

Bind mount связывает путь на хосте с путем в контейнере. Например, монтирование ./app:/usr/src/app приводит к тому, что папка app на хосте начинает отображаться по пути /usr/src/app. Если в образе уже были файлы в этой директории, они остаются частью образа, но становятся скрытыми, пока активно монтирование. Из-за этого работоспособный образ может казаться пустым или вызывать ошибки запуска, если перекрывается его исполняемая программа. То же самое поведение применимо и к Mac: Docker Desktop обеспечивает доступ к файлам хоста через виртуальную машину Linux. (Bind mounts)

Это отличается от проблем с правами доступа к файлам: контейнер может корректно считывать смонтированный каталог, но при этом считывать совершенно другой набор файлов, а не каталог образа. Проверьте сопоставление путей, прежде чем менять права владения или пересобирать образ.

Поиск сопоставления в Compose-файле

Откройте Compose-файл, используемый для запуска проекта, и найдите записи volumes: у нужного сервиса. Краткая форма записи, например ./app:/usr/src/app, является bind mount, если её источником выступает путь на хосте. В локальном Compose относительный путь источника разрешается относительно родительского каталога Compose-файла. Это означает, что ./app может указывать не на ту папку, которую вы ожидаете, если Compose-файл находится во вложенном каталоге. (Compose services reference)

Чтобы увидеть разрешенную конфигурацию и состояние сервисов, выполните следующие команды из каталога проекта в Терминале macOS:

docker compose config
docker compose ps

В полученной конфигурации сопоставьте source каждого монтирования (путь на Mac) с его target (путь в контейнере). Затем сравните целевую точку с рабочей директорией образа и каталогом, где должны находиться файлы приложения. Слишком широкое монтирование, например .:/usr/src/app, может перекрыть весь каталог приложения; более точечное сопоставление, например ./config:/usr/src/app/config, оставит остальную часть каталога образа видимой.

Выбор правильного решения

Если сервису требуется динамический доступ к исходному коду, оставьте bind mount, но направьте его на нужную папку хоста и в требуемый подкаталог контейнера. Убедитесь, что каталог на хосте содержит ожидаемые файлы. Краткий синтаксис Compose автоматически создает каталог, если указанный источник bind mount отсутствует, поэтому опечатка может незаметно подставить в контейнер пустую папку. Для явного контроля используйте расширенный синтаксис с create_host_path: false: в таком случае Compose сообщит об отсутствующем источнике вместо того, чтобы создавать каталог. (Compose services reference)

services:
  app:
    volumes:
      - type: bind
        source: ./app
        target: /usr/src/app
        bind:
          create_host_path: false

Если файлы приложения должны предоставляться самим образом, удалите монтирование, направленное на этот каталог. Если доступ к хосту нужен только конфигурационным файлам или одной генерируемой папке, смонтируйте только этот конкретный подкаталог. Для постоянных данных контейнера (например, базы данных) рассмотрите возможность использования именованного тома (named volume): Docker управляет его хранилищем самостоятельно, и это избавляет от привязки данных к конкретному каталогу на Mac. (Volumes)

Пересоздание сервиса и проверка

После редактирования Compose-файла пересоздайте затронутый сервис, чтобы применились обновленные параметры монтирования. Замените app в примере ниже на имя сервиса из вашего файла:

docker compose up -d --force-recreate app
docker compose exec app sh -c 'ls -la /usr/src/app'

Команда ls проверяет, что именно видит контейнер в точке монтирования; измените путь, если ваш сервис использует другой. Если в образе нет командной оболочки или отсутствует ls, изучите логи запуска с помощью docker compose logs app и используйте любую диагностическую команду, доступную в этом образе. Docker также описывает команду docker inspect для проверки источника и точки назначения монтирования контейнера; в случае с Compose сначала определите имя контейнера с помощью docker compose ps, а затем выполните docker inspect CONTAINER_NAME. (Bind mounts)

Если источник находится за пределами общих папок Docker Desktop или возникают ошибки Mounts denied либо file is not shared from the host, откройте в Docker Desktop раздел Settings > Resources > File sharing и добавьте нужный каталог Mac. В Docker по умолчанию общими являются /Users, /Volumes, /private, /tmp и /var/folders, однако каталоги вне этих расположений может потребоваться добавить вручную. Docker VMM не поддерживает автоматический общий доступ для bind mount, поэтому при использовании этого бэкенда добавление каталога вручную обязательно. (Docker Desktop settings, Virtual Machine Manager)

Ситуация, когда монтирование скрывает файлы образа, обычно устраняется исправлением пути источника или назначения, сужением области монтирования либо его удалением с последующим пересозданием сервиса. Используйте bind mount, когда контейнеру действительно нужна конкретная папка с хоста; во всех остальных случаях позвольте образу использовать свои собственные файлы или храните постоянные данные в томах под управлением Docker.

Источники