Bisakah Anda menjalankan aplikasi GUI dalam wadah Docker?

409

Bagaimana Anda bisa menjalankan aplikasi GUI dalam wadah Docker ?

Apakah ada gambar yang mengatur vncserveratau sesuatu sehingga Anda dapat - misalnya - menambahkan kotak pasir speedbump tambahan di sekitar katakanlah Firefox?

Akan
sumber
Pertanyaan ini tampaknya hanya berkaitan dengan Linux (berdasarkan usia dan konten jawaban) dan bukan Windows. Jika demikian, dapatkah kita mengedit judul untuk memperjelas ini? Terima kasih
UuDdLrLrSs
Periksa Panduan Pengguna Wadah Visualisasi HPC untuk beberapa ide.
kenorb

Jawaban:

238

Anda cukup menginstal vncserver bersama dengan Firefox :)

Saya mendorong gambar, vnc / firefox, di sini: docker pull creack/firefox-vnc

Gambar telah dibuat dengan Dockerfile ini:

# 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'

Ini akan membuat wadah Docker yang menjalankan VNC dengan kata sandi 1234:

Untuk Docker versi 18 atau lebih baru:

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

Untuk Docker versi 1.3 atau lebih baru:

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

Untuk Docker sebelum versi 1.3:

docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
creack
sumber
2
Bagaimana saya menggunakan klien VNC untuk melihat ini dari jarak jauh? Mengetik di port IP + sepertinya tidak berfungsi.
user94154
17
Pertama, Anda perlu memeriksa port yang dialokasikan (dengan melakukan docker inspect <container id>atau hanya docker ps, kemudian Anda terhubung ke ip host Anda dengan port yang baru saja Anda temukan.
creack
9
gambar creackfirefox-vnc gagal karena kesalahan: Masukkan kata sandi VNC: stty: input standar: ioctl yang tidak sesuai untuk perangkat: Tidak ada file atau direktori stty: input standar: ioctl yang tidak sesuai untuk perangkat x11vnc -usepw: tidak dapat menemukan kata sandi untuk digunakan.
alfonsodev
6
Gunakan buruh pelabuhan dengan baik> Menjalankan aplikasi GUI dengan Docker fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker
Dennis C
7
Tidak ada nama pengguna, kata sandi jelas ditunjukkan dalam jawaban dan klien vnc akan melakukannya. Dalam kasus saya, saya suka yang asli OSX. (dari finder, tekan perintah + K dan sambungkan ke vnc: // <docker ip>: <container container port>)
creack
195

Xauthority menjadi masalah dengan sistem yang lebih baru. Saya bisa membuang perlindungan dengan xhost + sebelum menjalankan wadah buruh pelabuhan saya, atau saya bisa mengirimkan file Xauthority yang dipersiapkan dengan baik. File Xauthority yang tipikal adalah spesifik hostname. Dengan buruh pelabuhan, setiap wadah dapat memiliki nama host yang berbeda (ditetapkan dengan buruh pelabuhan run-h), tetapi bahkan mengatur nama host wadah yang identik dengan sistem host tidak membantu dalam kasus saya. xeyes (saya suka contoh ini) hanya akan mengabaikan cookie ajaib dan tidak memberikan kredensial ke server. Karenanya kami mendapatkan pesan kesalahan 'Tidak ada protokol yang ditentukan Tidak dapat membuka tampilan'

File Xauthority dapat ditulis sedemikian rupa sehingga nama host tidak menjadi masalah. Kita perlu mengatur Keluarga Otentikasi ke 'FamilyWild'. Saya tidak yakin, jika xauth memiliki baris perintah yang tepat untuk ini, jadi di sini adalah contoh yang menggabungkan xauth dan sed untuk melakukan itu. Kita perlu mengubah 16 bit pertama dari output nlist. Nilai FamilyWild adalah 65535 atau 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
Jürgen Weigert
sumber
8
Hanya sebuah catatan, -v $XSOCK:$XSOCK -v $XAUTH:$XAUTHdapat disingkat menjadi-v $XSOCK -v $XAUTH
Piotr Aleksander Chmielowski
2
@PiotrAleksanderChmielowski yang tidak berfungsi untuk saya, Docker versi 1.12.0, build 8eab29e
tbc0
14
@ Gang: Anda mungkin ingin menggantinya :0dengan $DISPLAY. Itu berarti xauth nlist $DISPLAY | ...dan docker run -ti -e DISPLAY=$DISPLAY .... Biasanya X DISPLAY adalah :0, tetapi tidak selalu (dan terutama tidak jika Anda terhubung melalui ssh -X).
johndodo
4
Di Ubuntu 16,04 xauth membuat /tmp/.docker.xauthfile dengan 600izin. Ini menghasilkan xauth di dalam wadah buruh pelabuhan tidak bisa membaca file. Anda dapat memverifikasi dengan menjalankan xauth listdalam wadah buruh pelabuhan. Saya telah menambahkan chmod 755 $XAUTHsetelah xauth nlist :0 | ...perintah untuk menyelesaikan ini.
Abai
2
@ Amai Mengapa menggunakan 755, jika 444 atau 644 sudah cukup?
Daniel Alder
68

Saya baru saja menemukan entri blog ini dan ingin membagikannya di sini dengan Anda karena saya pikir itu adalah cara terbaik untuk melakukannya dan itu sangat mudah.

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

PROS:
+ tidak ada server x barang dalam wadah buruh pelabuhan
+ tidak ada vnc klien / server diperlukan
+ tidak ssh dengan penerusan x
+ wadah buruh pelabuhan yang jauh lebih kecil

CONS:
- menggunakan x pada host (tidak dimaksudkan untuk safe-sandboxing)

kalau-kalau link akan gagal suatu hari nanti saya telah meletakkan bagian terpenting di sini:
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

membangun gambar:

docker build -t firefox .

dan perintah run:

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

tentu saja Anda juga dapat melakukan ini dengan menjalankan perintah sh -c "echo script-here"

PETUNJUK: untuk audio lihatlah di: https://stackoverflow.com/a/28985715/2835523

A. Binzxxxxxx
sumber
Bagaimana saya bisa melakukan ini di windows 7? Apakah saya perlu menginstal server X?
walksignison
3
Karena sebagian besar jawaban di sini ini hanya berlaku untuk unix saya pikir - sampai windows mendukung sistem windows X server.
A. Binzxxxxxx
Apakah Anda pikir itu bisa berfungsi jika saya menginstal server X di windows atau bahkan menggabungkan server X ke dalam wadah Docker saya?
walksignison
1
Saya pikir Anda juga perlu menginstal di Dockerfile apt-get -y install sudountuk membuat /etc/sudoers.dfolder.
mulg0r
1
mungkin juga diperlukan untuk mengizinkan koneksi ke X dari host mana pun dengan$ xhost +
Bandoos
52

Dengan volume data buruh pelabuhan itu sangat mudah untuk mengekspos soket domain unix xorg di dalam wadah.

Misalnya, dengan Dockerfile seperti ini:

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

Anda dapat melakukan hal berikut:

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

Ini tentu saja pada dasarnya sama dengan penerusan X. Ini memberi kontainer akses penuh ke xserver pada host, jadi itu hanya disarankan jika Anda mempercayai apa yang ada di dalamnya.

Catatan: Jika Anda khawatir tentang keamanan, solusi yang lebih baik adalah membatasi aplikasi dengan kontrol akses wajib atau berbasis peran . Docker mencapai isolasi yang cukup bagus, tetapi dirancang dengan tujuan berbeda. Gunakan AppArmor , SELinux , atau GrSecurity , yang dirancang untuk mengatasi masalah Anda.

Aryeh Leib Taurog
sumber
5
Anda juga perlu mengizinkan akses ke X Server dari host lain menggunakan alat seperti xhost. Untuk benar-benar membukanya gunakan xhost +host.
Tully
3
Hanya xhost +localdiperlukan @Tully . Akan lebih baik untuk membuat ~/.Xauthorityfile tersedia dalam wadah, sehingga dapat mengotentikasi sendiri.
Aryeh Leib Taurog
3
apakah Anda berhasil membuatnya bekerja di Mac (menggunakan boot2docker)?
Karl Forner
4
Ini bekerja dengan baik bagi saya pada laptop Ubuntu 14.04 dengan docker 1.5 sebelumnya; tetapi sekarang gagal untuk saya di Ubuntu 15.04, docker 1.6.2, dengan kesalahan Can't open display: :0. Ada ide?
cboettig
6
Saya dulu xhost +si:localuser:$USERhanya mengotorisasi pengguna yang memulai wadah.
Nick Breen
26

Anda juga dapat menggunakan subuser: https://github.com/timthelion/subuser

Ini memungkinkan Anda untuk mengemas banyak aplikasi gui di buruh pelabuhan. Firefox dan emacs telah diuji sejauh ini. Dengan firefox, webGL tidak berfungsi. Chromium tidak berfungsi sama sekali.

EDIT: Suara bekerja!

EDIT2: Pada saat saya pertama kali memposting ini, subuser telah mengalami kemajuan pesat. Saya sekarang memiliki situs web subuser.org , dan model keamanan baru untuk menghubungkan ke X11 melalui XPRA bridging .

timthelion
sumber
3
Harap perhatikan bahwa subuser masih sangat baru dan relatif belum diuji. Jika Anda mengalami masalah, silakan kirim laporan bug!
timthelion
Saya akan menghindari X11 jika ada cara yang bisa Anda lakukan. Aplikasi pembunuh Anda akan menjalankan proxy untuk docker, dan menjalankan browser lengkap dengan plugins di buruh pelabuhan anak sehingga firewall dll memaksa semua jaringan keluar melalui buruh pelabuhan. Ini akan menjalankan putaran di sekitar bundel peramban saat ini untuk kegunaan web karena Anda akan membiarkan konten kaya melewatinya.
Will
1
Apakah masalah untuk Anda dengan keamanan X11? Atau apakah Anda ingin ini berfungsi dengan windows? Atau Anda ingin ini bekerja dari jarak jauh? Semua yang di atas? Saya pikir membuat ini bekerja dengan vnc sangat mungkin (meskipun saya tidak akan menjadikannya metode default karena menambah ketergantungan pada vnc). Membuat subuser berfungsi dari jarak jauh tidak benar-benar mungkin / bermakna. Ada juga ini: github.com/rogaha/docker-desktop tetapi dari laporan bug sepertinya xpra mungkin tidak dapat digunakan dalam kehidupan nyata.
timthelion
24

OSX

Jürgen Weigert memiliki jawaban terbaik yang bekerja untuk saya di Ubuntu, namun pada OSX, docker berjalan di dalam VirtualBox dan jadi solusinya tidak bekerja tanpa kerja lebih banyak.

Saya sudah membuatnya bekerja dengan bahan tambahan ini:

  1. Xquartz (OSX tidak lagi dikirim dengan server X11)
  2. penerusan soket dengan socat (brew install socat)
  3. skrip bash untuk meluncurkan wadah

Saya menghargai komentar pengguna untuk meningkatkan jawaban ini untuk OSX, saya tidak yakin apakah penerusan soket untuk X aman, tetapi tujuan penggunaan saya adalah untuk menjalankan wadah buruh pelabuhan secara lokal saja.

Selain itu, skripnya agak rapuh karena tidak mudah untuk mendapatkan alamat IP mesin karena itu ada di nirkabel lokal kami sehingga selalu ada beberapa IP acak.

Skrip BASH yang saya gunakan untuk meluncurkan wadah:

#!/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

Saya bisa mendapatkan xeyes dan matplotlib bekerja dengan pendekatan ini.

Windows 7+

Ini sedikit lebih mudah pada Windows 7+ dengan MobaXterm:

  1. Instal MobaXterm untuk windows
  2. Mulai MobaXterm
  3. Konfigurasikan server X: Pengaturan -> X11 (tab) -> atur X11 Remote Access menjadi penuh
  4. Gunakan skrip BASH ini untuk meluncurkan wadah

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 berjalan di PC

Nick
sumber
saya tidak mengerti apa yang Anda maksud dengan skrip bash - bagaimana saya menjalankannya di windows?
deller
@deller Saya melakukan pengembangan perangkat lunak pada windows menggunakan GIT, jadi saya memiliki shell GIT-bash tersedia untuk saya.
Nick
Saya mengikuti langkah-langkahnya. Namun, saya dapat error: XDG_RUNTIME_DIR not set in the environment.dan Error: cannot open display: VAIO:0.0. Apakah Anda menemukan sesuatu seperti ini?
user3275095
1
Saya mendapatkan kesalahan terkait dengan pengguna yang tidak ditemukan yaitu "tidak ada entri yang cocok dalam file passwd" Ada petunjuk?
walksignison
19

Berbagi tampilan host: 0, sebagaimana dinyatakan dalam beberapa jawaban lain, memiliki dua kelemahan:

  • Ini merusak isolasi kontainer karena beberapa kebocoran keamanan X. Misalnya, keylogging dengan xevatau xinputdimungkinkan, dan remote control aplikasi host dengan xdotool.
  • Aplikasi dapat menyebabkan kesalahan dan kesalahan akses RAM yang buruk karena hilangnya memori bersama untuk ekstensi X MIT-SHM. (Dapat juga diperbaiki dengan opsi degradasi isolasi --ipc=host).

Di bawah ini contoh skrip untuk menjalankan gambar buruh pelabuhan di Xephyr yang membahas masalah ini.

  • Ini menghindari kebocoran keamanan X sebagai aplikasi buruh pelabuhan berjalan di server X bersarang.
  • MIT-SHM dinonaktifkan untuk menghindari kegagalan akses RAM.
  • Keamanan kontainer ditingkatkan dengan --cap-drop ALL --security-opt no-new-privileges. Juga pengguna kontainer tidak root.
  • Cookie X dibuat untuk membatasi akses ke tampilan Xephyr.

Script mengharapkan beberapa argumen, pertama manajer jendela host dijalankan di Xephyr, kedua gambar buruh pelabuhan, opsional ketiga perintah gambar yang akan dieksekusi. Untuk menjalankan lingkungan desktop di buruh pelabuhan, gunakan ":" alih-alih manajer jendela host.

Jendela Penutupan Xephyr mengakhiri aplikasi kontainer buruh pelabuhan. Mengakhiri aplikasi yang merapat menutup jendela Xephyr.

Contoh:

  • xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
  • xephyrdocker : x11docker/lxde
  • xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom

skrip xephyrdocker:

#! /bin/bash
#
# Xephyrdocker:     Example script to run docker GUI applications in Xephyr.
#
# Usage:
#   Xephyrdocker WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER     host window manager for use with single GUI applications.
#                   To run without window manager from host, use ":"
# DOCKERIMAGE       docker image containing GUI applications or a desktop
# IMAGECOMMAND      command to run in image
#
Windowmanager="$1" && shift
Dockerimage="$*"

# Container user
Useruid=$(id -u)
Usergid=$(id -g)
Username="$(id -un)"
[ "$Useruid" = "0" ] && Useruid=1000 && Usergid=1000 && Username="user$Useruid"

# Find free display number
for ((Newdisplaynumber=1 ; Newdisplaynumber <= 100 ; Newdisplaynumber++)) ; do
  [ -e /tmp/.X11-unix/X$Newdisplaynumber ] || break
done
Newxsocket=/tmp/.X11-unix/X$Newdisplaynumber

# cache folder and files
Cachefolder=/tmp/Xephyrdocker_X$Newdisplaynumber
[ -e "$Cachefolder" ] && rm -R "$Cachefolder"
mkdir -p $Cachefolder
Xclientcookie=$Cachefolder/Xcookie.client
Xservercookie=$Cachefolder/Xcookie.server
Xinitrc=$Cachefolder/xinitrc
Etcpasswd=$Cachefolder/passwd

# 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
# --user $Useruid:$Usergid           Security: avoid root in container
# -v $Etcpasswd:/etc/passwd:ro       /etc/passwd file with user entry
# --group-add audio                  Allow access to /dev/snd if shared with '--device /dev/snd' 
# --cap-drop ALL                     Security: disable needless capabilities
# --security-opt no-new-privileges   Security: forbid new privileges
Dockercommand="docker run --rm \
  -e DISPLAY=:$Newdisplaynumber \
  -e XAUTHORITY=/Xcookie \
  -v $Xclientcookie:/Xcookie:ro \
  -v $Newxsocket:$Newxsocket:rw \
  --user $Useruid:$Usergid \
  -v $Etcpasswd:/etc/passwd:ro \
  --group-add audio \
  --env HOME=/tmp \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  $(command -v docker-init >/dev/null && echo --init) \
  $Dockerimage"

echo "docker command: 
$Dockercommand
"

# command to run Xorg or Xephyr
# /usr/bin/Xephyr                an absolute path to X server executable must be given for xinit
# :$Newdisplaynumber             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
# -extension MIT-SHM             disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it)
# -nolisten tcp                  disable tcp connections for security reasons
# -retro                         nice retro look
Xcommand="/usr/bin/Xephyr :$Newdisplaynumber \
  -auth $Xservercookie \
  -extension MIT-SHM \
  -nolisten tcp \
  -screen 1000x750x24 \
  -retro"

echo "X server command:
$Xcommand
"

# create /etc/passwd with unprivileged user
echo "root:x:0:0:root:/root:/bin/sh" >$Etcpasswd
echo "$Username:x:$Useruid:$Usergid:$Username,,,:/tmp:/bin/sh" >> $Etcpasswd

# create xinitrc
{ echo "#! /bin/bash"

  echo "# set environment variables to new display and new cookie"
  echo "export DISPLAY=:$Newdisplaynumber"
  echo "export XAUTHORITY=$Xclientcookie"

  echo "# same keyboard layout as on host"
  echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - :$Newdisplaynumber"

  echo "# create new XAUTHORITY cookie file" 
  echo ":> $Xclientcookie"
  echo "xauth add :$Newdisplaynumber . $(mcookie)"
  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 '":$Newdisplaynumber | sed -e 's/^..../ffff/')" 
  echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -'
  echo "cp $Xclientcookie $Xservercookie"
  echo "chmod 644 $Xclientcookie"

  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 "# run docker"
  echo "$Dockercommand"
} > $Xinitrc

xinit  $Xinitrc -- $Xcommand
rm -Rf $Cachefolder

Skrip ini dikelola di wiki x11docker . Skrip yang lebih canggih adalah x11docker yang juga mendukung fitur seperti akselerasi GPU, webcam, dan berbagi printer, dan sebagainya.

mviereck
sumber
18

Berikut adalah solusi ringan yang menghindari keharusan memasang Xserver, vncserver atau sshddaemon apa pun pada wadah. Apa yang diperolehnya dalam kesederhanaan itu hilang dalam keamanan dan isolasi.

Diasumsikan bahwa Anda terhubung ke mesin host menggunakan sshdengan X11penerusan.

Dalam sshdkonfigurasi host, tambahkan baris

X11UseLocalhost no

Sehingga port server X yang diteruskan pada host dibuka pada semua antarmuka (bukan hanya lo) dan khususnya pada antarmuka virtual Docker docker0,.

Kontainer, ketika dijalankan, membutuhkan akses ke .Xauthorityfile sehingga dapat terhubung ke server. Untuk melakukan itu, kita mendefinisikan volume read-only yang menunjuk ke direktori home pada host (mungkin bukan ide yang bijak!) Dan juga mengatur XAUTHORITYvariabel sesuai.

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

Itu tidak cukup, kita juga harus melewati variabel DISPLAY dari host, tetapi mengganti nama host dengan ip:

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

Kita dapat mendefinisikan alias:

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

Dan mengujinya seperti ini:

dockerX11run centos xeyes
danidiaz
sumber
2
(Namun, ini bagus untuk aplikasi tepercaya. Untuk segala jenis sandboxing, Anda ingin menghindari penerusan X.)
Will
1
Jika Anda lebih suka tidak me-mount direktori home seluruh ke dalam wadah Anda hanya dapat me-mount .Xauthorityfile itu sendiri: -v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority.
Robert Haines
2
Alih-alih mengubah X11UseLocalhost, Anda juga dapat menggunakan opsi tambahan --net=hostuntuk docker runperintah (ditemukan di sini ).
ingomueller.net
--net=hostadalah ide yang buruk karena sekarang jika Anda membuka port dalam wadah itu akan terbuka di tuan rumah juga ...
MrR
16

Sementara jawaban oleh Jürgen Weigert pada dasarnya mencakup solusi ini, pada awalnya tidak jelas bagi saya apa yang dijelaskan di sana. Jadi saya akan menambahkan pendapat saya, kalau-kalau ada orang lain yang perlu klarifikasi.

Off pertama, dokumentasi yang relevan adalah manualnya keamanan X .

Banyak sumber online menyarankan hanya memasang soket unix X11 dan ~/.Xauthorityfile ke wadah. Solusi ini sering berhasil, tanpa benar-benar memahami mengapa, misalnya pengguna wadah berakhir dengan UID yang sama dengan pengguna, sehingga tidak perlu otorisasi kunci ajaib.

Pertama, file Xauthority memiliki mode 0600, sehingga pengguna kontainer tidak akan dapat membacanya kecuali ia memiliki UID yang sama.

Bahkan jika Anda menyalin file ke dalam wadah, dan mengubah kepemilikan, masih ada masalah lain. Jika Anda menjalankan xauth listhost dan container, dengan Xauthorityfile yang sama , Anda akan melihat entri yang berbeda terdaftar. Ini karena xauthmemfilter entri tergantung pada tempat dijalankannya.

Klien X dalam wadah (yaitu aplikasi GUI) akan berperilaku sama dengan xauth. Dengan kata lain, itu tidak melihat cookie ajaib untuk sesi X yang berjalan di desktop pengguna. Alih-alih, ia melihat entri untuk semua sesi "remote" X yang telah Anda buka sebelumnya (dijelaskan di bawah).

Jadi, apa yang perlu Anda lakukan adalah menambahkan entri baru dengan nama host wadah dan tombol hex yang sama dengan cookie host (yaitu sesi X yang berjalan di desktop Anda), misalnya:

containerhostname/unix:0   MIT-MAGIC-COOKIE-1   <shared hex key>

Tangkapannya adalah bahwa cookie harus ditambahkan dengan xauth adddi dalam wadah:

touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>

Kalau tidak, xauthtandai dengan cara yang hanya terlihat di luar wadah.

Format untuk perintah ini adalah:

xauth add hostname/$DISPLAY protocol hexkey

Dimana .mewakili MIT-MAGIC-COOKIE-1protokol.

Catatan: Tidak perlu menyalin atau mengikat-mount .Xauthorityke wadah. Cukup buat file kosong, seperti yang ditunjukkan, dan tambahkan cookie.

Jawaban Jürgen Weigert menyiasatinya dengan menggunakan FamilyWildjenis koneksi untuk membuat file otoritas baru pada host dan menyalinnya ke dalam wadah. Perhatikan bahwa ini pertama-tama mengekstrak kunci hex untuk sesi X saat ~/.Xauthoritymenggunakan xauth nlist.

Jadi langkah-langkah penting adalah:

  • Ekstrak kunci hex cookie untuk sesi X pengguna saat ini.
  • Buat file Xauthority baru dalam wadah, dengan hostname wadah dan kunci hex bersama (atau buat cookie dengan FamilyWildtipe koneksi).

Saya akui bahwa saya tidak begitu mengerti bagaimana cara FamilyWildkerjanya, atau bagaimana xauthatau klien X memfilter entri dari file Xauthority tergantung di mana mereka dijalankan. Informasi tambahan tentang ini disambut baik.

Jika Anda ingin mendistribusikan aplikasi Docker Anda, Anda akan memerlukan skrip mulai untuk menjalankan wadah yang mendapat kunci hex untuk sesi X pengguna, dan mengimpornya ke dalam wadah dengan salah satu dari dua cara yang dijelaskan sebelumnya.

Ini juga membantu untuk memahami mekanisme proses otorisasi:

  • Klien X (yaitu aplikasi GUI) yang berjalan di wadah melihat dalam file Xauthority untuk entri cookie yang cocok dengan nama host penampung dan nilai $DISPLAY.
  • Jika entri yang cocok ditemukan, klien X meneruskannya dengan permintaan otorisasi ke server X, melalui soket yang sesuai di /tmp/.X11-unixdirektori yang dipasang di wadah.

Catatan: Soket Unix X11 masih harus dipasang di wadah, atau wadah tidak akan memiliki rute ke server X. Sebagian besar distribusi menonaktifkan akses TCP ke server X secara default untuk alasan keamanan.

Untuk informasi tambahan, dan untuk lebih memahami bagaimana hubungan X client / server bekerja, juga membantu untuk melihat contoh kasus penerusan SSH X:

  • Server SSH yang berjalan pada mesin jarak jauh mengemulasi server X-nya sendiri.
  • Ini menetapkan nilai $DISPLAYdalam sesi SSH untuk menunjuk ke server X-nya sendiri.
  • Ini digunakan xauthuntuk membuat cookie baru untuk host jarak jauh, dan menambahkannya ke Xauthorityfile untuk pengguna lokal dan jarak jauh.
  • Ketika aplikasi GUI dimulai, mereka berbicara dengan server X yang ditiru SSH.
  • Server SSH meneruskan data ini kembali ke klien SSH di desktop lokal Anda.
  • Klien SSH lokal mengirimkan data ke sesi server X yang berjalan di desktop Anda, seolah-olah klien SSH sebenarnya adalah klien X (yaitu aplikasi GUI).
  • Server X menggunakan data yang diterima untuk membuat GUI di desktop Anda.
  • Di awal pertukaran ini, klien X jarak jauh juga mengirim permintaan otorisasi, menggunakan cookie yang baru saja dibuat. Server X lokal membandingkannya dengan salinan lokalnya.
orodbhen
sumber
12

Ini tidak ringan tetapi merupakan solusi yang bagus yang memberikan fitur fitur docker dengan virtualisasi desktop penuh. Baik Xfce4 atau IceWM untuk Ubuntu dan CentOS berfungsi, dan noVNCopsi ini memudahkan akses melalui browser.

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

Ini berjalan noVNCserta tigerVNCvncserver. Kemudian ia memanggil startxWindow Manager yang diberikan. Selain itu, libnss_wrapper.sodigunakan untuk meniru manajemen kata sandi untuk pengguna.

gagah
sumber
Adakah yang sudah menguji ini?
guilhermecgs
3
@guilhermecgs ya, dan berfungsi dengan baik. Sejak itu saya juga mencoba xpradi docker, yang merupakan root-less X. xpraadalah IMO paling cocok dan lebih efisien daripada VNC.
dashesy
Untuk lebih jelasnya ... Dapatkah saya memiliki pengalaman desktop penuh (GNOME, KDE) dengan gambar ini?
guilhermecgs
Saya hanya mencoba Xfce4 dan IceWM (yang ada di repo itu). Tentu saja pengalamannya akan terbatas, misalnya pemasangan perangkat tidak akan muncul di desktop (gvfs) kecuali Anda lulus --device /dev/...ke buruh pelabuhan dan mengatur --caphak istimewa yang diperlukan . Itu mengalahkan tujuan penahanan, tetapi Anda dapat melewati perangkat. Dengan beberapa penyesuaian, saya bisa menjalankan GNOME / KDE di bawah VNC. Saya menjalankan beberapa X di buruh pelabuhan dengan kartu nvidia (tidak ada VNC atau Xpra), sehingga tentu saja bisa dilakukan.
dashesy
Kami belum mencobanya sejauh ini. Tantangan terbesar dalam hal ini adalah memunculkan daemon D-Bus yang berfungsi. Sebagian besar desktop gnome atau KDE akan membutuhkannya. Semoga proyek ubuntu-desktop-lxde-vnc membantu Anda di sana.
toschneck
11

Solusi yang diberikan di http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ tampaknya merupakan cara mudah untuk memulai aplikasi GUI dari dalam wadah (saya mencoba firefox lebih dari ubuntu 14.04) tetapi saya menemukan bahwa perubahan tambahan kecil diperlukan untuk solusi yang diposting oleh penulis.

Secara khusus, untuk menjalankan wadah, penulis telah menyebutkan:

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

Tetapi saya menemukan bahwa (berdasarkan komentar tertentu di situs yang sama) ada dua opsi tambahan

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

dan

    -net=host 

perlu ditentukan saat menjalankan wadah agar firefox berfungsi dengan baik:

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

Saya telah membuat gambar buruh pelabuhan dengan informasi di halaman itu dan temuan tambahan ini: https://hub.docker.com/r/amanral/ubuntu-firefox/

Anshuman Manral
sumber
3
Saya telah menemukan bahwa Anda bahkan tidak lulus /tmp/.X11-unixsoket sama sekali. Ini hanya berfungsi dengan pemasangan .Xauthoritydan --net=host.
CMCDragonkai
2
Ini sebenarnya satu-satunya solusi yang berfungsi akhir-akhir ini. Menggunakan /tmp/.X11-unixsebagai volume tidak lagi berfungsi, karena buruh pelabuhan diam-diam menolak volume mount dari direktori lengket.
Christian Hujer
1
Saya pikir itu tergantung pada distro apa yang Anda gunakan. Anda pasti dapat mengikat soket Unix X11 pada CentOS. Penting juga untuk memahami apa yang harus --network=hostdilakukan. Ini memberi kontainer Anda akses penuh ke tumpukan jaringan host, yang mungkin tidak diinginkan, tergantung pada apa yang Anda coba lakukan. Jika Anda hanya mengutak-atik menjalankan GUI kemas di desktop Anda, maka itu tidak masalah.
orodbhen
7

Ada solusi lain oleh lord.garbage untuk menjalankan aplikasi GUI dalam sebuah wadah tanpa menggunakan penerusan VNC, SSH dan X11. Disebutkan di sini juga.

niutech
sumber
1
Ini bagus jika keamanan bukan masalah. Jika tujuan merendahkan sesuatu adalah mengisolasinya, yang terbaik adalah menghindari X11 masuk-keluar dari wadah.
Will
7

Jika Anda ingin menjalankan aplikasi GUI tanpa kepala, baca di sini . Yang harus Anda lakukan adalah membuat monitor virtual dengan xvfbatau perangkat lunak serupa lainnya. Ini sangat membantu jika Anda ingin menjalankan tes Selenium misalnya dengan browser.

Sesuatu yang tidak disebutkan di mana pun adalah bahwa beberapa perangkat lunak sebenarnya menggunakan kotak pasir dengan wadah Linux. Jadi misalnya Chrome tidak akan pernah berjalan normal jika Anda tidak menggunakan bendera yang sesuai --privilegedsaat menjalankan wadah.

Pithikos
sumber
6

Saya terlambat ke pesta, tetapi untuk pengguna Mac yang tidak ingin menyusuri jalur XQuartz, berikut ini adalah contoh kerja yang membangun Gambar Fedora, dengan Lingkungan Desktop (xfce) menggunakan Xvfbdan VNC. Sederhana, dan berfungsi:

Di Mac, Anda bisa mengaksesnya menggunakan aplikasi Screen Sharing (default), yang terhubung ke 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

Periksa readme yang tertaut untuk perintah build dan run jika Anda mau / butuhkan.

Vince
sumber
5

Berdasarkan jawaban Jürgen Weigert , saya memiliki beberapa peningkatan:

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

Satu-satunya perbedaan adalah ia menciptakan direktori $ XAUTH_DIR yang digunakan untuk menempatkan file $ XAUTH dan me-mount direktori $ XAUTH_DIR alih-alih file $ XAUTH ke dalam wadah buruh pelabuhan.

Manfaat dari metode ini adalah Anda dapat menulis perintah di /etc/rc.local yaitu membuat folder kosong bernama $ XAUTH_DIR di / tmp dan mengubah modenya ke 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

Ketika sistem dinyalakan kembali, sebelum pengguna masuk, buruh pelabuhan akan memasang direktori $ XAUTH_DIR secara otomatis jika kebijakan restart kontainer "selalu". Setelah pengguna login, Anda dapat menulis perintah di ~ / .profile yaitu untuk membuat file $ XAUTH, maka container akan secara otomatis menggunakan file $ XAUTH ini.

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

Setelah semua, wadah akan secara otomatis mendapatkan file Xauthority setiap kali sistem restart dan login pengguna.

allenyllee
sumber
4

Solusi lain harus berhasil, tetapi di sini ada solusi untuk docker-compose.

Untuk memperbaiki kesalahan itu, Anda harus meneruskan $ DISPLAY dan .X11-unix ke buruh pelabuhan, serta memberikan pengguna yang mulai mengakses buruh pelabuhan ke xhost.

Dalam docker-compose.ymlfile:

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

Dalam terminal atau skrip:

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

Anda dapat mengizinkan pengguna Docker (di sini: root) untuk mengakses tampilan 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
wedesoft
sumber
2

OSX (10.13.6, sierra tinggi)

Mirip dengan jawaban @Nick , tetapi solusinya tidak bekerja untuk saya.

Pertama instal socat dengan melakukan brew install socat, dan instal XQuartz ( https://www.xquartz.org/ )

Kemudian ikuti langkah-langkah ini di sini ( http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ ) di bagian komentar:

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

Saya juga dapat meluncurkan CLion dari wadah buruh pelabuhan debian saya juga.

tidak
sumber
1

Docker dengan jaringan BRIDGE. untuk Ubuntu 16.04 dengan display manager lightdm:

cd /etc/lightdm/lightdm.conf.d
sudo nano user.conf

[Seat:*]
xserver-allow-tcp=true
xserver-command=X -listen tcp

Anda dapat menggunakan lebih banyak izin pribadi

xhost +

docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$HOST_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name
dabizharoman
sumber
1

Namun jawaban lain jika Anda sudah membangun gambar:

  1. aktifkan buruh pelabuhan tanpa sudo ( Cara memperbaiki buruh pelabuhan: Mendapat izin ditolak masalah )

  2. bagikan PENGGUNA & home & passwd yang sama antara host dan berbagi kontainer (kiat: gunakan id pengguna, bukan nama pengguna)

  3. folder dev untuk lib bergantung pada driver agar berfungsi dengan baik

  4. ditambah X11 maju.

    docker run --name=CONTAINER_NAME --network=host --privileged \
      -v /dev:/dev \
      -v `echo ~`:/home/${USER} \
      -p 8080:80 \
      --user=`id -u ${USER}` \
      --env="DISPLAY" \
      --volume="/etc/group:/etc/group:ro" \
      --volume="/etc/passwd:/etc/passwd:ro" \
      --volume="/etc/shadow:/etc/shadow:ro" \
      --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
      --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
      -it REPO:TAG /bin/bash

Anda mungkin bertanya, apa gunanya menggunakan buruh pelabuhan jika begitu banyak hal yang sama? baik, salah satu alasan yang dapat saya pikirkan adalah untuk mengatasi paket neraka neraka ( https://en.wikipedia.org/wiki/Dependency_hell ).

Jadi jenis penggunaan ini lebih cocok untuk pengembang saya pikir.

TingQian LI
sumber
Ini adalah satu-satunya yang akan bekerja untuk saya. Untuk tujuan saya, saya dapat menguranginya menjadi ini: buruh pelabuhan --network = host --volume = echo ~: / home / $ {USER} id -u ${USER}--user = --env = "DISPLAY" --volume = "/ etc / passwd: / etc / passwd: ro "-it REPO: TAG / bin / bash
user1145922
1

Saya berhasil menjalankan streaming video dari kamera USB menggunakan opencvdi dockerdengan mengikuti langkah berikut:

  1. Biarkan buruh pelabuhan mengakses server X

    xhost +local:docker
    
  2. Buat soket Unix X11 dan file otentikasi X.

    XSOCK=/tmp/.X11-unix
    XAUTH=/tmp/.docker.xauth
    
  3. Tambahkan izin yang tepat

    xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
    
  4. Atur kecepatan rendering Qt ke "asli", sehingga tidak mem-bypass mesin rendering X11

    export QT_GRAPHICSSYSTEM=native
    
  5. Katakan Qt untuk tidak menggunakan MIT-SHM (memori bersama) - dengan cara itu seharusnya juga lebih aman dari segi keamanan

    export QT_X11_NO_MITSHM=1
    
  6. Perbarui perintah jalankan buruh pelabuhan

    docker run -it \
               -e DISPLAY=$DISPLAY \
               -e XAUTHORITY=$XAUTH \
               -v $XSOCK:$XSOCK \
               -v $XAUTH:$XAUTH \
               --runtime=nvidia \
               --device=/dev/video0:/dev/video0 \
               nvcr.io/nvidia/pytorch:19.10-py3
    

Catatan: Saat Anda menyelesaikan proyek, kembalikan kontrol akses pada nilai standarnya - xhost -local:docker

Lebih detail: Menggunakan GUI dengan Docker

Kredit: Deteksi objek pemrosesan video dan real-time menggunakan Tensorflow, OpenCV dan Docker

tsveti_iko
sumber
"Buat soket Unix X11 dan file otentikasi X" tidak membuat file apa pun, itu hanya mendefinisikan variabel?
MrR