não conseguiu obter conexão D-Bus: Operação não permitida

22

Estou tentando listar serviços na minha imagem do CentOS em execução no Docker usando

systemctl list-units  

mas recebo esta mensagem de erro:

Failed to get D-Bus connection: Operation not permitted

Alguma sugestão de qual é o problema?

    
por Snowcrash 08.01.2017 / 21:35

4 respostas

14

Meu palpite é que você está executando um contêiner non-privileged . O systemd requer o recurso CAP_SYS_ADMIN, mas o Docker descarta esse recurso nos contêineres não privilegiados, para incluir mais segurança.

O

systemd também requer acesso RO ao sistema de arquivos cgroup dentro de um contêiner. Você pode adicioná-lo com –v /sys/fs/cgroup:/sys/fs/cgroup:ro

Então, aqui estão alguns passos sobre como executar o CentOS com o systemd dentro de um contêiner Docker:

  1. Puxe a imagem centos
  2. Configure um arquivo docker como o abaixo:

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. Construa-o - docker build --rm -t centos7-systemd - < mydockerfile
  2. Executar um contêiner com docker run --privileged -ti -e container=docker -v /sys/fs/cgroup:/sys/fs/cgroup centos7-systemd /usr/sbin/init

  3. Você deve ter o systemd no seu contêiner

por 09.01.2017 / 08:53
2

Consegui corrigir esse problema em um contêiner do CentOS: 7 Docker. Eu segui principalmente o projeto de imagem Guide on 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"]

Agora, crie a imagem e execute-a usando pelo menos os argumentos a seguir no comando docker run : -v /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro

O ponto principal é que /usr/sbin/init deve ser o primeiro processo dentro do contêiner do Docker.

Portanto, se você quiser usar um script personalizado que execute alguns comandos antes de executar /usr/sbin/init , inicie-o no final do script usando exec /usr/sbin/init (em um script bash).

Aqui está um exemplo:

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

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

E aqui está o conteúdo 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

Você pode ter System is booting up. See pam_nologin(8) se estiver usando o sistema PAM, nesse caso, exclua /usr/lib/tmpfiles.d/systemd-nologin.conf no seu Dockerfile porque ele cria o arquivo /var/run/nologin que gera esse erro específico.

    
por 01.03.2017 / 15:26
2

Esta não é uma resposta direta à sua pergunta, mas na verdade pode ser mais importante, e me deparei com essa percepção, pois estava lendo as outras respostas aqui.

Eu tive alguma experiência de migração de alguns sistemas complicados para o Docker, e uma das realizações importantes que tive foi que você deveria idealmente ter um contêiner Docker por aplicativo / serviço ou "por daemon".

Uma razão muito significativa para isso é que o Docker não encerrará os serviços que você inicia com systemctl e, na verdade, poderá acabar com o mesmo tipo de corrupção de banco de dados proveniente de uma queda de energia inesperada .

Para aprofundar isso um pouco mais: quando o Docker emite um comando "stop" para um contêiner, ele envia o sinal SIGTERM somente para o único processo que foi iniciado com o CMD / ENTRYPOINT, não para todos os serviços e daemons. De modo que um serviço tenha o aviso para encerrar de forma limpa e todos os outros terminem sem cerimônias.

Se você tiver que empacotar dois serviços no mesmo contêiner (ou seja, seu aplicativo e um banco de dados PostgreSQL ou algo parecido), será necessário que seu CMD / ENTRYPOINT seja um script que capture SIGTERM e retransmita-o para os conhecidos Serviços. Isso pode ser feito, mas se você tiver a oportunidade, repensar sua solução e tentar dividi-la em vários contêineres.

Um adendo

Há uma nota / página interessante no site do Docker sobre como usar o supervisord se você realmente precisar ter vários serviços em execução no mesmo contêiner.

    
por 18.05.2018 / 15:22
0

Eu não queria ter que iniciar o systemd como init / PID 1. Depois de executar as etapas de limpeza mencionadas por outras pessoas, eu inicio o systemd a partir de um script de inicialização como /usr/lib/systemd/systemd --system & .

Isso permitiu que o systemd iniciasse e lançasse os serviços registrados, mas o systemctl estava falhando com o erro do D-Bus.

Para mim, o elo perdido foi a ausência do diretório / run / systemd / system, descoberto por strace ing systemctl.

Criar este diretório manualmente antes de executar o systemctl permite que o systemctl funcione para mim.

    
por 09.08.2018 / 19:45