Alternativas para o encaminhamento ssh X11 para contêineres Docker

Eu estou executando um contêiner Docker principalmente como um ambiente de desenvolvimento isolado para a linguagem R (O uso de R aqui é ortogonal ao resto do post, ou seja, você pode simplesmente assumir qualquer programa genérico que possa ser executado em uma session de repl .) Muitas vezes isso envolve fazer coisas como plotagem, criação de charts e assim por diante. ; e eu preciso olhar para isso. Por isso, eu preferiria ter a opção de exibir charts que criei no meu contêiner. Aqui está como eu faço isso até agora. Primeiro eu crio um Dockerfile . Deixando de lado os passos triviais, os mais relevantes são:

 # Set root passwd RUN echo "root:test" | chpasswd # Add user so that container does not run as root RUN useradd -m docker RUN echo "docker:test" | chpasswd RUN usermod -s /bin/bash docker RUN usermod -aG sudo docker ENV HOME /home/docker RUN mkdir /var/run/sshd RUN mkdir -p /var/log/supervisor # copy servisord.conf which lists the processes to be spawned once this # container is started (currently only one: sshd) COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf EXPOSE 22 CMD ["/usr/bin/supervisord"] 

Eu construo a imagem e, em seguida, inicio o contêiner usando:

 docker run -d -p 127.0.0.1:5000:22 -h ubuntu-r -v /home/chb/files/Data:/home/docker/Data -P --name="rdev" ubuntu-r 

e, em seguida, pode ssh no meu contêiner:

 ssh -X docker@localhost -p 5000. 

Isso vai me dar o que eu quero. Mas gostaria de saber se existe outra maneira mais fácil de obter charts / saída de GUI de um contêiner? (Eu preferiria, se possível, soluções não envolveriam vnc .)

Existe uma maneira agradável e semi-fácil de obter saída gráfica de um contêiner Docker sem ter que executar um daemon sshd dentro do contêiner. O Docker pode fornecer desempenho bare-metal ao executar um único processo que, nesse caso, deve ser R A execução de um daemon sshd, por mais marginal que seja, introduz uma sobrecarga adicional. Isso não é feito melhor executando o daemon sshd como um processo filho do daemon de supervisor. Ambos podem ser dispensados ​​quando se faz um bom uso de montagens de ligamento. Depois de construir a imagem a partir da qual o contêiner deve ser executado, iniciamos um contêiner interativo e ligamos a pasta /tmp/.X11-unix nele. Eu declararei o comando completo e explicarei em detalhes o que ele faz:

docker run -i -t –rm \

  • -i configura uma session interativa; -t aloca um pseudo tty; --rm torna esse contêiner efêmero

-e DISPLAY = $ DISPLAY \

  • define a exibição do host para a exibição das máquinas locais (que normalmente será :0 )

-u docker \

  • -u especifica que o processo deve ser executado por um usuário (aqui docker ) e não por root. Este passo é importante (vi)!

-v /tmp/.X11-unix:/tmp/.X11-unix:ro \

  • -v bind monta o socket X11 reside em /tmp/.X11-unix em sua máquina local em /tmp/.X11-unix no container e :ro faz o soquete somente leitura.

–name = “rdev” ubuntu-r

  • --name="" especifica o nome do container (aqui rdev ); a imagem da qual você deseja executar o container (aqui ubuntu-r ); o processo que você deseja executar no contêiner (aqui R ). (A última etapa da especificação de um processo só é necessária se você não tiver definido um CMD ou ENTRYPOINT padrão para sua imagem.)

Depois de emitir este comando, você deve estar olhando para a bela saída de partida R Se você fosse tentar uma demo(graphics) para ver se a saída gráfica já está funcionando, você notaria que não é. Isso é devido à extensão Xsecurity impedindo que você acesse o soquete. Agora você pode digitar xhost + em sua máquina local e tentar uma demo(graphics) em seu contêiner novamente. Agora você deve ter saída gráfica. Esse método, no entanto, não é recomendado, já que você permite o access ao seu xsocket a qualquer host remoto ao qual você esteja conectado atualmente. Contanto que você esteja interagindo apenas com sistemas de usuário único, isso pode ser de alguma forma justificável, mas assim que houver vários usuários envolvidos, isso será absolutamente inseguro! Portanto, você deve usar um método menos perigoso. Uma boa maneira é usar o servidor interpretado

 xhost +si:localuser:username 

que pode ser usado para especificar um único usuário local (veja man xhost ). Isso significa que username deve ser o nome do usuário que executa o servidor X11 em sua máquina local e que executa o contêiner docker. Essa também é a razão pela qual é importante especificar um usuário ao executar seu contêiner. Por último, mas não menos importante, existe sempre a solução mais complexa de usar os arquivos xauth e .Xauthority para conceder access ao soquete X11 (consulte man xauth ). No entanto, isso também envolverá um pouco mais de conhecimento sobre como o X funciona.

O efeito positivo que isso pode ter pode ser visto no número de processos que precisam ser executados para atingir o desejado.

(1) com supervisor e sshd rodando no container:

 UID PID PPID C STIME TTY TIME CMD root 4564 718 1 18:16 ? 00:00:00 /usr/bin/python /usr/bin/supervisord root 4576 4564 0 18:16 ? 00:00:00 /usr/sbin/sshd 

quando logado via ssh e executando R :

 UID PID PPID C STIME TTY TIME CMD root 4564 718 0 18:16 ? 00:00:00 /usr/bin/python /usr/bin/supervisord root 4576 4564 0 18:16 ? 00:00:00 /usr/sbin/sshd root 4674 4576 0 18:17 ? 00:00:00 sshd: docker [priv] chb 4725 4674 0 18:18 ? 00:00:00 sshd: docker@pts/0 chb 4728 4725 1 18:18 pts/0 00:00:00 -bash 

(2) com o método de assembly de binding:

 UID PID PPID C STIME TTY TIME CMD chb 4356 718 0 18:12 pts/4 00:00:00 /usr/local/lib/R/bin/exec/R --no-save --no-restore 

Aqui está claramente a melhor solução que encontrei até agora:

https://stackoverflow.com/a/25280523/1353930 (todos os créditos vão para Jürgen Weigert)

Vantagens:

  • Dentro do docker, o UID não é relevante (mas eu ainda recomendo não usar root)
  • No host, você não precisa alterar as configurações de segurança ( xhost + )
Intereting Posts