falha ao obter a conexão D-Bus: operação não permitida

29

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 pode ser o problema?

Snowcrash
fonte
1
Você não usou sudo?
Michael Hampton
Você não deve usar o systemd, se não precisar. Tente iniciar o aplicativo sem ele no CMD ou no RUN ou usando um script de wrapper.
nelaaro
Se você precisar systemddo CentOS, use esta imagem: FROM centos/systemd
james.garriss

Respostas:

24

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

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

Portanto, aqui estão algumas etapas sobre como executar o CentOS com o systemd dentro de um contêiner do Docker:

  1. Pull 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 - docker build --rm -t centos7-systemd - < mydockerfile
  2. Execute 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 systemd no seu contêiner

13dimitar
fonte
Muito arrumado! No entanto, pelo menos estou recebendo mais informações agora. Aqui está o que eu registro:[ 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
Caso eu não estivesse claro! Eu ainda estou recebendo o erroFailed to get D-Bus connection: Operation not permitted
Snowcrash
Você construiu sua própria imagem a partir do Dockerfile copiado em minha resposta, executa um contêiner a partir dessa imagem e ainda recebe um erro?
13dimitar
4
Bingo! Eu estava executando o contêiner /bin/bashpara obter uma concha. No entanto, isso me deu o erro mencionado anteriormente. Quando eu corri com /usr/sbin/inito sugerido, em seguida, anexado com uma concha, tudo correu bem. Claramente, estou sentindo falta de uma nuance /usr/sbin/init. Esta resposta merece alguma votação substancial.
Snowcrash
Estou nessa há 2 dias, e ainda não consigo descobrir o que /sys/fs/cgroup:/sys/fs/cgroupé ou de onde ela vem ... Eu sei como montar a pasta de convidados em um histórico como: /src/:/var/wwwmas de onde vem o seu arquivo? É causando-me muitos erros porque eu colou o código, eu estou pensando que eu deveria criar aqueles em algum lugar
samayo
4

Esta não é uma resposta direta à sua pergunta, mas pode ser realmente mais importante, e me deparei com essa percepção enquanto lia as outras respostas aqui.

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

Uma razão muito significativa para isso é que o Docker não desligará corretamente os serviços iniciados com o systemctl e, de fato, você poderá acabar com o mesmo tipo de corrupção de banco de dados resultante de uma falta de energia inesperada.

Para aprofundar isso um pouco mais: quando o Docker emite um comando "stop" para um contêiner, ele envia ao sinal SIGTERM apenas o processo único iniciado com o CMD / ENTRYPOINT, e não a todos os serviços e daemons. Para que um serviço tenha o aviso de desligamento limpo e todos os outros sejam encerrados sem cerimônia.

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

Um adendo

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

Murray Todd Williams
fonte
2

Consegui corrigir esse problema em um contêiner do CentOS: 7 Docker. Acompanhei principalmente o projeto de imagem do 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 seguintes argumentos para docker runcomandar:-v /run -v /sys/fs/cgroup:/sys/fs/cgroup:ro

O ponto principal é que /usr/sbin/initdeve 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 seu 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ê poderia ter, System is booting up. See pam_nologin(8)se estiver usando o sistema PAM, nesse caso, excluir /usr/lib/tmpfiles.d/systemd-nologin.confno seu Dockerfileporque ele cria o arquivo /var/run/nologinque gera esse erro específico.

Anthony O.
fonte
systemd-nologin.conf / nologin for the win because CentOS/RHEL 7 claims UsePAM no is unsupported and will complain in logs as such. Not sure if RH openssh portable patched / broke it somehow or they're trying to lower their support surface from novice customers.
1

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

Isso permitiu ao systemd iniciar e iniciar os serviços registrados, mas systemctl estava falhando com o erro do D-Bus.

Para mim, o link que faltava era a ausência do diretório / run / systemd / system, descoberto por straceing systemctl.

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

Chaim Geretz
fonte