x11 도커 데비안 - Docker 컨테이너에서 GUI 응용 프로그램을 실행할 수 있습니까?





9 Answers

Xauthority는 새로운 시스템에서 문제가됩니다. 도커 컨테이너를 실행하기 전에 xhost +로 보호를 해제하거나 제대로 준비된 Xauthority 파일을 전달할 수 있습니다. 일반적인 Xauthority 파일은 호스트 이름에 따라 다릅니다. docker를 사용하면 각 컨테이너마다 다른 호스트 이름 (docker run -h로 설정)을 가질 수 있지만 호스트 시스템과 동일한 컨테이너의 호스트 이름을 설정해도 내 경우에는 도움이되지 않습니다. xeyes (이 예제가 마음에 든다)는 단순히 마법 쿠키를 무시하고 서버에 자격 증명을 전달하지 않습니다. 따라서 '프로토콜이 지정되지 않았습니다. 디스플레이를 열 수 없습니다'라는 오류 메시지가 나타납니다.

Xauthority 파일은 호스트 이름이 중요하지 않도록 작성 될 수 있습니다. 인증 패밀리를 'FamilyWild'로 설정해야합니다. xauth에 적절한 명령 줄이 있다면 잘 모르겠다. xauth와 sed를 결합한 예가 여기에있다. nlist 출력의 처음 16 비트를 변경해야합니다. FamilyWild의 값은 65535 또는 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
리눅스 민트 안드로이드

Docker 컨테이너에서 GUI 응용 프로그램을 어떻게 실행할 수 있습니까?

거기에 vncserver 또는 뭔가를 설정할 수있는 이미지가 있습니까? 예를 들어 파이어 폭스 샌드 박스 주위에 여분의 스피드 범프 샌드 박스를 추가 할 수 있습니까?




도커 데이터 볼륨을 사용하면 xorg의 유닉스 도메인 소켓을 컨테이너 내부에 노출시키는 것이 매우 쉽습니다.

예를 들어 다음과 같은 Dockerfile을 사용합니다.

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

당신은 다음을 할 수 있습니다 :

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

이것은 물론 X-forwarding과 본질적으로 같습니다. 컨테이너에 호스트의 xserver에 대한 모든 액세스 권한을 부여하므로 내부 내용을 신뢰하는 경우에만 컨테이너를 권장합니다.

참고 : 보안이 염려되는 경우 더 나은 해결책은 앱을 mandatory- 또는 role-based- 액세스 제어로 제한하는 것입니다. Docker는 꽤 좋은 격리를 달성하지만, 다른 목적으로 염두에두고 설계되었습니다. 귀하의 우려를 해소하기 위해 고안된 AppArmor , SELinux 또는 GrSecurity를 사용하십시오.




OSX

Jürgen Weigert 는 우분투에서 저에게 가장 잘 맞는 답변을 가지고 있습니다. 그러나 OSX에서는 docker가 VirtualBox 내부에서 실행되기 때문에 솔루션이 더 이상 작동하지 않으면 작동하지 않습니다.

나는이 추가 성분들로 작업하고있다.

  1. Xquartz (OSX는 더 이상 X11 서버와 함께 제공되지 않음)
  2. socat으로 소켓 전달 (brew install socat)
  3. 컨테이너를 시작하는 bash 스크립트

OSX에서이 대답을 향상시키기 위해 사용자 의견을 보내 주시면 감사하겠습니다. X 용 소켓 전달이 안전할지 모르겠지만 의도 한 용도는 도커 컨테이너를 로컬에서만 실행하는 것입니다.

또한이 스크립트는 약간의 약점을 가지고 있는데, 로컬 무선을 사용하기 때문에 컴퓨터의 IP 주소를 얻는 것이 쉽지 않기 때문에 항상 임의의 IP입니다.

컨테이너를 시작하는 데 사용하는 BASH 스크립트 :

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

xeyes와 matplotlib를이 접근 방식으로 작업 할 수 있습니다.

Windows 7 이상

MobaXterm을 사용하면 Windows 7 이상에서 좀 더 편리합니다.

  1. Windows 용 MobaXterm 설치
  2. MobaXterm 시작
  3. X 서버 구성 : 설정 -> X11 (탭) -> X11 원격 액세스전체로 설정
  4. 이 BASH 스크립트를 사용하여 컨테이너를 시작하십시오.

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




호스트 디스플레이 공유 : 0은 다른 답변에서 언급했듯이 두 가지 단점이 있습니다.

  • X 보안 누출로 인해 컨테이너 격리가 중단됩니다. 예를 들어, xev 또는 xinput 하여 keylogging이 가능하며 xdotool 사용하여 호스트 응용 프로그램을 원격 제어 할 수 있습니다.
  • 응용 프로그램은 X 확장 MIT-SHM의 공유 메모리 누락으로 인해 렌더링 오류 및 잘못된 RAM 액세스 오류가 발생할 수 있습니다. (절연 분해 옵션 인 --ipc=host 로 고정 될 수도 있음).

