天天看點

c++builder 運作網站的api_如何在docker中運作ubuntukylin桌面系統

如何在docker中運作ubuntukylin桌面系統

背景

由于要和開源社合辦一個活動,要求線上線下同時進行,需要使用對方的雲平台,本來以為隻需要提供iso鏡像就行了,沒想到對方隻支援docker鏡像。雖然之前用過docker,但是完全沒想過docker裡跑桌面。

思路調研和已有開源項目

說實話,由于沒怎麼接觸過docker,是以花了一上午時間看了下docker實踐教程,但是對如何運作桌面還是沒什麼頭緒。但是我之前在win10剛出wsl的時候好奇去嘗試過,當時有一種使用ximage映射使wsl運作圖形界面的方案,我猜測docker也可以通過這種類似遠端桌面的方式來跑桌面。

同時我又尋找了一些開源項目,這裡不得不吐槽下,大家似乎對在docker裡啟桌面都沒什麼興趣,相關資料是真的少...

首先是kde neno,kde neno有docker鏡像的試用,看了下發現采用的是xserver-xwphyr這個方案,但是對于docker鏡像的細節并看不到,遂放棄。

然後我想到了deepin,似乎曾經聽說過他們有相應的docker鏡像,我抱着試試看的心态去找了找,發現确實有一個在docker裡運作桌面的方案,然而是使用xdocker,這個顯然不符合我的預期,隻能放棄。

最後終于在github上找到了這個docker-ubuntu-vnc-desktop 這個項目是在docker裡運作lxde桌面的ubuntu,并通過浏覽器來通路。效果如下

c++builder 運作網站的api_如何在docker中運作ubuntukylin桌面系統

效果相當不錯,趕緊看看人家的dockerfile是如何建構的

# Built with arch: amd64 flavor: lxde image: ubuntu:18.04 localbuild: 1
#
################################################################################
# base system
################################################################################

FROM ubuntu:18.04 as system



RUN sed -i 's#http://archive.ubuntu.com/#http://tw.archive.ubuntu.com/#' /etc/apt/sources.list; 


