Я безуспешно пробую простой рабочий процесс, и мне требуется много времени, чтобы протестировать множество решений на SO и github. Разрешение для именованной папки и более общий объем разрешений в докере — это кошмар link1 link2 имхо.
Поэтому я перезапускаю с нуля, пытаясь создать простое доказательство концепции для моего варианта использования.
Я хочу этот общий рабочий процесс:
- пользователь в Windows и/или Linux создает 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, которые запускают один и тот же сценарий, легко получать доступ к файлам в томе без проблем с разрешениями?
ИЗМЕНИТЬ 1:
Стратегия, впервые описанная только здесь, работает с привязанным томом, и не именованный том. Мы используем entrypoint.sh
для выбора uid/gid папок контейнера на основе информации, полученной при запуске докера.
Я копирую и вставляю измененный 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"]
Точка входа.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 [НА ПОЛОВИНУ ОК]
Если я использую связываемый том, а не именованный том, он работает. Но это нежелательное поведение, как я могу использовать именованный том с правильным разрешением в Win/Linux...