Як використовувати судо всередині контейнера для докера?


259

Зазвичай контейнери докера запускаються за допомогою кореня користувача . Я хотів би скористатися іншим користувачем, що не викликає проблем із використанням USER-директиви докера. Але цей користувач повинен мати можливість використовувати судо всередині контейнера. Ця команда відсутня.

Ось простий Dockerfile для цієї мети:

FROM ubuntu:12.04

RUN useradd docker && echo "docker:docker" | chpasswd
RUN mkdir -p /home/docker && chown -R docker:docker /home/docker

USER docker
CMD /bin/bash

Запускаючи цей контейнер, я входжу з користувачем 'docker'. Коли я намагаюся використовувати sudo, команда не знайдена. Тому я спробував встановити пакет sudo всередині свого Dockerfile за допомогою

RUN apt-get install sudo

Це призводить до неможливості знайти sudo пакета


Просто дайте користувачеві групу sudo. askubuntu.com/questions/7477/…
Regan

Відповіді:


242

Просто дісталося. Як зазначив реган, мені довелося додати користувача до групи судерів. Але головною причиною було те, що я забув оновити кеш сховищ, тому apt-get не зміг знайти пакет sudo. Зараз це працює. Ось заповнений код:

FROM ubuntu:12.04

RUN apt-get update && \
      apt-get -y install sudo

RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo

USER docker
CMD /bin/bash

8
не працює в центсах. adduserкоманда випльовує використання допомоги дляuseradd
Emad

Для CentOS ви можете додати користувача та групу, а потім створити файл осколки під /etc/sudoers.d/і встановити дозволи 440на цей файл. Тоді користувач отримав би доступ до sudo під CentOS, 6 і вище. 5 вам доведеться додати #includedir /etc/sudoers.dдирективу в/etc/sudoers
FilBot3

Не працює для мене. У мене є такі помилки: E: Не вдалося відкрити файл блокування / var / lib / apt / list / lock - відкрити (13: Дозвіл відхилено) E: Не вдається заблокувати каталог / var / lib / apt /
list

1
Схоже, це не працює для зображення
докера

100

Коли ні sudo, ні apt-get недоступні в контейнері, ви також можете перейти до запущеного контейнера як користувач root за допомогою команди

docker exec -u root -t -i container_id /bin/bash

Це набагато краще рішення того, чого, можливо, хоче досягти ОП, навіть якщо прийнята відповідь дає запитуване рішення. Принаймні, це відповідь, яку я шукав!
spikyjt

79

Інші відповіді не спрацювали для мене. Я продовжував шукати і знайшов допис у блозі, який висвітлював, як команда працює не-root у контейнері докера.

Ось версія TL; DR:

RUN apt-get update \
 && apt-get install -y sudo

RUN adduser --disabled-password --gecos '' docker
RUN adduser docker sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

USER docker

# this is where I was running into problems with the other approaches
RUN sudo apt-get update 

Я використовував FROM node:9.3для цього, але підозрюю, що інші подібні бази контейнерів також будуть працювати.


Я використовую ubuntu:bionic-20180724.1. Я використовував такий підхід, але після вищезазначеного він не дозволяє мені встановити інший пакет. Я доклав один рядок вище Dockerfile, щоб встановити пакет з: RUN apt-get install -y tree. Однак, мені дали це повідомлення про помилку:Step xxxx/xxxx : RUN apt-get install -y tree ---> Running in j5e6gsvwfafa Reading package lists... E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied) E: Unable to lock directory /var/lib/apt/lists/
edesz

1
@WR Я думаю, вам потрібно змінити цей рядок, щоб прочитати RUN sudo apt-get install -y tree. Після встановлення USERзначень іншого, ніж rootвам, вам потрібно буде використовувати sudoдля будь-яких команд, які потребують rootпривілеїв.
М. Скотт Форд

Ах, дякую! Пропустив це. Я не думав, що sudoйого пустять в Dockerfile.
edesz

Ідеально, просто те, що мені було потрібно.
Арін Екадем

25

Для тих, хто має цю проблему з уже запущеним контейнером, і вони не обов'язково хочуть перебудувати, наступна команда підключається до запущеного контейнера з правами root:

docker exec -ti -u root container_name bash

Ви також можете підключитися, використовуючи його ідентифікатор, а не його ім'я, знайшовши його за допомогою:

docker ps -l

Щоб зберегти зміни, щоб вони все ще були під час наступного запуску контейнера (або кластера докер-композицій):

docker commit container_id image_name

Щоб запустити контейнер, який не працює та з'єднаний як root:

docker run -ti -u root --entrypoint=/bin/bash image_id_or_name -s

Щоб скопіювати з запущеного контейнера:

docker cp <containerId>:/file/path/within/container /host/path/target

Щоб експортувати копію зображення:

