#Что происходит и как распознать неисправность
Python внутри контейнера может успешно читать данные и получать PermissionError при создании файла. Внутри образа и на хосте действуют разные пространства имён, пользователи UID/GID, права и настройки монтирования.
#Как отличить причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
Папка смонтирована только на чтениеbind mount или volume используется с :ro либо контейнер запущен с read_only. | Ошибка возникает и у процессов с корректными правами. | Измените режим только для специально выделенного рабочего каталога. |
| UID/GID процесса не имеет правВладельцем bind mount является другой UID, чем у процесса в контейнере. | id и stat показывают разные значения. | Согласуйте права и пользователя без глобальных chmod. |
| Папка отсутствует или невернаОжидаемый абсолютный путь создан на хосте, но в контейнере он другой. | ls внутри контейнера показывает другой каталог. | Проверьте фактические mounts и переменные приложения. |
#Пошаговая диагностика и исправление
- Запишите точный путь, в который пишет программаОткройте журнал контейнера через
docker compose logs --tail 100 ИМЯ_СЛУЖБЫ, заменив имя названием службы в compose.yaml; в терминале перейдите в каталог с этим файлом. Найдите PermissionError: [Errno 13] и абсолютный путь. Не меняйте права наугад по корню контейнера. - Проверьте пользователя процесса и путь внутри контейнераВ терминале Docker-хоста выполните
docker compose exec ИМЯ_СЛУЖБЫ idиdocker compose exec ИМЯ_СЛУЖБЫ ls -ld /путь/для/записи, предварительно подставив реальные имя и путь. В выводе запишите UID/GID и разрешения. Если служба не запущена, используйте её диагностику черезdocker compose psи логи, не удаляя контейнеры. - Сравните настройки монтирования в ComposeОткройте compose.yaml в редакторе, найдите разделы
volumes,read_onlyиuserу проблемной службы. При записи./data:/app/data:roсуффикс:roозначает запрет записи. Если файл должен быть только читаемым, измените путь вывода Python, а не защиту контейнера. - Убедитесь, что на хосте существует назначенный каталогВ файловом менеджере или терминале хоста проверьте соответствующий исходный каталог bind mount, например
./data. Поскольку относительный путь зависит от Compose-проекта, сначала определите его реальное расположение командойdocker compose config. Не создавайте неизвестные каталоги в системных папках; для вывода выделите отдельный путь приложения. - Исправьте права точечно после резервной копииЕсли диагностика доказала конфликт UID/GID, согласуйте владельца конкретной папки данных с администратором. Не применяйте
chmod -R 777или изменение владельца к общему разделу. При необходимости можно настроить отдельный именованный volume либоuserсервиса, предварительно проверив права на существующие файлы и влияние на другие задачи. - Проверьте запись без риска для данныхВнутри запущенного контейнера через Python создайте НОВЫЙ диагностический файл в нужном каталоге с уникальным именем, убедитесь, что он появился, затем удалите только этот собственный тестовый файл после проверки. Если контейнер read-only по политике безопасности, используйте разрешённый каталог
/tmpлибо отдельный volume, не отключая защиту всей системы. - Примените изменения контролируемо и откатите при проблемеЕсли правили compose.yaml, сохраните его копию, проверьте синтаксис
docker compose configи только по согласованию пересоздайте нужную службу командойdocker compose up -d ИМЯ_СЛУЖБЫ. После запуска повторите запись. Если пропал доступ к старым данным, остановитесь, восстановите исходный compose.yaml и проверьте, не был ли смонтирован пустой новый том.
#Команды и примеры для проверки
docker compose psdocker compose configfrom pathlib import Path
target = Path("/app/data/probe-write.txt") # замените путём к разрешённой папке
with target.open("x", encoding="utf-8") as f:
f.write("проверка записи\n")
print(target)#Как проверить результат и что делать дальше
Рабочий признак — новый файл появляется именно в ожидаемой папке, приложение не сообщает PermissionError, а контейнер не получил ненужные привилегии. Если запись невозможна даже при согласованном UID/GID, проверьте ACL, SELinux/AppArmor и ограничения файловой системы совместно с администратором.