У меня есть контейнер, который я определяю в Dockerfile:
FROM python:3.9-alpine
WORKDIR /usr/app/
COPY src/backend/ .
RUN apk add acl
RUN pip install -r requirements.txt
RUN adduser -D game wheel
RUN setfacl -Rdm u:game:rwx /usr/app/
RUN chown -hR game /usr/app/ && chown -hR game /var/log/
USER game
HEALTHCHECK CMD curl --fail http://localhost:5000 || exit 1
CMD [ "python", "./src/app.py" ]
Цель состоит в том, чтобы запустить контейнер от имени «игрового» пользователя. Часть файла docker-compose, определяющая эту службу, такова:
server:
container_name: "server"
user: game
build:
context: .
dockerfile: ./src/backend/Dockerfile
volumes:
- ./src/backend/:/usr/app
ports:
- 5000:5000
depends_on:
- redis
И команда для запуска службы:
sudo docker compose -f docker-compose.yml up -d --no-deps
Однако приложение не работает при записи в журнал этой строки:
PermissionError: [Errno 13] Permission denied: '/usr/app/log'
Несмотря на то, что пользователь игры является владельцем папки /usr/app, ему не разрешено писать в нее. Я проверил это, добавив отпечатки в приложение текущего пользователя и его разрешения, и увидел, что разрешения на запись отсутствуют. Это не воспроизводится при запуске образа Docker без создания. Похоже, это связано с тем, как компоновка запускает докер. Что следует изменить в определениях Docker, чтобы пользователь игры мог писать в этот каталог?
Быстрый ответ: вы используете volume
.
Подробный ответ: когда вы запускаете контейнер через Compose, ваша ./src/backend/
хост-система монтируется /usr/app
внутри контейнера и принадлежит идентификатору пользователя и идентификатору группы из вашей локальной системы. Вы можете быстро это проверить, выполнив exec
внутри контейнера и выполнив ls -lah
. Вы увидите все файлы, принадлежащие идентификатору группы идентификаторов пользователей вашего пользователя (предположительно 1000:1000
).
Есть пара вещей, которые вы можете с этим сделать.
Забудьте пользователя game
и запустите его от имени пользователя root. Почему нет?
Создайте свой образ с помощью исходного кода, просто COPY
перед созданием game
пользователя и chown
после этого. Вам придется пересобирать образ каждый раз, когда вы захотите внести новые изменения в код.
Создайте пользователя game
с идентификатором пользователя и идентификатором группы. Это может нарушить переносимость. Плохое решение.
Запустите контейнер, exec
в него и chown
еще раз. Однако это нарушит вашу локальную разработку, поскольку файлы и каталоги в ./src/backend/
будут принадлежать любому идентификатору пользователя и идентификатору группы, назначенному game
.