Рабочие инструкции по извлечению данных неименованных разрешений для томов, работающих с Linux и Win - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь выполнить простой рабочий процесс безуспешно, и мне понадобилось много времени, чтобы протестировать множество решений на SO и github.Разрешение для указанной папки и более общий объем разрешений в докере - это кошмар link1 link2 imho.

Поэтому я перезагружаюсь с нуля, пытаясь создать простое доказательство концепции для моего варианта использования.

Я хочу этот общий рабочий процесс:

  • пользователь в Windows и/ или linux build Dockerfile
  • пользователь запускает контейнер (если возможно не как root)
  • контейнер запускает crontab, который каждую минуту запускает скрипт, записывающий в том данных
  • пользователи (в Linux или Windows) получают результаты из тома данных (не root), потому что разрешения правильно сопоставлены

Я использую supercronic, потому что он запускает crontab в контейнере без разрешения root.

Dockerfile:

FROM artemklevtsov/r-alpine:latest as baseImage

RUN mkdir -p /usr/local/src/myscript/
RUN mkdir -p /usr/local/src/myscript/result

COPY . /usr/local/src/myscript/

WORKDIR /usr/local/src/myscript/

RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories
RUN apk --no-cache add busybox-suid curl

ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.$
    SUPERCRONIC=supercronic-linux-amd64 \
    SUPERCRONIC_SHA1SUM=9aeb41e00cc7b71d30d33c57a2333f2c2581a201

RUN curl -fsSLO "$SUPERCRONIC_URL" \
 && echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - \
 && chmod +x "$SUPERCRONIC" \
 && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
 && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic

CMD ["supercronic", "crontab"]

Файл crontab:

* * * * * sh /usr/local/src/myscript/run.sh > /proc/1/fd/1 2>&1

Сценарий run.sh

#!/bin/bash

name=$(date '+%Y-%m-%d-%s')

echo "some data for the file" >> ./result/fileName$name

Команды:

# create the volume for result, uid/gid option are not possible for windows 
docker volume create --name myTestVolume

docker run --mount type=volume,source=myTestVolume,destination=/usr/local/src/myscript/result test

docker run --rm -v myTestVolume:/alpine_data -v $(pwd)/local_backup:/alpine_backup alpine:latest tar cvf /alpine_backup/scrap_data_"$(date '+%y-%m-%d')".tar /alpine_data

Когда я делаю это, папка результатов local_backup и содержащиеся в ней файлы имеют разрешения root:root, поэтому пользователь, запускающий этот контейнер, не может получить доступ к файлам.

Есть ли решение?который работает, что позволяет пользователям Windows / Linux / Mac, которые запускают thОдин и тот же сценарий для простого доступа к файлам в томе без проблем с разрешениями?

РЕДАКТИРОВАТЬ 1:

Стратегия, впервые описанная только здесь работа с привязанным томом и без именного тома .Мы используем entrypoint.sh для сокращения uid / gid папок контейнера на основе информации, предоставленной Docker Run.

Копирую, вставляю модифицированный Dockerfile:

FROM artemklevtsov/r-alpine:latest as baseImage

RUN mkdir -p /usr/local/src/myscript/
RUN mkdir -p /usr/local/src/myscript/result

COPY . /usr/local/src/myscript/

ENTRYPOINT [ "/usr/local/src/myscript/entrypoint.sh" ]

WORKDIR /usr/local/src/myscript/

RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories
RUN apk --no-cache add busybox-suid curl su-exec

ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.$
    SUPERCRONIC=supercronic-linux-amd64 \
    SUPERCRONIC_SHA1SUM=9aeb41e00cc7b71d30d33c57a2333f2c2581a201

RUN curl -fsSLO "$SUPERCRONIC_URL" \
 && echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - \
 && chmod +x "$SUPERCRONIC" \
 && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
 && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic

CMD ["supercronic", "crontab"]

entrypoint.sh

#!/bin/sh
set -e

addgroup -g $GID scrap && adduser -s /bin/sh -D -G scrap -u $UID scrap

if [ "$(whoami)" == "root" ]; then
    chown -R scrap:scrap /usr/local/src/myscript/
    chown --dereference scrap "/proc/$$/fd/1" "/proc/$$/fd/2" || :
    exec su-exec scrap "$@"
fi

Процедура сборки, запуска, экспорта:

docker build . --tag=test                                                       

docker run -e UID=1000 -e GID=1000 --mount type=volume,source=myTestVolume,destination=/usr/local/src/myscript/result test

 docker run --rm -v myTestVolume:/alpine_data -v $(pwd)/local_backup:/alpine_backup alpine:latest tar cvf /alpine_backup/scrap_data_"$(date '+%y-%m-%d')".tar /alpine_data

РЕДАКТИРОВАТЬ 2:

Для Windows, используя панель инструментов Docker и связанный том, я нашел ответ на SO .Я использую папку c:/Users/MyUsers для привязки, она более проста.

docker run --name test -d -e UID=1000 -e GID=1000 --mount type=bind,source=/c/Users/myusers/localbackup,destination=/usr/local/src/myscript/result dockertest --name rflightscraps 

Результат исследования

  • crontab запускается с утилитой пользователя [OK]
  • UID / GID локального пользователя сопоставлены с запиской пользователя контейнера [OK]
  • Экспортированные данные продолжают оставаться корневыми [НЕ ОК].
  • Windows / Linux [HALF OK]

    Если я использую том связывания, а не именованный том, он работает.Но это не желаемое поведение, как я могу использовать именованный том с правильным разрешением в Win / Linux ...

1 Ответ

0 голосов
/ 09 октября 2018

Позвольте мне разделить ответ на две части: часть 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, основываясь на вашем убеждении.

Ссылки:

  1. Руководство Crontab .
  2. Идентификатор пользователя - Wiki .
  3. Определение идентификатора пользователя .
  4. О драйверах хранилища .
  5. UNION FILE SYSTEM .
...