impossible d'obtenir la connexion D-Bus: opération non autorisée

29

J'essaie de répertorier les services sur mon image CentOS exécutée dans Docker en utilisant

systemctl list-units  

mais je reçois ce message d'erreur:

Failed to get D-Bus connection: Operation not permitted

Des suggestions sur le problème?

Snowcrash
la source
1
Tu n'as pas utilisé sudo?
Michael Hampton
Vous ne devriez pas utiliser systemd, si vous n'en avez pas besoin. Essayez de démarrer l'application sans celle-ci dans le CMD ou le RUN, ou en utilisant un script wrapper.
nelaaro
Si vous avez besoin systemdde CentOS, utilisez cette image: FROM centos/systemd
james.garriss

Réponses:

24

Je suppose que vous exécutez un non-privilegedconteneur. systemd nécessite la capacité CAP_SYS_ADMIN mais Docker supprime cette capacité dans les conteneurs non privilégiés, afin d'ajouter plus de sécurité.

systemd nécessite également un accès RO au système de fichiers cgroup dans un conteneur. Vous pouvez l'ajouter avec–v /sys/fs/cgroup:/sys/fs/cgroup:ro

Voici donc quelques étapes pour exécuter CentOS avec systemd dans un conteneur Docker:

  1. Pull image centos
  2. Configurez un fichier Docker comme celui ci-dessous:
FROM centos
MAINTAINER "Yourname" <[email protected]>
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. Construit le - docker build --rm -t centos7-systemd - < mydockerfile
  2. Exécutez un conteneur avec docker run --privileged -ti -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup centos7-systemd /usr/sbin/init

  3. Vous devriez avoir systemd dans votre conteneur

13dimitar
la source
Génial! Cependant, au moins, je reçois plus d'informations maintenant. Voici ce que je me connecte:[ 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
Au cas où je ne serais pas clair! Je reçois toujours l'erreurFailed to get D-Bus connection: Operation not permitted
Snowcrash
Vous avez créé votre propre image à partir du Dockerfile copié dans ma réponse, vous exécutez un conteneur à partir de cette image et vous obtenez toujours une erreur?
13dimitar du
4
Bingo! J'exécutais le conteneur avec /bin/bashpour obtenir un shell. Cependant, cela m'a donné l'erreur mentionnée précédemment. Quand je l'ai couru avec /usr/sbin/initcomme suggéré puis attaché avec une coque, tout s'est bien passé. De toute évidence, il me manque une nuance /usr/sbin/init. Cette réponse mérite un vote positif substantiel.
Snowcrash
J'y suis depuis 2 jours, et je n'arrive toujours pas à comprendre de quoi il /sys/fs/cgroup:/sys/fs/cgroups'agit ou d'où il vient ... Je sais comment monter le dossier invité sur hist comme: /src/:/var/wwwmais d'où vient votre fichier? Cela me cause beaucoup d'erreurs parce que j'ai collé le code, je pense que je devrais les créer quelque part
samayo
4

Ce n'est pas une réponse directe à votre question, mais elle peut en fait être plus importante, et je suis tombé sur cette réalisation alors que je lisais les autres réponses ici.

J'ai eu une certaine expérience de la migration de certains systèmes complexes vers Docker, et l'une des réalisations importantes que j'ai eues est que vous devriez idéalement avoir un conteneur Docker par application / service ou "par démon".

Une raison très importante à cela est que Docker ne fermera pas proprement les services que vous démarrez avec systemctl et, en fait, vous pourriez vous retrouver avec le même type de corruption de base de données provenant d'une panne de courant inattendue.

Pour approfondir ceci: lorsque Docker émet une commande "stop" vers un conteneur, il envoie le signal SIGTERM uniquement le seul processus qui a été démarré avec le CMD / ENTRYPOINT, pas à tous les services et démons. Pour qu'un service ait l'avertissement de s'arrêter proprement et que tous les autres soient arrêtés sans cérémonie.

Si vous devez absolument empaqueter deux services dans le même conteneur (c'est-à-dire votre application et une base de données PostgreSQL ou quelque chose comme ça), alors vous devez avoir votre CMD / ENTRYPOINT être un script qui attrape SIGTERM puis le rediffuse vers ces services connus. Cela peut être fait, mais si vous en avez l'occasion, repensez votre solution et essayez de la diviser en plusieurs conteneurs.

Un addendum

Il y a une note / page intéressante sur le site Docker à propos de l'utilisation de supervisord si vous devez absolument avoir plusieurs services en cours d'exécution dans le même conteneur.

Murray Todd Williams
la source
2

J'ai réussi à résoudre ce problème dans un conteneur Docker CentOS: 7. J'ai principalement suivi le projet d'image Guide sur 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"]

Maintenant, créez l'image et exécutez-la en utilisant au moins les arguments suivants pour docker runcommander:-v /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro

Ensuite, le point principal est que ce /usr/sbin/initdoit être le premier processus à l'intérieur du conteneur Docker.

Donc, si vous souhaitez utiliser un script personnalisé qui exécute certaines commandes avant de s'exécuter /usr/sbin/init, lancez-le à la fin de votre script en utilisant exec /usr/sbin/init(dans un script bash).

Voici un exemple:

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

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

Et voici le contenu de 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

Vous pourriez avoir System is booting up. See pam_nologin(8)si vous utilisez le système PAM, dans ce cas, supprimez- /usr/lib/tmpfiles.d/systemd-nologin.confle Dockerfilecar cela crée le fichier /var/run/nologinqui génère cette erreur spécifique.

Anthony O.
la source
systemd-nologin.conf/ nologinpour la victoire car CentOS / RHEL 7 ne UsePAM noprend pas en charge les réclamations et se plaindra dans les journaux en tant que tels. Je ne sais pas si RH openssh portable a patché / cassé d'une manière ou d'une autre ou essaie de réduire la surface de support des clients novices.
1

Je ne voulais pas avoir à lancer systemd en tant que init / PID 1. Après avoir effectué les étapes de nettoyage mentionnées par d'autres, je lance systemd à partir d'un script de démarrage en tant que /usr/lib/systemd/systemd --system &.

Cela a permis à systemd de démarrer et de lancer les services enregistrés, mais systemctl échouait avec l'erreur D-Bus.

Pour moi, le lien manquant était l'absence du répertoire / run / systemd / system, découvert par straceing systemctl.

La création manuelle de ce répertoire avant d'exécuter systemctl permet à systemctl de fonctionner pour moi.

Chaim Geretz
la source