Позвольте мне разделить ответ на две части: часть Linux и часть Docker.Чтобы решить эту проблему, вы должны понимать оба эти понятия.
Часть Linux
В Linux легко запускать cronjobs как пользователь, отличный от root.
Этого можно достичьпутем создания пользователя в Docker-контейнере с тем же UID, что и на хост-компьютере, и копирования файла crontab как /var/spool/cron/crontabs/user_name.
From man crontab
crontab - это программа, используемая для установки, удаления или перечисления таблиц, используемых для управления демоном cron (8) в Vixie Cron.Каждый пользователь может иметь свой собственный crontab, и, хотя это файлы в / var / spool / cron / crontabs , они не предназначены для непосредственного редактирования.
Поскольку Linux идентифицирует пользователей по идентификатору пользователя, в докере UID будет привязан к вновь созданному пользователю, тогда как на хост-машине он будет связан с пользователем хоста.
Итак, у вас нетвопрос разрешения, поскольку файлы принадлежат host_user.Теперь вы бы поняли, почему я упомянул создание пользователя с тем же UID, что и на хост-компьютере.
Docker Part
Docker рассматривает все каталоги (или слои) как UNION FILE SYSTEM.Всякий раз, когда вы строите изображение, каждая инструкция создает слой, и слой помечается как доступный только для чтения.По этой причине контейнеры Docker не сохраняют данные.Поэтому вы должны явно указать докеру, что некоторые каталоги должны сохранять данные, используя ключевое слово VOLUME
.
Вы можете запускать контейнеры без явного упоминания тома.Если вы это сделаете, демон docker считает их UFS и сбросит разрешения.Для сохранения изменений в файле / каталоге, включая право собственностиСоответствующий файл должен быть объявлен как Том в Dockerfile.
С UNION FILE SYSTEM
Действительно, когда контейнер загружен, он перемещается в память,и загрузочная файловая система отключена для освобождения оперативной памяти, используемой образом диска initrd.Пока это выглядит как обычный стек виртуализации Linux.В действительности, Docker размещает корневую файловую систему rootfs поверх загрузочной файловой системы.Этими rootfs могут быть одна или несколько операционных систем (например, файловая система Debian или Ubuntu).Докер вызывает каждую из этих файловых систем.Изображения могут быть наложены друг на друга.Изображение ниже называется родительским изображением, и вы можете проходить через каждый слой, пока не достигнете нижней части стопки изображений, где конечное изображение называется базовым изображением.Наконец, когда контейнер запускается из образа, Docker монтирует файловую систему для чтения и записи поверх любых слоев ниже.Именно здесь будут выполняться все процессы, которые мы хотим, чтобы наш контейнер Docker выполнял.Когда Docker впервые запускает контейнер, начальный слой чтения-записи пуст.Когда происходят изменения, они применяются к этому слою;например, если вы хотите изменить файл, этот файл будет скопирован из слоя только для чтения ниже в слой для чтения и записи.Версия файла, доступная только для чтения, все еще будет существовать, но теперь она скрыта под копией.
Пример:
Предположим, что у нас есть пользователь с именем host_user . UID для host_user 1000 .Теперь мы собираемся создать пользователя с именем docker_user в контейнере Docker.Поэтому я назначу ему UID как 1000 .Теперь любые файлы, которые принадлежат docker_user в контейнере Docker, также принадлежат host_user, если эти файлы доступны host_user с хоста (т. Е. Через тома).
Теперь вы можете совместно использовать каталог с другими без проблем с разрешениями,Вы даже можете дать разрешение 777 на соответствующий каталог, который позволяет другим редактировать данные.Иначе, Вы можете оставить 755 разрешений, что позволяет другим копировать, но редактировать данные может только владелец.
Я объявил каталог для сохранения изменений как том.Это сохраняет все изменения.Будьте осторожны, так как после того, как вы объявите каталог как том, дальнейшие изменения, внесенные в этот каталог при построении, будут игнорироваться, так как эти изменения будут в отдельных слоях.Поэтому внесите все изменения в каталог, а затем объявите его как том.
Вот файл Docker.
FROM alpine:latest
ARG ID=1000
#UID as arg so we can also pass custom user_id
ARG CRON_USER=docker_user
#same goes for username
COPY crontab /var/spool/cron/crontabs/$CRON_USER
RUN adduser -g "Custom Cron User" -DH -u $ID $CRON_USER && \
chmod 0600 /var/spool/cron/crontabs/$CRON_USER && \
mkdir /temp && \
chown -R $ID:$ID /temp && \
chmod 777 /temp
VOLUME /temp
#Specify the dir to be preserved as Volume else docker considers it as Union File System
ENTRYPOINT ["crond", "-f", "-l", "2"]
Вот файл crontab
* * * * * /usr/bin/whoami >> /temp/cron.log
Buildingизображение
docker build . -t test
Создать новый том
docker volume create --name myTestVolume
Запускать с томом данных
docker run --rm --name test -d -v myTestVolume:/usr/local/src/myscript/result test:latest
Всякий раз, когда вы монтируете myTestVolume
в другой контейнер, вы можетесм. данные в /usr/local/src/myscript/result
принадлежат UID 1000 , если в этом контейнере нет пользователя с таким UID или имя пользователя соответствующего UID.
Запуск с томом Bind
docker run --rm --name test - -dv $PWD:/usr/local/src/myscript/result test:latest
Когда вы выполните ls -al /home/host_user/temp
, вы увидите, что файл с именем cron.log
создан и принадлежит **host_user**
.
То же самое будет принадлежать docker_user в контейнере Docker при выполнении ls -al /temp
.Содержимое cron.log
будет docker_user
.
Итак, ваш эффективный Dockerfile
должен быть
FROM artemklevtsov/r-alpine:latest as baseImage
ARG ID=1000
ARG CRON_USER=docker_user
RUN adduser -g "Custom Cron User" -DH -u $ID $CRON_USER && \
chmod 0600 /var/spool/cron/crontabs/$CRON_USER && \
echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && \
apk --no-cache add busybox-suid curl && \
mkdir -p /usr/local/src/myscript/result && \
chown -R $ID:$ID /usr/local/src/myscript/result && \
chmod 777 /usr/local/src/myscript/result
COPY crontab /var/spool/cron/crontabs/$CRON_USER
COPY . /usr/local/src/myscript/
VOLUME /usr/local/src/myscript/result
#This preserves chown and chmod changes.
WORKDIR /usr/local/src/myscript/
ENTRYPOINT ["crond", "-f", "-l", "2"]
Теперь, когда вы присоединяете том Data / bind к /usr/local/src/myscript/result
itбудет принадлежать пользователю, имеющему UID 1000, и он будет постоянным во всех контейнерах, в зависимости от того, кто подключил один и тот же том с соответствующим пользователем с 1000 в качестве владельцев файлов.
Обратите внимание: I 'мы дали 777
разрешения, чтобы поделиться с каждым.Вы можете пропустить этот шаг в Dockerfle, основываясь на вашем убеждении.
Ссылки:
- Руководство Crontab .
- Идентификатор пользователя - Wiki .
- Определение идентификатора пользователя .
- О драйверах хранилища .
- UNION FILE SYSTEM .