이 문제를 해결하는 도미노 이미지를 Xephyr에서 실행하는 예제 스크립트.

  • 도커 응용 프로그램이 중첩 된 X 서버에서 실행될 때 X 보안 누출을 방지합니다.
  • RAM 액세스 실패를 피하기 위해 MIT-SHM이 비활성화되었습니다.
  • --cap-drop ALL --security-opt no-new-privileges 컨테이너 보안이 개선 --cap-drop ALL --security-opt no-new-privileges . 또한 컨테이너 사용자는 루트가 아닙니다 .
  • Xephyr 표시에 대한 액세스를 제한하기 위해 X 쿠키가 작성됩니다.

스크립트는 Xephyr에서 호스트 윈도우 관리자를 실행하고, 두 번째로 도커 이미지를, 두 번째로 선택적으로 실행할 이미지 명령을 인수로 사용합니다. 도커에서 데스크탑 환경을 실행하려면 호스트 창 관리자 대신 ":"을 사용하십시오.

Xephyr 창을 닫으면 도커 컨테이너 응용 프로그램이 종료됩니다. 도킹 된 응용 프로그램을 종료하면 Xephyr 창이 닫힙니다.

예 :

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

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



fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker 에서 주어진 해결책은 컨테이너 내부에서 GUI 응용 프로그램을 시작할 수있는 쉬운 방법 인 것 같습니다 (firefox 우분투 14.04 이상)하지만 저자가 게시 한 솔루션에는 약간의 추가 변경이 필요하다는 사실을 발견했습니다.

특히 컨테이너를 실행하기 위해 작성자는 다음과 같이 언급했습니다.

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

그러나 나는 (동일한 사이트의 특정 코멘트를 기반으로) 두 개의 추가 옵션

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

    -net=host 

firefox가 제대로 작동하려면 컨테이너를 실행하는 동안 지정해야합니다.

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

해당 페이지의 정보와 다음 추가 발견 사항으로 도커 이미지를 만들었습니다. https://hub.docker.com/r/amanral/ubuntu-firefox/




GUI 애플리케이션을 헤드리스로 실행하려면 here 를 읽으 here . xvfb 또는 다른 유사한 소프트웨어로 가상 모니터를 만드는 것입니다. 예를 들어 브라우저에서 Selenium 테스트를 실행하려는 경우 매우 유용합니다.

아무 것도 언급하지 않은 것은 실제로 일부 소프트웨어가 실제로 리눅스 컨테이너로 샌드 박싱을 사용한다는 것입니다. 예를 들어, 컨테이너를 실행할 때 적절한 플래그 --privileged 사용하지 않으면 Chrome이 정상적으로 실행되지 않습니다.




Jürgen Weigert 의 대답은 본질적으로이 솔루션을 다루지 만 처음에는 거기에 무엇이 설명되어 있는지 분명하지 않았습니다. 다른 사람이 설명이 필요할 경우를 대비하여 필자의 의견을 추가하겠습니다.

먼저 관련 문서가 X 보안 맨 페이지 입니다.

수많은 온라인 소스는 X11 유닉스 소켓과 ~/.Xauthority 파일을 컨테이너에 마운트하는 것을 제안합니다. 이러한 솔루션은 종종 컨테이너 사용자가 사용자와 동일한 UID로 끝나는 등의 이유를 실제로 이해하지 않고 행운을 따라 작동합니다. 따라서 마법 키 인증이 필요하지 않습니다.

우선, Xauthority 파일은 0600 모드를 가지므로 컨테이너 사용자는 동일한 UID를 가지고 있지 않으면 읽을 수 없습니다.

파일을 컨테이너에 복사하고 소유권을 변경하더라도 다른 문제가 있습니다. 동일한 Xauthority 파일을 사용하여 호스트 및 컨테이너에서 xauth list 를 실행하면 다른 항목이 나열됩니다. 이는 xauth 가 실행되는 위치에 따라 항목을 필터링하기 때문입니다.

컨테이너 (예 : GUI 응용 프로그램)의 X 클라이언트는 xauth 와 동일하게 작동합니다. 즉, 사용자의 데스크톱에서 실행중인 X 세션에 대한 마법 쿠키가 표시되지 않습니다. 대신, 이전에 열어 둔 모든 "원격"X 세션에 대한 항목을 봅니다 (아래에서 설명 함).

따라서 컨테이너의 호스트 이름과 호스트 쿠키 (예 : 데스크탑에서 실행중인 X 세션)와 동일한 16 진수 키를 가진 새로운 항목을 추가하십시오. 예 :

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

xauth add 은 컨테이너 내부에 xauth add 추가하여 쿠키를 추가해야한다는 것입니다.

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

그렇지 않으면, xauth 는 컨테이너 외부에서만 볼 수있는 방식으로 태그를 xauth 입니다.

이 명령의 형식은 다음과 같습니다.

