Docker에서 가상의 x-window 세팅
Docker의 UI를 띄우는 가장 쉬운 방법은 X서버의 소켓 (/tmp/.X11:unix)을 Docker 볼륨으로 마운트 (Read Ony) 시키고 이것을 이용하는 방법인 것 같습니다. 이런 경우 대부분의 경우에서 문제 없이 동작하지만 QT의 경우 이런식의 X Section 공유가 제대로 동작하지 않는다고 합니다. 개발된 QT 앱을 Docker 내에서 실행할 경우 Invalid Shared Segment 등의 오류가 발생하며 컨트롤들이 보이지 않는 현상이 발생합니다.
이를 해결하기 위해 Docker 안에 가상의 x-window 환경을 구축해 보고자 합니다. 또한 Local로 접속하기만 한다면 상관없지만 외부에서 접속을 하고 싶다면 메인 PC의 포트와 겹치지 않는게 좋기 때문에 VNC를 위한 포트를 메인 PC와 겹치지 않게 여기서는 5902 포트를 포팅한 후 작업하였습니다. (참고로 저는 Docker 관리를 Portainer를 이용합니다.)
먼저 Container를 켜서 필요한 다음의 도구들을 모두 설치해 놓습니다.
apt-get update
apt-get install vim // vi editor (docker에 대부분 설치 안되어 있어서/필요없으면 pass)
apt-get install -y psmisc // killall 설치 (쉘명령중 사용할 거다)
apt-get install python // openbox 메뉴에서 이를 사용한다
apt-get install xvfb # xvfb 설치 X Virtual Frame Buffer (가상 디스플레이 서버)
apt-get install openbox # x11-Window을 위한 창관리자
그 다음 vnc server인 x11vnc를 설치합니다.
이때 Ubuntu 18.04에서는 알려진 문제가 있으므로 apt-get으로 받지 않는 걸 권장합니다.
헷갈리지 않게 접은 글로 나눠서 표시할테니 필요한 글을 펼쳐 읽으시기 바랍니다.
Xvfb를 통해 가상의 Screen을 만들고, OpenBox를 그위에 띄우고 VNC로 접속하는 과정으로 진행됩니다.
Ubuntu 20.04 이상의 방법
apt-get install x11vnc
x11vnc 설치도중에는 time zones 설정하라고 나옵니다. 맞는 타임존을 선택합니다.
((참고) 한국은 6. Asia -> 69. Seoul)
vnc의 접속 password를 설정합니다.
x11vnc -storepasswd
그후 다음의 폴더와 스크립트 파일을 만들어 놓겠습니다.
mkdir /opt/xvfb_vnc
vim /opt/xvfb_vnc/run.sh
#!/bin/bash
echo “Xvfb Virtual Display 1920x1080 (24Bit)”
killall Xvfb
rm /tmp/.X1-lock
Xvfb :1 -screen 0 1920x1080x24 & sleep 5
export DISPLAY=:1.0
openbox & sleep 1
x11vnc -noxdamage -loop -repeat -forever -display :1 -usepw -rfbport 5902 & sleep 1
Ubuntu 18.04 에서 방법
ubuntu 18.04에서 x11vnc버전은 마지막 버전이 0.9.13인데 vnc가 자꾸 죽어서 loop 등의 옵션을 사용했지만 stack smashing detected라는 말이 나오며 여전히 죽었습니다. 찾아보니 0.9.13 버전에 문제가 있다고 합니다. 추후 해결되었다고 하나 apt-get으로는 받을 수 없습니다. 화면이 변하지 않을 때 부하를 줄이기 위한 X Damage 옵션이 있는데 이것이 세션문제를 많이 일으킨다고 들어서 해당 옵션을 끄고, 종료시 자동 재시작 옵션 등을 추가해 놓았지만 큰 효과는 없었습니다. 그래서 찾은 방법은 이 문제를 해결하기 0.9.14 버전을 직접받아 빌드하는 방법입니다. 제가 참고했던 글도 함께 링크 첨부 합니다. 저는 이 이후로는 죽지 않았습니다.
(참고: https://gist.github.com/mangoliou/407d6a39a60d128610c20c4143f39f0d)
이제 다음의 shell script를 만들어서 수행합니다.
apt-get update
apt-get install libxtst-dev libssl-dev libjpeg-dev
apt-get install -y libxtst-dev libssl-dev libjpeg-dev
wget http://x11vnc.sourceforge.net/dev/x11vnc-0.9.14-dev.tar.gz
gzip -dc x11vnc-0.9.14-dev.tar.gz | tar -xvf -
cd x11vnc-0.9.14/
./configure --prefix=/usr/local CFLAGS='-g -O2 -fno-stack-protector -Wall'
make
make install
ps wwwwaux | grep auth
그후 다음의 폴더와 스크립트 파일을 만들어 놓겠습니다.
mkdir /opt/xvfb_vnc
vim /opt/xvfb_vnc/run.sh
#!/bin/bash
echo “Xvfb Virtual Display 1920x1080 (24Bit)”
killall Xvfb
rm /tmp/.X1-lock
Xvfb :1 -screen 0 1920x1080x24 & sleep 5
export DISPLAY=:1.0
openbox & sleep 1
/usr/local/bin/x11vnc -auth /var/run/lightdm/root/:0 -noxdamage -xkb -loop -repeat -forever -display :1 -usepw -rfbport 5902 & sleep 1
위의 방법 중 하나로 실행 스크립트를 최종적으로 만드셨다면 해당 스크립트 파일에 실행 권한을 줍니다.
chmod 700 /opt/xvfb_vnc/run.sh
그다음 EntryPoint에 해당 스크립트를 추가하거나 기존 EntryPoint가 존재한다면 마지막 줄에 위의 스크립파일 실행을 추가합니다. 그러면 해당 도커를 시작할 때 VNC 관련 기능이 동작하면서 VNC를 통해 OpenBox 의 접속이 가능해 집니다.
다음은 VNC를 통해 Docker에서 QT Creator를 수행후 빌드 실행해본 화면입니다.