Почему Docker в Gitlab CI способен генерировать нерабочие образы?
- Дано: Dockerfile и сопутствующие файлы хранятся в Gitlab-репозитарии.
- Через .gitlab-ci.yml настроены автоматическая генерация и запуск Docker-контейнера.
- Внутри контейнера выполняется SSH-подключение к внешнему серверу.
- config для openssh-client хранится в Git и помещается внутрь контейнера во время docker build.
Результат:
- всё прекрасно собирается и выполняется на рабочей станции;
- однако при запуске из Gitlab'a SSH-клиент завершается с ошибкой:
Bad owner or permissions on /root/.ssh/config
Разбираемся:
- Сообщение выводится функцией read_config_file_depth в файле readconf.c, если файл настроек доступен на запись группе или всем.
- В контейнере, построенном на рабочей станции, /root/.ssh/config имеет права доступа 0644 и ssh-клиент запускается нормально.
- Файл sshconfig, клонируемый из Git на рабочую станцию, тоже имеет права доступа 0644.
- Однако в контейнере, построенном из-под Gitlab'a, этот файл (и все остальные, помещённые в контейнер через COPY и ADD) имеет права 0666.
Разбираемся дальше:
- Docker использует во время build общесистемный umask. Это его давний и справедливо критикуемый недостаток: например, см. https://github.com/Netflix/security_monkey/issues/959.
- На рабочих станциях umask принято устанавливать как минимум в 022.
- Однако umask внутри gitlab-runner'a устанавливается в 0: см. https://gitlab.com/gitlab-org/gitlab-runner/issues/1736.
- Это сначала приводит к тому, что git clone создаёт файлы с правами 0666, а потом docker build переносит их внутрь контейнера, оставляя такие же права.
Что же делать?
- После COPY и ADD надо явно выставлять права доступа на файлы и каталоги, созданные ими внутри контейнера, через RUN chmod ....
- О повторяемости сборок как ключевом достоинстве Docker надо помнить, что пока это не более, чем маркетинговый миф.