2015-09-10 3 views
1

Следующий файл Dockerfile вызывает ошибку при его создании. Есть ли способ использовать mount с overlay при построении контейнера?Ошибка при использовании команды mount в файле Docker

Dockerfile

FROM ubuntu:15.10 

RUN mkdir /var/data \ 
&& mkdir /var/data/delta \ 
&& mkdir /var/data/delta/changes \ 
&& mkdir /var/data/delta/workdir \ 
&& mkdir /var/data/merged \ 
&& mkdir /var/data/lower 

RUN mount -t overlay overlay -o lowerdir=/var/data/lower,upperdir=/var/data/delta/changes,workdir=/var/data/delta/workdir /var/data/merged 

Ошибка

...

Step 2 : RUN mount -t overlay overlay -o lowerdir=/var/data/lower,upperdir=/var/data/delta/changes,workdir=/var/data/delta/workdir /var/data/merged 
---> Running in 37434cc88e15 
mount: overlay is write-protected, mounting read-only 
mount: cannot mount overlay read-only 
Removing intermediate container 37434cc88e15 
The command '/bin/sh -c mount -t overlay overlay -o lowerdir=/var/data/lower,upperdir=/var/data/delta/changes,workdir=/var/data/delta/workdir /var/data/merged' returned a non-zero code: 32 

Примечание

Я попытался запустить приведенную ниже команду mount в контейнере ubuntu:15.10, и он дает ту же ошибку. Если контейнер запущен с --privileged, команда работает.

+0

Почему бы не сделать с 'VOL UME' в 'Dockerfile'? – BMW

+1

Они не VOLUMES, кроме/var/data/delta/changes, ни один из них не монтирует файловую систему хостов или не раскрывает их данные, данные будут существовать ТОЛЬКО внутри контейнера. Например, установка Jenkins будет включена/var/data/lower, а затем ТОЛЬКО измененные файлы будут отображаться вне контейнера через/var/data/delta/changes. – Enzey

+0

это антипаттерн, проголосуйте, конечно! Американский я ....! – BigDong

ответ

1

Есть ли способ использовать mount с overlay при построении контейнера?

Краткий ответ: No, and there won't be any time soon.

Похоже, что консенсус в том, что любая привилегированная операция во время сборки нарушает контракт на переносимость изображения, поскольку он может потенциально изменить хост-систему. Если другая система должна была вытащить и запустить такое изображение вместо того, чтобы строить его из источника, хост будет находиться в недопустимом состоянии с точки зрения результирующего контейнера.

Помните, докер строить работы по завершению каждого этапа/слой в Dockerfile с использованием (свободно) эти действия:

  1. Выполнить образ последнего шага/слоя в качестве нового контейнера
  2. Complete операции для текущего шага/слоя внутри контейнера
  3. фиксации контейнера (вкл. новое состояние) в новое изображение
  4. Повторите для любых дальнейших шагов

Таким образом, очевидно, что привилегированная операция сборки может выйти из временного контейнера и прикоснуться к узлу в этом сценарии. Нет буено.

Итак, что делать?


Решение 1 (запеченный в креплении)

UPDATE - 2015-10-24: Неудача. См. Решение 2 ниже для рабочей реализации.

Примечание: YMMV в зависимости от версии Docker, драйвера хранения/графика и т. Д.Вот мой докер Информация, для сравнения:

Containers: 12 
Images: 283 
Storage Driver: overlay 
Backing Filesystem: extfs 
Execution Driver: native-0.2 
Logging Driver: json-file 
Kernel Version: 4.1.10-040110-generic 
Operating System: Ubuntu 15.04 
CPUs: 4 
Total Memory: 7.598 GiB 
Name: agthinkpad 
ID: F6WH:LNV4:HH66:AHYY:OGNI:OTKN:UALY:RD52:R5L5:ZTGA:FYBT:SWA4 
WARNING: No swap limit support 

Ну, я удивительно найти его почти невозможно испечь гору в изображение с помощью докер совершить. Файловая система /proc, в которой файл-метаданные монтирования файлов записывается ядром (более конкретно /proc/self/mounts, изнутри контейнера), по-видимому, не сохраняется докерером вообще. Из того, что я могу сказать, в любом случае - /var/lib/docker/overlay/<container-root-lower>/root/proc пуст, а /var/lib/docker/overlay/<container-root-upper>/upper/proc не существует.

Я думал, что /proc можно манипулировать с помощью тома и действительно найти ссылки на 2+ год, чтобы привязать монтаж /proc:/proc к достижению того, что, вероятно, никто не должен пытаться (например, это возможно?), Но он выглядит так больше не работает. Attemping привязать крепление /proc к директории хозяина или даже просто сделать объем его теперь фатальная ошибка, даже с докер запустить --privileged:

