не вдалося встановити з'єднання D-Bus: Експлуатація заборонена


29

Я намагаюсь перелічити служби на моєму зображенні CentOS, що працює в Docker

systemctl list-units  

але я отримую це повідомлення про помилку:

Failed to get D-Bus connection: Operation not permitted

Будь-які пропозиції в чому можуть бути проблеми?


1
Ви не використовували sudo?
Майкл Хемптон

Ви не повинні використовувати systemd, якщо він вам не потрібен. Спробуйте запустити програму з неї в CMD або RUN або використовуючи скрипт для обгортки.
nelaaro

Якщо вам потрібно systemdна CentOS, використовуйте це зображення: FROM centos/systemd
james.garriss

Відповіді:


24

Я здогадуюсь, що ти працюєш з non-privilegedконтейнером. systemd вимагає можливості CAP_SYS_ADMIN, але Docker скидає цю здатність у непривілейовані контейнери, щоб додати більше безпеки.

Також systemd вимагає доступу RO до файлової системи cgroup в контейнері. Ви можете додати його за допомогою–v /sys/fs/cgroup:/sys/fs/cgroup:ro

Отже, ось кілька кроків про те, як запустити CentOS з системою всередині контейнера Docker:

  1. Витягніть зображення центоса
  2. Налаштуйте файл докера, як описано нижче:
FROM centos
MAINTAINER "Yourname" <youremail@address.com>
ENV container docker
RUN yum -y update; yum clean all
RUN yum -y install systemd; yum clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
  1. Побудуйте - docker build --rm -t centos7-systemd - < mydockerfile
  2. Запустіть контейнер із docker run --privileged -ti -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup centos7-systemd /usr/sbin/init

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


Досить акуратно! Однак принаймні я зараз отримую більше інформації. Ось що я реєструюсь:[ INFO ] Update UTMP about System Boot/Shutdown is not active. [DEPEND] Dependency failed for Update UTMP about System Runlevel Changes. Job systemd-update-utmp-runlevel.service/start failed with result 'dependency'. [ OK ] Started Journal Service. [ OK ] Reached target System Initialization. [ OK ] Reached target Timers. [ OK ] Listening on D-Bus System Message Bus Socket.
Snowcrash

1
У випадку, якщо я не був зрозумілий! Я все ще отримую помилкуFailed to get D-Bus connection: Operation not permitted
Snowcrash

Ви будуєте своє власне зображення з Dockerfile, скопійованого в моїй відповіді, запускаєте контейнер із цього зображення, і ви все одно отримуєте помилку?
13димітар

4
Бінго! Я запускав контейнер /bin/bash, щоб отримати оболонку. Однак це дало мені раніше згадану помилку. Коли я запустив його, /usr/sbin/initяк було запропоновано, тоді, прикріплений до оболонки, все пішло добре. Ясна річ я пропускаю нюанс /usr/sbin/init. Ця відповідь заслуговує на значну підтримку.
Snowcrash

Я був на цьому вже 2 дні, і досі не можу зрозуміти, що /sys/fs/cgroup:/sys/fs/cgroupце таке або звідки воно надходить ... Я знаю, як змонтувати гостьову папку до історії, як: /src/:/var/wwwале звідки береться ваш файл? Це заподіює мені багато помилок, тому що я вставив код, я думаю, що я мушу їх створити десь
samayo

4

Це не пряма відповідь на ваше запитання, але насправді це може бути важливіше, і я натрапив на це усвідомлення, читаючи тут інші відповіді.

Я мав певний досвід міграції деяких складних систем до Docker, і одна з найважливіших реалізацій, яку я мав, - це те, що в ідеалі вам слід мати один контейнер Docker на додаток / послугу або "на демон".

Однією з дуже вагомих причин цього є те, що Docker не буде чітко відключати послуги, які ви починаєте з systemctl, і насправді ви можете виявити такі ж пошкодження бази даних, які виникають внаслідок несподіваного відключення електроенергії.

Щоб зануритися в це трохи глибше: коли Докер видає контейнер команду "стоп", він надсилає сигналу SIGTERM лише той єдиний процес, який було розпочато з CMD / ENTRYPOINT, а не всім службам і демон. Так що одна служба має попередження про чистоту відключення, а всі інші безцеремонно припиняються.

Якщо вам абсолютно доведеться пакувати дві послуги в один контейнер (тобто вашу програму та базу даних PostgreSQL чи щось подібне), тоді вам потрібно, щоб ваш CMD / ENTRYPOINT був сценарієм, який ловить SIGTERM, а потім ретранслює його на ті відомі служби. Це можна зробити, але якщо у вас є можливість, переосмисліть своє рішення і спробуйте розбити його на кілька контейнерів.

Додаток

На сайті Docker є цікава примітка / сторінка про використання нагляду, якщо вам абсолютно потрібно мати кілька служб, що працюють в одному контейнері.


2

Мені вдалося виправити цю проблему в контейнері Docker CentOS: 7. Я в основному дотримувався проекту «Довідник із зображень CentOS Docker» .

FROM centos:7

ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

# Install anything. The service you want to start must be a SystemD service.

CMD ["/usr/sbin/init"]

Тепер, побудуйте зображення та запустіть його, використовуючи принаймні такі аргументи для docker runкоманди:-v /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro

Тоді головним є те, що /usr/sbin/initповинен бути перший процес всередині контейнера Docker.

Отже, якщо ви хочете використовувати користувальницький скрипт, який виконує деякі команди перед запуском /usr/sbin/init, запустіть його в кінці сценарію, використовуючи exec /usr/sbin/init(у bash-скрипті).

Ось приклад:

ADD cmd.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/cmd.sh

CMD ["/usr/local/bin/cmd.sh"]

А ось зміст cmd.sh:

#!/bin/bash

# Do some stuffs

exec /usr/sbin/init # To correctly start D-Bus thanks to https://forums.docker.com/t/any-simple-and-safe-way-to-start-services-on-centos7-systemd/5695/8

Ви можете мати, System is booting up. See pam_nologin(8)якщо ви використовуєте систему PAM, у такому випадку видаліть /usr/lib/tmpfiles.d/systemd-nologin.confсвою, Dockerfileоскільки вона створює файл, /var/run/nologinякий генерує цю конкретну помилку.


systemd-nologin.conf/ nologinдля виграшу, оскільки претензії CentOS / RHEL 7 UsePAM noне підтримуються, і вони подаватимуть скарги в журналах як такі. Не впевнений, чи RH відкритий переносний латка / зламав його якось або вони намагаються опустити поверхню підтримки від початківців клієнтів.

1

Мені не хотілося запускати systemd як init / PID 1. Після виконання кроків очищення, згаданих іншими, я запускаю systemd з сценарію запуску як /usr/lib/systemd/systemd --system &.

Це дозволило systemd запускати та запускати зареєстровані сервіси, але systemctl виходив з ладу з помилкою D-Bus.

Для мене відсутнім посиланням була відсутність каталогу / run / systemd / system, виявленого цим за допомогою straceing systemctl.

Створення цього каталогу вручну перед запуском systemctl дозволяє systemctl працювати для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.