не удалось установить соединение по шине D-Bus: операция не разрешена

29

Я пытаюсь перечислить сервисы на моем образе CentOS, работающем в Docker, используя

systemctl list-units  

но я получаю это сообщение об ошибке:

Failed to get D-Bus connection: Operation not permitted

Любые предложения, в чем может быть проблема?

Snowcrash
источник
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 с systemd внутри контейнера Docker:

  1. Вытащить изображение Centos
  2. Настройте файл Docker, как показано ниже:
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. Вы должны были бы systemd в вашем контейнере

13dimitar
источник
Довольно аккуратно! Однако, по крайней мере, сейчас я получаю больше информации. Вот что я записал:[ 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
Вы создали свой собственный образ из файла Docker, скопированного в моем ответе, вы запустили контейнер из этого образа, и у вас все еще появляется ошибка?
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, и фактически вы можете столкнуться с такими же повреждениями базы данных, которые происходят из-за неожиданного отключения питания.

Чтобы углубиться в это немного глубже: когда Docker выдает команду «stop» контейнеру, он отправляет сигнал SIGTERM только одному единственному процессу, который был запущен с CMD / ENTRYPOINT, а не всем службам и демонам. Таким образом, одна служба имеет предупреждение о чистом завершении работы, а все остальные отключаются.

Если вам абсолютно необходимо упаковать две службы в один и тот же контейнер (т.е. ваше приложение и базу данных PostgreSQL или что-то в этом роде), вам нужно, чтобы ваш CMD / ENTRYPOINT был сценарием, который перехватывает SIGTERM, а затем ретранслирует его в эти известные службы. Это можно сделать, но если у вас есть возможность, переосмыслите свое решение и попробуйте разбить его на несколько контейнеров.

Приложение

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

Мюррей Тодд Уильямс
источник
2

Мне удалось решить эту проблему в контейнере CentOS: 7 Docker. Я следовал в основном Руководству по созданию изображений 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 openssh portable как-то исправил или сломал его, или они пытаются снизить свою поддержку от начинающих клиентов.
1

Я не хотел запускать systemd как init / PID 1. После выполнения действий по очистке, упомянутых другими, я запускаю systemd из скрипта запуска as /usr/lib/systemd/systemd --system &.

Это позволило systemd запускать и запускать зарегистрированные службы, но systemctl не работал с ошибкой D-Bus.

Для меня отсутствующей ссылкой было отсутствие каталога / run / systemd / system, обнаружил это с помощью stracesystemctl.

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

Хаим Геретц
источник