Всі процеси в контейнері будуть працювати з-під користувача root, якщо його не вказати спеціальним чином. Це здається дуже зручно, адже цей користувач не має жодних обмежень. Саме тому працювати під рутом неправильно з погляду безпеки. Якщо на локальному комп'ютері ніхто при здоровому глузді не працює з рутовими правами, то багато хто запускає процеси під рутом у контейнерах.
Завжди є баги, які дозволять зловреді вибратися з контейнера та потрапити на хостовий комп'ютер. Припускаючи найгірше, ми повинні забезпечити запуск процесів усередині контейнера від користувача, який не має жодних прав на хостовій машині.
Створення користувача
Створення користувача в контейнері не відрізняється від створення в лінуксових дистрибутивах. Однак, для різних базових образів команди можуть різнитися.
Для дистрибутивів, заснованих на debian, в Dockerfile необхідно додати:
RUN groupadd --gid 2000 node
&& useradd --uid 2000 --gid node --shell /bin/bash --create-home node
Для Alpine:
RUN addgroup -g 2000 node
&& adduser -u 2000 -G node -s /bin/sh -D node
Запуск процесів від користувача
Для запуску всіх наступних процесів від користувача з UID 2000 виконайте:
USER 2000
Для запуску всіх наступних процесів від користувача node виконайте:
USER node
Детальніше в
Монтування томів
При монтуванні томів усередину контейнера забезпечте користувачеві можливість читати та (або) писати файли. Для цього користувача UID (GID) у контейнері та користувача за межами контейнера, у якого є відповідні права на доступ до файлу, повинні відповідати. При цьому імена користувачів не мають значення.
Часто на лінуксовому комп'ютері користувача UID і GID рівні 1000. Ці ідентифікатори присвоюються першому користувачеві комп'ютера.
Дізнатися про свої ідентифікатори просто:
id
Ви отримаєте вичерпну інформацію про свого користувача.
Замініть 2000 прикладів на свій ідентифікатор і все буде в порядку.
Присвоєння користувачеві UID та GID
Якщо користувач створений раніше, але необхідно змінити ідентифікатори, можна зробити це так:
RUN usermod -u 1000 node
&& groupmod -g 1000 node
Якщо ви використовуєте базовий образ alpine, потрібно встановити пакет shadow:
RUN apk add —no-cache shadow
Передача ідентифікатора користувача всередину контейнера при побудові образу
Якщо ваш ідентифікатор та ідентифікатори всіх людей, які працюють над проектом, збігаються, достатньо вказати цей ідентифікатор у Dockerfile. Однак, часто ідентифікатори користувачів не збігаються.
Як здійснити бажане не одразу зрозуміло. Для мене це було найскладнішим у процесі освоєння docker. Багато користувачів docker не замислюються над тим, що є різні етапи життя способу. Спочатку образ збирається для цього, використовуючи Dockerfile. Під час запуску контейнера з Dockerfile вже не використовується.
Створення користувачів має відбуватися під час побудови образу. Це стосується і визначення користувача, з-під якого запускаються процеси. Отже, ми маємо якимось чином передати всередину контейнера UID (GID).
Для використання зовнішніх змінних у Dockerfile служать директиви
Докер-файл
ARG UID=1000
ARG GID=1000
ENV UID=${UID}
ENV GID=${GID}
RUN usermod -u $UID node
&& groupmod -g $GID node
Надіслати аргументи через docker-compose можна так:
докер-створити
build:
context: ./src/backend
args:
UID: 1000
GID: 1000
PS Для освоєння всіх премудростей docker недостатньо читати документацію чи статті. Потрібно багато практикуватись, потрібно відчути docker.
Джерело: habr.com