Code: System error 

Message: "/var/lib/docker/overlay/c091a331f26bed12f22f19d73b139ab0c5b9971ea24aabbfad9c6482805984c9/merged/proc" 
cannot be mounted because it is located inside "/proc" 

Frames: 
--- 
0: setupRootfs 
Package: github.com/opencontainers/runc/libcontainer 
File: [email protected] 
--- 
1: Init 
Package: github.com/opencontainers/runc/libcontainer.(*linuxStandardInit) 
File: [email protected] 
--- 
2: StartInitialization 
Package: Error response from daemon: Cannot start container c091a331f26bed12f22f19d73b139ab0c5b9971ea24aabbfad9c6482805984c9: [8] System error: "/var/lib/docker/overlay/c091a331f26bed12f22f19d73b139ab0c5b9971ea24aabbfad9c6482805984c9/merged/proc" cannot be mounted because it is located inside "/proc" 

С точки зрения метода, который не требует работает mount ... внутри контейнеров, порожденных из изображения с помощью сценария запуска/записи, я действительно не уверен, куда идти с этого момента. Поскольку /proc/self/mounts управляется ядром, не говоря уже о невозможности записи, это никогда не будет возможно. Надеюсь, я что-то пропустил, и кто-то может указать мне в правильном направлении.

Если вы * должны * сделать это во время компиляции изображений вы можете свернуть свой собственный сценарий строитель, делая что-то вроде следующего: - Необязательно, сначала создайте `Dockerfile` и использовать фондовый строитель: ОТ mybaseimg | поцарапать COPY ./a/TMP/а RUN Foo ... `докер сборки -t mynewimg .` - Написать скрипт, используя комбинацию:` CID = $ (докер создать mynewimg) `, [`docker cp ...`] (https://docs.docker.com/reference/commandline/cp/), `docker start $ CID`,` docker exec | run ... $ CID ... `,` docker stop $ CID`, `docker commit $ CID mynewimg` и т. д. * (Изменить: желательно использовать [API] (https://docs.docker.com/reference/ api/remote_api_client_libraries /)!) * Когда вам нужно применить привилегированную операцию, вы можете эскалатировать команду `docker run`, но` --privileged` здесь полный избыток. Если вы думаете, что вам не нужно `--привилегировано` за что-то, что вы почти наверняка не делаете *. Для монтирования OverlayFS/AuFS вам нужно инициализировать `docker run` с` --cap-add = [SYS_ADMIN] `, а для Ubuntu (и, возможно, других) хостов с` AppArmor` вам также понадобится `--security- opt = [apparmor: unconfined] `(или предпочтительно профиль AppArmor, который ослабляет необходимые ограничения, а не` unconfined`). Я не уверен в `SELinux`.

Решение 2 (выполнения монтажа)

host$uname -a

Linux agthinkpad 4.1.10-040110-родовое # 201510030837 SMP сб 3 октября 12:38:41 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

host$MkDir/TMP/оверлей-тест & & кд/TMP/оверлей-тест

./Dockerfile:

FROM debian:jessie 

RUN apt-get update && apt-get install -y curl jq 

WORKDIR /usr/local/sbin 

# Locate and fetch the latest version of gosu 
RUN ["/bin/bash", "-c", "curl -o ./gosu -sSL \"$(\ 
     curl -s https://api.github.com/repos/tianon/gosu/releases/latest \ 
     | jq --raw-output \ 
     '.assets[] | select(.name==\"gosu-'$(dpkg --print-architecture)'\") | .browser_download_url' \ 
    )\" && chmod +x ./gosu"] 

COPY ./entrypoint.sh ./entrypoint 
RUN chmod +x ./entrypoint 

# UPPERDIR and WORKDIR **MUST BE ON THE SAME FILESYSTEM**, so 
# instead of creating a VOLUME for UPPERDIR we have to create a 
# parent directory for both UPPERDIR and WORKDIR, and then make 
# it the VOLUME. 
RUN ["/bin/bash", "-c", "mkdir -p /var/overlay-test/{lower,upper/{data,work}} /mnt/overlay-test"] 
VOLUME /var/overlay-test/upper 

# Create a file named FOO in the lower/root branch 
RUN touch /var/overlay-test/lower/FOO 

ENTRYPOINT ["entrypoint"] 

./entrypoint.sh:

#!/bin/bash 
set -e 

cd /var/overlay-test 
mount -t overlay -o lowerdir=lower,upperdir=upper/data,workdir=upper/work overlay /mnt/overlay-test 
chown -R "$DUID":"$DGID" ./ 
chown root: ./upper/work 
chmod 0750 ./upper/work 