xauth add hostname/$DISPLAY protocol hexkey

어디서 . MIT-MAGIC-COOKIE-1 프로토콜을 나타냅니다.

참고 : 컨테이너에 .Xauthority 를 복사하거나 바인드 마운트 할 필요가 없습니다. 표시된 것처럼 빈 파일을 만들고 쿠키를 추가하십시오.

Jürgen Weigert 의 답변은 FamilyWild 연결 유형을 사용하여 호스트에서 새로운 전거 파일을 만들고이를 컨테이너에 복사 FamilyWild 문제를 해결합니다. xauth nlist 사용하여 ~/.Xauthority 에서 현재 X 세션에 대한 16 진수 키를 추출합니다.

따라서 필수 단계는 다음과 같습니다.

  • 사용자의 현재 X 세션에 대한 쿠키의 16 진수 키를 추출하십시오.
  • 컨테이너 호스트 이름과 공유 된 16 진수 키를 사용하여 컨테이너에 새 Xauthority 파일을 만들거나 FamilyWild 연결 유형으로 쿠키를 만듭니다.

필자는 FamilyWild 가 어떻게 작동하는지, 또는 xauth 또는 X 클라이언트가 실행되는 위치에 따라 Xauthority 파일의 항목을 필터링하는 방식을 잘 이해하지 못한다는 것을 인정합니다. 이에 대한 추가 정보는 환영합니다.

Docker 앱을 배포하려면 사용자의 X 세션에 대한 16 진수 키를 가져 오는 컨테이너를 실행하기위한 시작 스크립트가 필요하며 이전에 설명한 두 가지 방법 중 하나를 사용하여 컨테이너로 가져옵니다.

또한 권한 부여 프로세스의 메커니즘을 이해하는 데 도움이됩니다.

  • 컨테이너에서 실행중인 X 클라이언트 (즉, GUI 응용 프로그램)는 Xauthority 파일에서 컨테이너의 호스트 이름과 $DISPLAY 의 값과 일치하는 쿠키 항목을 찾습니다.
  • 일치하는 항목이 있으면 X 클라이언트는 컨테이너에 마운트 된 /tmp/.X11-unix 디렉토리의 해당 소켓을 통해 X 서버에 권한 요청과 함께 권한을 전달합니다.

참고 : X11 Unix 소켓을 컨테이너에 마운트해야합니다. 그렇지 않으면 컨테이너에 X 서버에 대한 경로가 없습니다. 대부분의 배포판은 기본적으로 보안상의 이유로 X 서버에 대한 TCP 액세스를 비활성화합니다.

추가 정보와 X 클라이언트 / 서버 관계가 어떻게 작동하는지 더 잘 이해하려면 SSH X 전달의 예제를 살펴 보는 것도 도움이됩니다.

  • 원격 시스템에서 실행중인 SSH 서버는 자체 X 서버를 에뮬레이트합니다.
  • 그것은 자신의 X 서버를 가리 키도록 SSH 세션에서 $DISPLAY 의 값을 설정합니다.
  • xauth 를 사용하여 원격 호스트에 대한 새로운 쿠키를 생성하고이를 로컬 및 원격 사용자 모두를위한 Xauthority 파일에 추가합니다.
  • GUI 응용 프로그램이 시작되면 SSH의 에뮬레이트 된 X 서버와 통신합니다.
  • SSH 서버는이 데이터를 로컬 데스크탑의 SSH 클라이언트로 다시 전달합니다.
  • 로컬 SSH 클라이언트는 SSH 클라이언트가 실제로 X 클라이언트 (예 : GUI 응용 프로그램) 인 것처럼 데스크탑에서 실행중인 X 서버 세션에 데이터를 보냅니다.
  • X 서버는 수신 된 데이터를 사용하여 데스크탑에서 GUI를 렌더링합니다.
  • 이 교환이 시작될 때 원격 X 클라이언트는 방금 작성된 쿠키를 사용하여 권한 요청을 전송합니다. 로컬 X 서버는이를 로컬 사본과 비교합니다.



나는 파티에 늦었지만 XQuartz 경로를 내려 가고 싶지 않은 Mac 사용자의 경우 XvfbVNC 사용하는 데스크탑 환경 (xfce)을 사용하여 Fedora 이미지를 만드는 작업 예제가 있습니다. 간단하고 작동합니다.

Mac의 경우 Screen Sharing (기본) 응용 프로그램 ( 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

필요에 따라 빌드 및 실행 명령에 대한 링크 된 https://github.com/ddual/docker_recipes#fedora-with-an-x-window-system 를 확인하십시오 .




다른 솔루션도 사용할 수 있지만 여기에는 해결책이 docker-compose있습니다.

이 오류를 수정하려면 docker에 $ DISPLAY 및 .X11-unix를 전달하고 docker 액세스를 시작한 사용자에게 xhost에 대한 액세스 권한을 부여해야합니다.

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

터미널 또는 스크립트에서 :

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





Related