Você pode executar aplicativos GUI em um contêiner Docker?

Como você pode executar aplicativos GUI em um contêiner Docker ?

Existem imagens que configuram o vncserver ou algo assim para que você possa – por exemplo – adicionar uma sandbox de speedbump extra ao redor do Firefox?

    Você pode simplesmente instalar um vncserver junto com o Firefox 🙂

    Eu empurrei uma imagem, vnc / firefox, aqui: docker pull creack/firefox-vnc

    A imagem foi feita com este Dockerfile:

     # Firefox over VNC # # VERSION 0.1 # DOCKER-VERSION 0.2 FROM ubuntu:12.04 # Make sure the package repository is up to date RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list RUN apt-get update # Install vnc, xvfb in order to create a 'fake' display and firefox RUN apt-get install -y x11vnc xvfb firefox RUN mkdir ~/.vnc # Setup a password RUN x11vnc -storepasswd 1234 ~/.vnc/passwd # Autostart firefox (might not be the best way to do it, but it does the trick) RUN bash -c 'echo "firefox" >> /.bashrc' 

    Isso criará um contêiner do Docker executando o VNC com a senha 1234 :

    Para Docker versão 1.3 ou mais recente:

     docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create 

    Para o Docker antes da versão 1.3:

     docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create 

    Xauthority se torna um problema com os sistemas mais novos. Eu posso descartar qualquer proteção com xhost + antes de executar meus contêineres do Docker, ou posso passar um arquivo Xauthority bem preparado. Arquivos típicos do Xauthority são específicos do nome do host. Com a janela de encaixe, cada contêiner pode ter um nome de host diferente (definido com o docker run -h), mas mesmo definir o nome do host do contêiner como idêntico ao sistema host não ajudou no meu caso. xeyes (eu gosto deste exemplo) simplesmente ignoraria o cookie mágico e não passaria credenciais para o servidor. Por isso, recebemos uma mensagem de erro ‘Nenhum protocolo especificado Não é possível abrir a canvas’

    O arquivo Xauthority pode ser escrito de forma que o nome do host não importe. Precisamos definir a Família de Autenticação para ‘FamilyWild’. Não tenho certeza se xauth tem uma linha de comando apropriada para isso, então aqui está um exemplo que combina xauth e sed para fazer isso. Precisamos alterar os primeiros 16 bits da saída nlist. O valor de FamilyWild é 65535 ou 0xffff.

     docker build -t xeyes - < < __EOF__ FROM debian RUN apt-get update RUN apt-get install -qqy x11-apps ENV DISPLAY :0 CMD xeyes __EOF__ XSOCK=/tmp/.X11-unix XAUTH=/tmp/.docker.xauth xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes 

    Acabei de encontrar esta input no blog e quero compartilhá-la aqui com você, porque acho que é a melhor maneira de fazer isso e é tão fácil.

    http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

    PROS:
    + nenhum x servidor no contêiner docker
    + sem necessidade de cliente / servidor vnc
    + não ssh com x forwarding
    + contêineres muito menores

    CONS:
    – usando x no host (não destinado a sandbox seguro)

    no caso de o link falhar, algum dia eu coloquei a parte mais importante aqui:
    dockerfile:

     FROM ubuntu:14.04 RUN apt-get update && apt-get install -y firefox # Replace 1000 with your user / group id RUN export uid=1000 gid=1000 && \ mkdir -p /home/developer && \ echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \ echo "developer:x:${uid}:" >> /etc/group && \ echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \ chmod 0440 /etc/sudoers.d/developer && \ chown ${uid}:${gid} -R /home/developer USER developer ENV HOME /home/developer CMD /usr/bin/firefox 

    construa a imagem:

     docker build -t firefox . 

    e o comando de execução:

     docker run -ti --rm \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ firefox 

    claro que você também pode fazer isso no comando run com sh -c "echo script-here"

    DICA: para áudio, dê uma olhada: https://stackoverflow.com/a/28985715/2835523

    Com os volumes de dados do docker é muito fácil expor o soquete do domínio unix do xorg dentro do container.

    Por exemplo, com um Dockerfile como este:

     FROM debian RUN apt-get update RUN apt-get install -qqy x11-apps ENV DISPLAY :0 CMD xeyes 

    Você poderia fazer o seguinte:

     $ docker build -t xeyes - < Dockerfile $ XSOCK=/tmp/.X11-unix/X0 $ docker run -v $XSOCK:$XSOCK xeyes 

    Isto, obviamente, é essencialmente o mesmo que o X-forwarding. Ele concede ao contêiner access total ao xserver no host, portanto, é recomendado apenas se você confiar no que está dentro.

    Observação: se você estiver preocupado com segurança, uma solução melhor seria restringir o aplicativo ao controle de access obrigatório ou baseado em function . O Docker consegue um bom isolamento, mas foi projetado com um objective diferente em mente. Use o AppArmor , SELinux ou GrSecurity , que foram projetados para resolver sua preocupação.

    Você também pode usar o subutilizador: https://github.com/timthelion/subuser

    Isso permite que você empacote muitos aplicativos GUI no Docker. Firefox e emacs foram testados até agora. Com o firefox, o webGL não funciona. O Chromium não funciona de todo.

    EDIT: obras de som!

    EDIT2: No tempo desde que eu postei isso pela primeira vez, o subutilizador progrediu muito. Agora eu tenho um site subuser.org , e um novo modelo de segurança para conexão com o X11 via ponte XPRA .

    OSX

    Jürgen Weigert tem a melhor resposta que funcionou para mim no Ubuntu, no entanto, no OSX, o docker é executado dentro do VirtualBox e, portanto, a solução não funciona sem mais algum trabalho.

    Eu trabalhei com estes ingredientes adicionais:

    1. Xquartz (o OSX não é mais fornecido com o servidor X11)
    2. encaminhamento de soquete com socat (brew install socat)
    3. script bash para iniciar o contêiner

    Eu apreciaria comentários de usuários para melhorar esta resposta para OSX, não tenho certeza se o encaminhamento de soquete para X é seguro, mas meu uso pretendido é para executar o contêiner docker apenas localmente.

    Além disso, o script é um pouco frágil na medida em que não é fácil obter o endereço IP da máquina, já que ela está em nossa rede sem fio local, por isso, é sempre um IP random.

    O script BASH que uso para iniciar o contêiner:

     #!/usr/bin/env bash CONTAINER=py3:2016-03-23-rc3 COMMAND=/bin/bash NIC=en0 # Grab the ip address of this box IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print $2}') DISP_NUM=$(jot -r 1 100 200) # random display number between 100 and 200 PORT_NUM=$((6000 + DISP_NUM)) # so multiple instances of the container won't interfer with eachother socat TCP-LISTEN:${PORT_NUM},reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2>&1 > /dev/null & XSOCK=/tmp/.X11-unix XAUTH=/tmp/.docker.xauth.$USER.$$ touch $XAUTH xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - docker run \ -it \ --rm \ --user=$USER \ --workdir="/Users/$USER" \ -v "/Users/$USER:/home/$USER:rw" \ -v $XSOCK:$XSOCK:rw \ -v $XAUTH:$XAUTH:rw \ -e DISPLAY=$IPADDR:$DISP_NUM \ -e XAUTHORITY=$XAUTH \ $CONTAINER \ $COMMAND rm -f $XAUTH kill %1 # kill the socat job launched above 

    Eu sou capaz de obter xeyes e matplotlib trabalhando com essa abordagem.

    Windows 7+

    É um pouco mais fácil no Windows 7+ com o MobaXterm:

    1. Instale o MobaXterm para janelas
    2. Inicie o MobaXterm
    3. Configure o servidor X: Configurações -> X11 (guia) -> defina o Acesso Remoto X11 como completo
    4. Use este script BASH para iniciar o contêiner

    run_docker.bash :

     #!/usr/bin/env bash CONTAINER=py3:2016-03-23-rc3 COMMAND=/bin/bash DISPLAY="$(hostname):0" USER=$(whoami) docker run \ -it \ --rm \ --user=$USER \ --workdir="/home/$USER" \ -v "/c/Users/$USER:/home/$USER:rw" \ -e DISPLAY \ $CONTAINER \ $COMMAND 

    xeyes rodando no PC

    Aqui está uma solução leve que evita ter que instalar qualquer servidor X , servidor vnc ou daemon sshd no container. O que ganha em simplicidade perde em segurança e isolamento.

    Ele pressupõe que você se conecte à máquina host usando o ssh com o encaminhamento do X11 .

    Na configuração sshd do host, adicione a linha

     X11UseLocalhost no 

    Para que a porta do servidor X encaminhada no host seja aberta em todas as interfaces (não apenas lo ) e, em particular, na interface virtual do Docker, docker0 .

    O contêiner, quando executado, precisa de access ao arquivo .Xauthority para poder se conectar ao servidor. Para fazer isso, definimos um volume somente para leitura apontando para o diretório pessoal no host (talvez não seja uma boa idéia!) E também configuramos a variável XAUTHORITY acordo.

     docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority 

    Isso não é suficiente, nós também temos que passar a variável DISPLAY do host, mas substituindo o nome do host pelo ip:

     -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/") 

    Podemos definir um alias:

      alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")' 

    E teste assim:

     dockerX11run centos xeyes 

    Compartilhando a exibição do host: 0, conforme declarado em algumas outras respostas, tem duas desvantagens:

    • Ele quebra o isolamento do contêiner devido a alguns vazamentos de segurança X. Por exemplo, keylogging com xev ou xinput é possível.
    • Os aplicativos podem ter falhas de renderização e erros de access a RAM ruins devido à falta de memory compartilhada para a extensão X MIT-SHM.

    Para contornar os vazamentos de segurança X e para evitar o problema MIT-SHM, eu publiquei o x11docker no github . A idéia principal é rodar um segundo servidor X com seus próprios cookies de autenticação e com o MIT-SHM desabilitado. Os contêineres docker obtêm access ao novo servidor X e são segregados da exibição do host: 0. Não há dependencies X dentro da imagem, pois o X / Xephyr é fornecido pelo host.

    Abaixo um script de exemplo para executar uma imagem do docker no Xephyr. Ele espera alguns argumentos, primeiro um gerenciador de janelas do host para rodar no Xephyr, segundo uma imagem do docker, opcionalmente um terceiro comando de imagem a ser executado. Para executar um ambiente de área de trabalho no docker, use “:” em vez de um gerenciador de janelas do host. Em sistemas sem uma senha root, altere a variável $Getroot

    O Xephyr é iniciado usando o xinit. Um xinitrc personalizado é criado para criar um cookie, definir o layout do teclado, executar o gerenciador de janelas e executar o xterm com o xtermrc para solicitar a senha para executar o docker.

    Fechar a janela do Xephyr encerra os aplicativos do contêiner da janela de encaixe. Encerrar os aplicativos de encaixe fecha a janela Xephyr.

    Anotações:

    • O problema MIT-SHM também pode ser evitado com a opção docker --ipc=host , mas isso quebra o isolamento do contêiner e é desencorajado.
    • O cookie deve ser alterado para “familia wild”, como descrito por @ Jürgen Weigert, se o soquete X compartilhado for usado. Com X over tcp, isso não é necessário.
    • soluções semelhantes são possíveis com Xpra, Xorg e Xvnc
    • Para X over tcp, descubra o daemon docker ip (principalmente 172.17.42.1), compartilhe DISPLAY = 172.17.42.1: 1, crie um cookie para ele, não compartilhe o NewXsocket e não use a opção X / Xephyr -nolisten tcp. Usando X em tcp, o MIT-SHM é desabilitado automaticamente.

    Exemplos:

    • x11docker_example "openbox --sm-disable" x11docker/lxde pcmanfm
    • x11docker_example : x11docker/lxde

    Script x11docker_example:

     #! /bin/bash # x11docker_example : Example script to run docker GUI applications in Xephyr. # Look at x11docker on github: https://github.com/mviereck/x11docker # # Usage: # x11docker_example WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]] # # WINDOWMANAGER host window manager for use with single GUI applications. # To run a desktop environment in docker, use ":" # DOCKERIMAGE docker image containing GUI applications or a desktop # IMAGECOMMAND command to run in image # Windowmanager="$1" && shift Dockerimage="$*" # command to get root permissions to run docker Getroot="su -c" # Getroot="sudo su -c" # Use this on systems without a root password like Ubuntu or Sparky # define new display and its X socket. Newdisplay=:1 # To make sure $Newdisplay is not already in use, check /tmp/.Xn-lock [ -e "/tmp/.X1-lock" ] && echo "Error: Display :1 is already in use" >&2 && exit 1 NewXsocket=/tmp/.X11-unix/X1 # cache folder and files Cachefolder=/tmp/x11docker_example mkdir -p $Cachefolder Xclientcookie=$Cachefolder/Xcookie.client Xservercookie=$Cachefolder/Xcookie.server Xtermrc=$Cachefolder/xtermrc Xinitrc=$Cachefolder/xinitrc Dockerpidfile=$Cachefolder/docker.pid Dockerlogfile=$Cachefolder/docker.log # command to run docker # --rm created container will be discarded. # -e DISPLAY=$Newdisplay set environment variable to new display # -e XAUTHORITY=/Xcookie set environment variable XAUTHORITY to provided cookie # -v $Xclientcookie:/Xcookie:ro provide cookie file to container # -v $NewXsocket:$NewXsocket:ro Share new X socket of Xephyr Dockercommand="docker run --rm -e DISPLAY=$Newdisplay -e XAUTHORITY=/Xcookie -v $Xclientcookie:/Xcookie:ro -v $NewXsocket:$NewXsocket:ro $Dockerimage" # command to run X/Xephyr # /usr/bin/Xephyr an absolute path to X server executable must be given # $Newdisplay first argument has to be new display # -auth $Xservercookie path to cookie file for X server. Must be different from cookie file of client, not sure why # -nolisten tcp disable tcp connections for security reasons # -extension MIT-SHM disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it) # -retro nice retro look Xcommand="/usr/bin/Xephyr $Newdisplay -auth $Xservercookie -nolisten tcp -extension MIT-SHM -retro" # create xinitrc { echo "#! /bin/bash" echo "# set environment variables to new display and new cookie" echo "export DISPLAY=$Newdisplay" echo "export XAUTHORITY=$Xclientcookie" echo "# same keyboard layout as on host" echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - $Newdisplay" echo "# create new XAUTHORITY cookie file" echo ":> $Xclientcookie" echo "xauth generate $Newdisplay . untrusted" echo "cp $Xclientcookie $Xservercookie" echo "# create prepared cookie with localhost identification disabled by ffff," echo "# needed if X socket is shared instead connecting over tcp. ffff means 'familiy wild'" echo 'Cookie=$(xauth nlist '"$Newdisplay | sed -e 's/^..../ffff/')" echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -' echo "# run window manager in Xephyr" echo $Windowmanager' & Windowmanagerpid=$!' echo "# show docker log" echo 'tail --retry -n +1 -F '$Dockerlogfile' 2>/dev/null & Tailpid=$!' echo "# prompt for password" echo "xterm -title x11docker_example -e '/bin/bash $Xtermrc'" echo "# wait for docker to finish" echo 'Dockerpid=$(cat '$Dockerpidfile') && {' echo ' while [ -n "$(pgrep docker | grep $Dockerpid)" ] ; do' echo ' sleep 1' echo ' done }' [ "$Windowmanager" = ":" ] || echo 'kill $Windowmanagerpid' echo 'kill $Tailpid' } > $Xinitrc # create xtermrc for a password prompt { echo "#! /bin/bash" echo "echo 'x11docker_example will start docker on display $Newdisplay with command:'" echo "echo $Getroot '$Dockercommand'" echo "echo 'Please type in your password to run docker:'" echo "$Getroot 'nohup $Dockercommand 2>&1 1>$Dockerlogfile & echo "'$!'" > $Dockerpidfile'" } > $Xtermrc xinit $Xinitrc -- $Xcommand rm -Rf $Cachefolder 

    Isso não é leve, mas é uma boa solução que oferece paridade de resources do docker com virtualização de desktop completa. Tanto o Xfce4 quanto o IceWM para Ubuntu e CentOS funcionam, e a opção noVNC facilita o access por meio de um navegador.

    https://github.com/ConSol/docker-headless-vnc-container

    Ele roda o noVNC , assim como o tigerVNC do tigerVNC. Em seguida, ele chama startx para determinado gerenciador de janelas. Além disso, o libnss_wrapper.so é usado para emular o gerenciamento de senhas para os usuários.

    A solução dada em http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ parece ser uma maneira fácil de iniciar aplicativos GUI de dentro dos containers (eu tentei para o firefox sobre o Ubuntu 14.04), mas descobri que uma pequena mudança adicional é necessária para a solução postada pelo autor.

    Especificamente, para executar o contêiner, o autor mencionou:

      docker run -ti --rm \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ firefox 

    Mas eu achei que (com base em um comentário em particular no mesmo site) que duas opções adicionais

      -v $HOME/.Xauthority:$HOME/.Xauthority 

    e

      -net=host 

    precisa ser especificado durante a execução do contêiner para que o firefox funcione corretamente:

      docker run -ti --rm \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -v $HOME/.Xauthority:$HOME/.Xauthority \ -net=host \ firefox 

    Eu criei uma imagem de janela de encaixe com as informações nessa página e essas descobertas adicionais: https://hub.docker.com/r/amanral/ubuntu-firefox/

    Há outra solução do lord.garbage para executar aplicativos GUI em um contêiner sem usar o encaminhamento VNC, SSH e X11. É mencionado aqui também.

    Se você deseja executar um aplicativo GUI sem cabeça, leia aqui . O que você precisa fazer é criar um monitor virtual com o xvfb ou outro software similar. Isso é muito útil se você deseja executar testes do Selenium, por exemplo, com navegadores.

    Algo não mencionado em nenhum lugar é que alguns softwares realmente usam boxe de areia com containers Linux. Por exemplo, o Chrome nunca funcionará normalmente se você não usar o sinalizador apropriado – --privileged ao executar o contêiner.

    Com base na resposta de Jürgen Weigert , tenho algumas melhorias:

     docker build -t xeyes - < < __EOF__ FROM debian RUN apt-get update RUN apt-get install -qqy x11-apps ENV DISPLAY :0 CMD xeyes __EOF__ XSOCK=/tmp/.X11-unix XAUTH_DIR=/tmp/.docker.xauth XAUTH=$XAUTH_DIR/.xauth mkdir -p $XAUTH_DIR && touch $XAUTH xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - docker run -ti -v $XSOCK:$XSOCK -v $XAUTH_DIR:$XAUTH_DIR -e XAUTHORITY=$XAUTH xeyes 

    A única diferença é que ele cria um diretório $ XAUTH_DIR que é usado para colocar o arquivo $ XAUTH e o diretório $ XAUTH_DIR em vez do arquivo $ XAUTH no contêiner docker.

    O benefício deste método é que você pode escrever um comando em /etc/rc.local que é criar uma pasta vazia chamada $ XAUTH_DIR em / tmp e mudar seu modo para 777.

     tr '\n' '\000' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null sudo sed -i 's|\x00XAUTH_DIR=.*\x00\x00|\x00|' /etc/rc.local >/dev/null tr '\000' '\n' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null sudo sed -i 's|^exit 0.*$|XAUTH_DIR=/tmp/.docker.xauth; rm -rf $XAUTH_DIR; install -m 777 -d $XAUTH_DIR\n\nexit 0|' /etc/rc.local 

    Quando o sistema for reiniciado, antes do login do usuário, o docker montará o diretório $ XAUTH_DIR automaticamente se a política de reboot do contêiner estiver "sempre". Após o login do usuário, você pode escrever um comando em ~ / .profile que é criar o arquivo $ XAUTH, então o contêiner usará automaticamente esse arquivo $ XAUTH.

     tr '\n' '\000' < ~/.profile | sudo tee ~/.profile >/dev/null sed -i 's|\x00XAUTH_DIR=.*-\x00|\x00|' ~/.profile tr '\000' '\n' < ~/.profile | sudo tee ~/.profile >/dev/null echo "XAUTH_DIR=/tmp/.docker.xauth; XAUTH=\$XAUTH_DIR/.xauth; touch \$XAUTH; xauth nlist \$DISPLAY | sed -e 's/^..../ffff/' | xauth -f \$XAUTH nmerge -" >> ~/.profile 

    Afinal, o contêiner obterá automaticamente o arquivo Xauthority sempre que o sistema for reiniciado e o login do usuário.

    Para renderização OpenGL com o driver Nvidia, use a seguinte imagem:

    https://github.com/thewtex/docker-opengl-nvidia

    Para outras implementações do OpenGL, certifique-se de que a imagem tenha a mesma implementação que o host.

    Estou atrasado para a festa, mas para usuários de Mac que não querem ir pelo caminho XQuartz, aqui está um exemplo de trabalho que constrói uma imagem do Fedora, com um ambiente de desktop (xfce) usando Xvfb e VNC . É simples e funciona:

    Em um Mac, você pode acessá-lo usando o aplicativo Screen Sharing (padrão), conectando-se ao localhost:5901 .

    Dockerfile:

     FROM fedora USER root # Set root password, so I know it for the future RUN echo "root:password123" | chpasswd # Install Java, Open SSL, etc. RUN dnf update -y --setopt=deltarpm=false \ && dnf install -y --setopt=deltarpm=false \ openssl.x86_64 \ java-1.8.0-openjdk.x86_64 \ xorg-x11-server-Xvfb \ x11vnc \ firefox \ @xfce-desktop-environment \ && dnf clean all # Create developer user (password: password123, uid: 11111) RUN useradd -u 11111 -g users -d /home/developer -s /bin/bash -p $(echo password123 | openssl passwd -1 -stdin) developer # Copy startup script over to the developer home COPY start-vnc.sh /home/developer/start-vnc.sh RUN chmod 700 /home/developer/start-vnc.sh RUN chown developer.users /home/developer/start-vnc.sh # Expose VNC, SSH EXPOSE 5901 22 # Set up VNC Password and DisplayEnvVar to point to Display1Screen0 USER developer ENV DISPLAY :1.0 RUN mkdir ~/.x11vnc RUN x11vnc -storepasswd letmein ~/.x11vnc/passwd WORKDIR /home/developer CMD ["/home/developer/start-vnc.sh"] 

    start-vnc.sh

     #!/bin/sh Xvfb :1 -screen 0 1024x768x24 & sleep 5 x11vnc -noxdamage -many -display :1 -rfbport 5901 -rfbauth ~/.x11vnc/passwd -bg sleep 2 xfce4-session & bash # while true; do sleep 1000; done 

    Verifique o readme vinculado para obter comandos de compilation e execução, se desejar / precisar.

    Você pode permitir que o usuário do Docker (aqui: root) acesse a exibição do X11:

     XSOCK=/tmp/.X11-unix xhost +SI:localuser:root docker run -t -i --rm -v $XSOCK:$XSOCK:ro -e DISPLAY=unix$(DISPLAY) image xhost -SI:localuser:root 

    Embora a resposta de Jürgen Weigert cubra essencialmente essa solução, não estava claro para mim, a princípio, o que estava sendo descrito ali. Então, eu adicionarei minha opinião sobre isso, caso alguém precise de esclarecimento.

    Primeiramente, a documentação relevante é a página de segurança X.

    Várias fonts on-line sugerem apenas a assembly do soquete X11 unix e o arquivo ~/.Xauthority no contêiner. Essas soluções geralmente funcionam por sorte, sem realmente entender por que, por exemplo, o usuário do contêiner acaba com o mesmo UID do usuário, portanto, não há necessidade de autorização de chave mágica.

    Primeiro, o arquivo Xauthority possui o modo 0600, portanto, o usuário do contêiner não poderá lê-lo, a menos que tenha o mesmo UID.

    Mesmo se você copiar o arquivo no contêiner e alterar a propriedade, ainda haverá outro problema. Se você executar a xauth list no host e no contêiner, com o mesmo arquivo Xauthority , verá inputs diferentes listadas. Isso ocorre porque o xauth filtra as inputs dependendo de onde elas são executadas.

    O cliente X no container (isto é, o aplicativo GUI) se comportará da mesma forma que o xauth . Em outras palavras, ele não vê o magic cookie para a session X em execução na área de trabalho do usuário. Em vez disso, ele vê as inputs para todas as sessões X “remotas” que você abriu anteriormente (explicadas abaixo).

    Então, o que você precisa fazer é adicionar uma nova input com o nome do host do container ea mesma chave hexagonal que o cookie do host (ou seja, a session X em execução na sua área de trabalho), por exemplo:

     containerhostname/unix:0 MIT-MAGIC-COOKIE-1  

    O problema é que o cookie deve ser adicionado com o xauth add dentro do container:

     touch ~/.Xauthority xauth add containerhostname/unix:0 .  

    Caso contrário, o xauth uma maneira que é visto apenas fora do contêiner.

    O formato deste comando é:

     xauth add hostname/$DISPLAY protocol hexkey 

    Onde . representa o protocolo MIT-MAGIC-COOKIE-1 .

    Nota: Não há necessidade de copiar ou vincular a assembly .Xauthority no contêiner. Basta criar um arquivo em branco, como mostrado, e adicionar o cookie.

    A resposta de Jürgen Weigert contorna isso usando o tipo de conexão FamilyWild para criar um novo arquivo de autoridade no host e copiá-lo no contêiner. Observe que primeiro extrai a chave hexadecimal para a session X atual de ~/.Xauthority usando xauth nlist .

    Então os passos essenciais são:

    • Extraia a chave hexagonal do cookie para a session X atual do usuário.
    • Crie um novo arquivo Xauthority no contêiner, com o nome do host do contêiner e a chave hexadecimal compartilhada (ou crie um cookie com o tipo de conexão FamilyWild ).

    Eu admito que não entendo muito bem como o FamilyWild funciona, ou como os clientes xauth ou X filtram as inputs do arquivo Xauthority, dependendo de onde elas são executadas. Informações adicionais sobre isso são bem-vindas.

    Se você quiser distribuir seu aplicativo Docker, precisará de um script de início para executar o contêiner que obtém a chave hexadecimal para a session X do usuário e o importa para o contêiner de uma das duas maneiras explicadas anteriormente.

    It also helps to understand the mechanics of the authorization process:

    • An X client (ie GUI application) running in the container looks in the Xauthority file for a cookie entry that matches the container’s hostname and the value of $DISPLAY .
    • If a matching entry is found, the X client passes it with its authorization request to the X server, through the appropriate socket in the /tmp/.X11-unix directory mounted in the container.

    Note: The X11 Unix socket still needs to be mounted in the container, or the container will have no route to the X server. Most distributions disable TCP access to the X server by default for security reasons.

    For additional information, and to better grasp how the X client/server relationship works, it’s also helpful to look at the example case of SSH X forwarding:

    • The SSH server running on a remote machine emulates its own X server.
    • It sets the value of $DISPLAY in the SSH session to point to its own X server.
    • It uses xauth to create a new cookie for the remote host, and adds it to the Xauthority files for both the local and remote users.
    • When GUI apps are started, they talk to SSH’s emulated X server.
    • The SSH server forwards this data back to the SSH client on your local desktop.
    • The local SSH client sends the data to the X server session running on your desktop, as if the SSH client was actually an X client (ie GUI app).
    • The X server uses the received data to render the GUI on your desktop.
    • At the start of this exchange, the remote X client also sends an authorization request, using the cookie that was just created. The local X server compares it with its local copy.

    The other solutions should work, but here is a solution for docker-compose .

    To fix that error, you need to pass $DISPLAY and .X11-unix to docker, as well as grant the user who started docker access to xhost.

    Within docker-compose.yml: version: '2' services: node: build: . container_name: node environment: - DISPLAY volumes: - /tmp/.X11-unix:/tmp/.X11-unix

    In terminal or script:

    • xhost +si:localuser:$USER
    • xhost +local:docker
    • export DISPLAY=$DISPLAY
    • docker-compose up

    OSX (10.13.6, high sierra)

    Similar to @Nick ‘s answer, but his solution did not work for me.

    First install socat by doing brew install socat , and install XQuartz ( https://www.xquartz.org/ )

    Then followed these steps here ( http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ ) in the comments section:

     1. in one mac terminal i started: socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2. and in another mac terminal I ran: docker run -ti --rm \ -e DISPLAY=$(ipconfig getifaddr en0):0 \ -v /tmp/.X11-unix:/tmp/.X11-unix \ firefox 

    I was also able to launch CLion from my debian docker container too.