cd /mnt/overlay-test 
exec gosu "$DUID":"$DGID" [email protected] 

host$докер построить -t наложения тест ./

Successfully built 582352b90f53

Хорошо, давайте проверим это!

Примечание: Под Ubuntu 15.04 хозяина я имел проблемы удаления (наложение Whiteout) любые файлы, которые существуют в lowerdir с помощью смонтированного каталога внутри контейнера. Эта ошибка оказалась виновницей: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1480411 - Редактировать: rm работает внезапно, и я могу видеть файл char в upper/data, поэтому могу только предположить, что это исправлено, и я получил обновленный пакет.

host$докер бег -это --name = оверлей-тест --env = "DUID = $ (идентификатор -u)" --env = "DGID = $ (идентификатор -g)" - колпачок добавьте = SYS_ADMIN --Безопасность-OPT = AppArmor: неограниченная оверлей-тест/бен/Баш

overlay-test$ID

uid=1000 gid=1000 groups=1000

overlay-test$mount | Grep '/ мнт/оверлей-тест'

overlay on /mnt/overlay-test type overlay (rw,relatime,lowerdir=lower,upperdir=upper/data,workdir=upper/work)

overlay-test$PWD

/mnt/overlay-test

overlay-test$Ls -Аль | СЕПГ '/^т/д'

 
-rw-r--r-- 1 1000 1000 0 Oct 24 03:54 FOO 

overlay-test$сенсорный BAR

overlay-test$Ls -Аль | СЕПГ '/^т/д'

 
-rw-r--r-- 1 1000 1000 0 Oct 24 04:21 BAR 
-rw-r--r-- 1 1000 1000 0 Oct 24 03:54 FOO 

overlay-test$Ls -Аль/вар/оверлей-тест/{нижняя/верхняя/*} | СЕПГ '/^т/д'

ls: cannot open directory /var/overlay-test/upper/work: Permission denied 

/var/overlay-test/lower: 
-rw-r--r-- 1 1000 1000 0 Oct 24 03:54 FOO 

/var/overlay-test/upper/data: 
-rw-r--r-- 1 1000 1000 0 Oct 24 04:21 BAR 

До сих пор так хорошо ... давайте попробуем импортировать объем из другого контейнера:

overlay-test$выхода

host$докер выполнения --rm --user = "$ (id -u): $ (id -g)" --volumes-from = overlay-test debian: jessie/bin/bash -c "ls -Al/var/overlay-test/upper/* | sed '/^t/d '"

ls: cannot open directory /var/overlay-test/upper/work: Permission denied 

/var/overlay-test/upper/data: 
-rw-r--r-- 1 1000 1000 0 Oct 24 05:32 BAR 

Успех! Обратите внимание, что вы можете также RUN echo в спецификации >> /etc/fstab в вашем Dockerfile, а затем mount -a внутри сценария точки входа, но этот метод был причудливым, по моему опыту. Я не уверен, почему, но поскольку между этими двумя методами нет функциональной разницы, я не стал больше разбираться.

Очистка: host$докер гт -v оверлей-тест & & докер RMI оверлей-тест


Документация по безопасности контейнеров во время выполнения в Докер:

https://docs.docker.com/reference/run/#security-configuration https://docs.docker.com/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration

+0

Возможно, команда mount не использует то, что я должен использовать, поскольку я не хочу монтировать тома из главной системы. Я хочу создать многоуровневую файловую систему в контейнере и иметь возможность отображать только папку с измененными файлами. – Enzey

+0

Идея состоит в том, что я хочу создать контейнер докеров для программы, скажем Дженкинс, который имеет все файлы, извлеченные, но не выставленные. Только новые или измененные файлы будут отображаться контейнером для легкого и небольшого резервного копирования, а не для всех файлов, которые составляют Jenkins, что и делает изображение докеров Jenkins. – Enzey

+0

@ Ензи, это именно то, для чего мои инструкции! Просто FYI мне понадобилось ядро ​​4.x, чтобы заставить монтирование OverlayFS работать внутри контейнера. Я также использую Overlay, поскольку драйвер/драйвер хранилища Docker и mount по-прежнему вызывают ошибку внутри контейнера, даже после установки правильных разрешений для создания контейнера, по-видимому, из-за того, что я укладывал файловые системы Overlay, которые были разбиты на ядро ​​3.19, которое я запускал. Я думаю, что у некоторых 4.2 ядер есть регрессия, но я могу подтвердить 4.10 работ. Во всяком случае, я уверен, что мой ответ решает ваш прецедент, поэтому вы можете прочитать его снова. :) –

Смежные вопросы