# built-in packages
ENV DEBIAN_FRONTEND noninteractive
RUN apt update 
    && apt install -y --no-install-recommends software-properties-common curl apache2-utils 
    && apt update 
    && apt install -y --no-install-recommends --allow-unauthenticated 
        supervisor nginx sudo net-tools zenity xz-utils 
        dbus-x11 x11-utils alsa-utils 
        mesa-utils libgl1-mesa-dri 
    && apt autoclean -y 
    && apt autoremove -y 
    && rm -rf /var/lib/apt/lists/*
# install debs error if combine together
RUN add-apt-repository -y ppa:fcwu-tw/apps 
    && apt update 
    && apt install -y --no-install-recommends --allow-unauthenticated 
        xvfb x11vnc=0.9.16-1 
        vim-tiny firefox chromium-browser ttf-ubuntu-font-family ttf-wqy-zenhei  
    && add-apt-repository -r ppa:fcwu-tw/apps 
    && apt autoclean -y 
    && apt autoremove -y 
    && rm -rf /var/lib/apt/lists/*

RUN apt update 
    && apt install -y --no-install-recommends --allow-unauthenticated 
        lxde gtk2-engines-murrine gnome-themes-standard gtk2-engines-pixbuf gtk2-engines-murrine arc-theme 
    && apt autoclean -y 
    && apt autoremove -y 
    && rm -rf /var/lib/apt/lists/*


# Additional packages require ~600MB
# libreoffice  pinta language-pack-zh-hant language-pack-gnome-zh-hant firefox-locale-zh-hant libreoffice-l10n-zh-tw

# tini for subreap
ARG TINI_VERSION=v0.18.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /bin/tini
RUN chmod +x /bin/tini

# ffmpeg
RUN mkdir -p /usr/local/ffmpeg 
    && curl -sSL https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz | tar xJvf - -C /usr/local/ffmpeg/ --strip 1

# python library
COPY image/usr/local/lib/web/backend/requirements.txt /tmp/
RUN apt-get update 
    && dpkg-query -W -f='${Package}n' > /tmp/a.txt 
    && apt-get install -y python-pip python-dev build-essential 
    && pip install setuptools wheel && pip install -r /tmp/requirements.txt 
    && dpkg-query -W -f='${Package}n' > /tmp/b.txt 
    && apt-get remove -y `diff --changed-group-format='%>' --unchanged-group-format='' /tmp/a.txt /tmp/b.txt | xargs` 
    && apt-get autoclean -y 
    && apt-get autoremove -y 
    && rm -rf /var/lib/apt/lists/* 
    && rm -rf /var/cache/apt/* /tmp/a.txt /tmp/b.txt


################################################################################
# builder
################################################################################
FROM ubuntu:18.04 as builder


RUN sed -i 's#http://archive.ubuntu.com/#http://tw.archive.ubuntu.com/#' /etc/apt/sources.list; 


RUN apt-get update 
    && apt-get install -y --no-install-recommends curl ca-certificates gnupg patch

# nodejs
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - 
    && apt-get install -y nodejs

# yarn
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - 
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list 
    && apt-get update 
    && apt-get install -y yarn

# build frontend
COPY web /src/web
RUN cd /src/web 
    && yarn 
    && npm run build



################################################################################
# merge
################################################################################
FROM system
LABEL maintainer="[email protected]"

COPY --from=builder /src/web/dist/ /usr/local/lib/web/frontend/
COPY image /

EXPOSE 80
WORKDIR /root
ENV HOME=/home/ubuntu 
    SHELL=/bin/bash
HEALTHCHECK --interval=30s --timeout=5s CMD curl --fail http://127.0.0.1:6079/api/health
ENTRYPOINT ["/startup.sh"]
           

發現這個鏡像是從最基礎的ubuntu18.04開始建構的,然後安裝桌面對應的包。然後很關鍵的,安裝了xvfb和x11vnc這兩個包。xvfb是虛拟顯示卡,x11vnc則是用來提供x11服務的,以便主機通過x11用戶端來通路桌面。

繼續往下看,略過那些庫,還有兩個重要的操作,一個是把上下文中的web後端部署到docker中,但是我并不清楚開源社會采用什麼方案,我了解裡應該隻需要提供相應的vnc端口即可,是以這一步沒什麼必要。另一個則是

ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /bin/tini

我去到github項目首頁下發現這是個用來初始化并啟動系統的項目,但是似乎新版的docker已經自帶這個功能?于是乎思路已經基本定了,在docker的系統中安裝xvfb和x11vnc,用xvfb虛拟顯示卡,通過x11vnc提供顯示服務。

制作過程

等等,一般的docker鏡像制作都是從基礎鏡像開始建構的,但是我并不清楚ubuntukylin需要哪些包...這下子尴尬了。好在docker可以通過導入tar包來制作鏡像。我找了一台已經安卓ubuntukylin19.04增強版的機器,把根目錄下除了啟動時自動生成的那些目錄打包到一個tar包裡,最後導入到docker制作成鏡像。

tar -cvpf /tmp/system.tar --directory=/ --exclude=proc --exclude=sys --exclude=dev --exclude=run --exclude=boot .
           

其中/proc、/sys、/run、/dev這幾個目錄都是系統啟動時自動生成的,雖然也屬于檔案系統一部分,但是他們每次開機都會有變化,是以打包的時候就應該忽略它們。 然後執行

cat system.tar | docker import - ubuntukylin:19.04
           

這樣,鏡像就制作完畢了。

接下來運作docker,恩?什麼都沒有發生???進入容器一看,發現ligtdm根本沒有啟動,這就很尴尬了...找了半天問題,沒什麼頭緒,大概猜測和systemd有關,一不做二不休,手動啟動ukui-session!恩?什麼情況,我的桌面怎麼沒了,被docker内的ukui占用了,開始運作開機動畫?我進到容器裡檢視,發現/dev目錄下挂載了主控端的裝置,去看了下runc的源碼,最後得出的結論是systemd的改動,使得某些目錄變成shared by default,是以主機顯示卡被docker占用了導緻主機桌面挂掉了...吸取教訓,先把/dev的挂載點删了再啟動...結果卡在登入進不去???然後同僚說ukui-greeter出了bug,但是作者上周剛剛才離職了...行吧,不要登入鎖屏了,直接把這個包解除安裝了。ok,終于成功的進了桌面,等等,視窗管理器怎麼不見了,滑鼠變成x了,想了想發現是自己頭腦混亂了,在管理者權限下啟動了桌面,用su lm(使用者名),切換到普通使用者lm,終于正常了。

但是我不能每次都手動去啟動吧,必須在啟動時自動執行腳本才行,于是在/etc建立了一個rc.local腳本,每次先删除裝置節點,然後通過xvfb建立虛拟顯示卡,設定顯示區域,切換到普通使用者并執行runsession腳本

rm /dev/fb0
rm -rf /dev/dri

export DISPLAY=:1
Xvfb :1 -screen 0 1024x768x16 > /opt/xvfb.log 2>&1 &

sleep 10

su lm -c /home/lm/runukwm
           

runsession腳本

#!/bin/sh

export DISPLAY=:1
DISPLAY=:1 x11vnc -display :1 -forever -bg -nopw -xkb
#sleep 30


export QT4_IM_MODULE=fcitx 
export QT_IM_MODULE=fcitx 
export [email protected]=fcitx 
export GTK_IM_MODULE=fcitx 

/usr/bin/fcitx


QT4_IM_MODULE=fcitx QT_IM_MODULE=fcitx [email protected]=fcitx GTK_IM_MODULE=fcitx DISPLAY=:1 ukui-session > /home/lm/ukui-session.log 2>&1 &
           

腳本裡主要就是啟動了x11vnc設定了一些預設參數,最後啟動ukui-session。這裡要注意的是,rc.local執行腳本的時候會缺失很多環境變量,必須在腳本裡指定,否則會導緻一些異常行為。

至此,docker鏡像完成了。

運作結果

執行

docker run --name test1(容器名) --cap-add ALL --privileged=true -td readlnh/ubuntukylin-vnc-docker:19.04 /sbin/init
           

建立并啟動容器 使用如下指令檢視ip位址

docker inspect test1(容器名)
           

最後通過vncview來連接配接

vncviewer 172.17.0.2(容器ip):5900(預設端口)
           

效果如下

c++builder 運作網站的api_如何在docker中運作ubuntukylin桌面系統