docker save container | gzip > /dir/file.tar.gz

Які можна відновити до іншої установки Docker, використовуючи:

gzcat /dir/file.tar.gz | docker load

Це набагато швидше, але займає більше місця, щоб не стискати, використовуючи:

docker save container | dir/file.tar

І:

cat dir/file.tar | docker load

17

якщо ви хочете підключитися до контейнера та встановити щось,
використовуючи apt-get
first, як відповідь вище від нашого брата "Tomáš Záluský"

docker exec -u root -t -i container_id /bin/bash

то спробуйте

RUN apt - отримати оновлення або apt - отримати "все, що завгодно"

він працював зі мною, сподіваюся, що це корисно для всіх


5

Якщо SUDO або apt-get не доступні всередині контейнера, ви можете скористатися опцією нижче в запущеному контейнері.

docker exec -u root -it f83b5c5bf413 ash

" f83b5c5bf413" - це мій ідентифікатор контейнера, і ось приклад роботи з мого терміналу:

введіть тут опис зображення


3

Ось як я настроюю некорінного користувача з базовим зображенням ubuntu:18.04:

RUN \
    groupadd -g 999 foo && useradd -u 999 -g foo -G sudo -m -s /bin/bash foo && \
    sed -i /etc/sudoers -re 's/^%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^root.*/root ALL=(ALL:ALL) NOPASSWD: ALL/g' && \
    sed -i /etc/sudoers -re 's/^#includedir.*/## **Removed the include directive** ##"/g' && \
    echo "foo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
    echo "Customized the sudoers file for passwordless access to the foo user!" && \
    echo "foo user:";  su - foo -c id

Що відбувається з наведеним вище кодом:

  • Користувач і група fooстворені.
  • Користувач fooдодається як до групи, так fooі до sudoгрупи.
  • Значення uidі gidвстановлюється на значення 999.
  • Домашній каталог встановлено на /home/foo.
  • Оболонку встановлено на /bin/bash.
  • sedКоманда виконує вбудовані поновлення в /etc/sudoersфайл , щоб fooі rootкористувачів беспарольному доступу до sudoгрупі.
  • sedКоманда відключає #includedirдирективу , яка дозволить будь-які файли в підкаталогах , щоб перевизначити ці оновлення інлайн.

2

Якщо у вас є контейнер, що працює як root, який виконує скрипт (який ви не можете змінити), який потребує доступу до sudoкоманди, ви можете просто створити новий sudoскрипт у своєму $PATHвиклику, який викликає передану команду.

наприклад, у вашому Dockerfile:

RUN if type sudo 2>/dev/null; then \ 
     echo "The sudo command already exists... Skipping."; \
    else \
     echo -e "#!/bin/sh\n\${@}" > /usr/sbin/sudo; \
     chmod +x /usr/sbin/sudo; \
    fi

1
Залежно від зображень докера, які ви використовуєте (у моєму випадку Ubuntu: 18.04), можливо, вам доведеться видалити -eз echo. Інакше він буде присутній у самому файлі, що робить його нефункціональним.
stiller_leser

Ідеальна ідея, але це не спрацює, якщо в оригінальній команді використовуються параметри sudo, такі як sudo -E ls. Це спробують виконати -E ls.
wisbucky

2

Це може працювати не для всіх зображень, але деякі зображення вже містять кореневого користувача, наприклад, у зображенні jupyterhub / singleuser. З цим зображенням просто:

USER root
RUN sudo apt-get update

1

Використовуйте псевдонім.

alias sudo=''

Простий та ефективний. Не забудьте додати його до .bashrc, щоб він все ще працював після повторного відкриття оболонки.

nano ~/.bashrc
alias sudo=''

Оскільки користувач має стандартний корінь у Docker, «ігнорувати» команду sudo - це найпростіший спосіб.


0

На відміну від прийнятої відповіді , я використовую usermodнатомість.

Припустимо, що вже зареєстрований як root у docker, а "фрукт" - це нове некорінне ім'я користувача, яке я хочу додати, просто запустіть ці команди:

apt update && apt install sudo
adduser fruit
usermod -aG sudo fruit

Не забудьте зберегти зображення після оновлення. Використовуйте docker psдля отримання поточного докера <CONTAINER ID> та <IMAGE>, а потім запустіть docker commit -m "added sudo user" <CONTAINER ID> <IMAGE>для збереження зображення докера.

Потім тестуйте:

su fruit
sudo whoami

Або протестуйте за допомогою прямого входу (спочатку переконайтеся, що зберегти зображення) як цього некорінного користувача під час запуску докера:

docker run -it --user fruit <IMAGE>
sudo whoami

Ви можете використовувати sudo -kдля скидання часових позначок підказок пароля:

sudo whoami # No password prompt
sudo -k # Invalidates the user's cached credentials
sudo whoami # This will prompt for password
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.