no se pudo obtener la conexión D-Bus: operación no permitida

29

Estoy tratando de enumerar servicios en mi imagen CentOS que se ejecuta en Docker usando

systemctl list-units  

pero recibo este mensaje de error:

Failed to get D-Bus connection: Operation not permitted

¿Alguna sugerencia de cuál podría ser el problema?

Snowcrash
fuente
1
¿No lo usaste sudo?
Michael Hampton
No debería usar systemd, si no lo necesita. Intente iniciar la aplicación sin ella en CMD o RUN, o usando un script de envoltura.
nelaaro
Si necesita systemdCentOS, use esta imagen: FROM centos/systemd
james.garriss

Respuestas:

24

Supongo que estás ejecutando un non-privilegedcontenedor. systemd requiere la capacidad CAP_SYS_ADMIN pero Docker elimina esa capacidad en los contenedores no privilegiados, para agregar más seguridad.

systemd también requiere acceso de RO al sistema de archivos cgroup dentro de un contenedor. Puedes agregarlo con–v /sys/fs/cgroup:/sys/fs/cgroup:ro

Entonces, aquí hay algunos pasos sobre cómo ejecutar CentOS con systemd dentro de un contenedor Docker:

  1. Imagen de centos de extracción
  2. Configure un archivo acoplable como el siguiente:
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. Constrúyelo - docker build --rm -t centos7-systemd - < mydockerfile
  2. Ejecute un contenedor con docker run --privileged -ti -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup centos7-systemd /usr/sbin/init

  3. Deberías tener systemd en tu contenedor

13dimitar
fuente
¡Con buena pinta! Sin embargo, al menos obtengo más información ahora. Esto es lo que logré registrar:[ 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
En caso de que no estuviera claro! Todavía recibo el errorFailed to get D-Bus connection: Operation not permitted
Snowcrash
¿Has creado tu propia imagen del Dockerfile copiado en mi respuesta, ejecutas un contenedor a partir de esa imagen y aún obtienes un error?
13dimitar
44
¡Bingo! Estaba ejecutando el contenedor con el /bin/bashfin de obtener un shell. Sin embargo, esto me dio el error mencionado anteriormente. Cuando lo ejecuté con /usr/sbin/initlo sugerido, luego adjunto con un caparazón todo salió bien. Claramente me estoy perdiendo un matiz al respecto /usr/sbin/init. Esta respuesta merece una votación considerable.
Snowcrash
He estado en esto durante 2 días, y todavía no puedo entender qué /sys/fs/cgroup:/sys/fs/cgroupes o de dónde viene ... Sé cómo montar la carpeta de invitados en hist como: /src/:/var/wwwpero ¿de dónde viene tu archivo? Me está causando muchos errores porque pegué el código, creo que debería crearlos en algún lugar
samayo
4

Esta no es una respuesta directa a su pregunta, pero en realidad puede ser más importante, y me di cuenta de esto al leer las otras respuestas aquí.

He tenido cierta experiencia migrando algunos sistemas complicados a Docker, y una de las realizaciones importantes que he tenido es que lo ideal es tener un contenedor Docker por aplicación / servicio o "por demonio".

Una razón muy importante para esto es que Docker no cerrará limpiamente los servicios que comience con systemctl y, de hecho, puede terminar con el mismo tipo de corrupción de la base de datos que proviene de un corte de energía inesperado.

Para profundizar un poco más en esto: cuando Docker emite un comando de "detención" a un contenedor, envía la señal SIGTERM solo al único proceso que se inició con el CMD / ENTRYPOINT, no a todos los servicios y demonios. Para que un servicio tenga la advertencia de que se apague limpiamente y todos los demás se terminen sin ceremonias.

Si absolutamente tiene que empaquetar dos servicios en el mismo contenedor (es decir, su aplicación y una base de datos PostgreSQL o algo así), entonces necesita que su CMD / ENTRYPOINT sea un script que capture SIGTERM y luego lo retransmita a esos servicios conocidos. Se puede hacer, pero si tiene la oportunidad, reconsidere su solución e intente dividirla en varios contenedores.

Un apéndice

Hay una nota / página interesante en el sitio de Docker sobre el uso de supervisión si realmente necesita tener múltiples servicios ejecutándose en el mismo contenedor.

Murray Todd Williams
fuente
2

Me las arreglé para solucionar este problema en un contenedor CentOS: 7 Docker. He seguido principalmente la guía del proyecto de imagen 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"]

Ahora, construya la imagen y ejecútela usando al menos los siguientes argumentos para docker runordenar:-v /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro

Entonces el punto principal es que /usr/sbin/initdebe ser el primer proceso dentro del contenedor Docker.

Entonces, si desea usar un script personalizado que ejecute algunos comandos antes de ejecutarlo /usr/sbin/init, inícielo al final de su script usando exec /usr/sbin/init(en un script bash).

Aquí hay un ejemplo:

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

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

Y aquí está el contenido 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

Podría haberlo hecho System is booting up. See pam_nologin(8)si está utilizando el sistema PAM, en ese caso, eliminar /usr/lib/tmpfiles.d/systemd-nologin.confen su Dockerfileporque crea el archivo /var/run/nologinque genera este error específico.

Anthony O.
fuente
systemd-nologin.conf/ nologinpor la victoria porque las reclamaciones de CentOS / RHEL 7 UsePAM nono son compatibles y se quejarán en los registros como tales. No estoy seguro si RH openssh portátil parcheado / roto de alguna manera o si están tratando de reducir su superficie de soporte de clientes novatos.
1

No quería tener que iniciar systemd como init / PID 1. Después de realizar los pasos de limpieza mencionados por otros, inicio systemd desde un script de inicio como /usr/lib/systemd/systemd --system &.

Esto permitió que systemd iniciara e iniciara los servicios registrados, pero systemctl estaba fallando con el error D-Bus.

Para mí, el enlace que faltaba era la ausencia del directorio / run / systemd / system, descubierto por straceing systemctl.

Crear este directorio manualmente antes de ejecutar systemctl permite que systemctl funcione para mí.

Jaim Geretz
fuente