Linux
docker

dockerでデスクトップ環境(GUI)を構築する

はじめに

私は普段使いのOSとしてArch Linuxを使っているのですが、ubuntuを触りたいときが稀にあります。Virtual BoxではOSのインストール作業、起動停止の遅さやメモリの圧迫などが気になります。なので、dockerでデスクトップ環境を構築する方法を模索しました。

2018-03-26-003556_1366x768_scrot.png

記事の中程にDockerfileを載せています。

Xephyr

dockerでGUIを使う方法はいくつかありますが、ホストがLinuxなので手軽にホストのX serverで描画します。Xephyr は X アプリケーションとして実行されるネストされた X serverです。
ubuntuならapt install xserver-xephyr、arch linuxならpacman -S xorg-server-xephyrでインストールできます。
Xephyr -resizeable :1で可変ウィンドウでディスプレイ番号1のX serverを起動します。
イメージ作成時あるいはコンテナ起動時に環境変数でディスプレイ番号を指定します。
-e DISPLAY=:1 ENV DISPLAY=:1

サウンド

音の出力はホストのpulse audioのサーバーを使います。コンテナ起動時にホストのソケットファイルを共有します。cookieによる認証を行っているのでそれも共有しておきます。
-v /run/user/$UID/pulse/native:/tmp/pulse/native
-v $HOME/.config/pulse/cookie:/tmp/pulse/cookie

環境変数でpathを指定します。

ENV PULSE_SERVER=unix:/tmp/pulse/native \
    PULSE_COOKIE=/tmp/pulse/cookie

タイムゾーン

tzdataをインストール時にタイムゾーンを聞かれてビルドが止まるので、apt installする前にexport DEBIAN_FRONTEND=noninteractiveを実行しておきます。
ENV TZ=Asia/Tokyoで指定します。

日本語入力

ENV GTK_IM_MODULE=fcitx \
    QT_IM_MODULE=fcitx \
    XMODIFIERS=@im=fcitx \
    DefalutIMModule=fcitx

デスクトップ環境やウィンドウマネージャの設定ファイルで、起動時に実行するコマンドを指定します。jwmの場合は下記です。

~/.jwmrc
<JWM>
  ...
  <StartupCommand>
    fcitx-autostart
    fcitx-imlist -e fcitx-keyboard-jp
    fcitx-imlist -s fcitx-keyboard-jp,mozc,fcitx-keyboard-us
  </StartupCommand>
  ...
</JWM>

ユーザの作成

UIDはホストのUIDに合わせます。サウンド出力のときに使用するcookieを参照できるようにするためです。
--build-arg DOCKER_UID=$(id -u)

ARG DOCKER_USER=docker
ARG DOCKER_UID=1000
ARG DOCKER_PASSWORD=docker
RUN useradd -m --uid ${DOCKER_UID} --groups sudo --shell /bin/bash ${DOCKER_USER} \
      && echo ${DOCKER_USER}:${DOCKER_PASSWORD} | chpasswd

デスクトップ環境,ウィンドウマネージャ

  • jwmというスタック型ウィンドウマネージャをインストールします。jwmはタスクバーが予めあり、設定ファイルが分かりやすく、非常に軽量です。画面をクリックするとmenuが出ます。
  • 注意点としてキーバインドが重複するとホストが優先されます。ctrlとshiftを同時に押すことで、キーバインドやマウスカーソルのスコープをjwm(ネストしているX server)だけに限定できます。

DockerFile

FROM ubuntu:18.04

# 使っていない値を指定します
ENV DISPLAY=:1

# ミラーの変更
RUN sed -i 's@archive.ubuntu.com@ftp.jaist.ac.jp/pub/Linux@' /etc/apt/sources.list

RUN export DEBIAN_FRONTEND=noninteractive \
    && apt update \
    && apt install -y x11-xserver-utils \
                   xinit \
                   tzdata \
                   language-pack-ja-base \
                   language-pack-ja \
                   sudo \
                   jwm \
                   lxterminal \
                   alsa-utils \
                   pulseaudio \
                   pulseaudio-utils \
                   fonts-ipafont-gothic \
                   dbus-x11 \
                   fcitx-mozc \
                   fcitx-imlist \
                   vim-gtk3 \
                   libcurl4 \
                   epiphany-browser \
                   curl

# 音
ENV PULSE_SERVER=unix:/tmp/pulse/native \
    PULSE_COOKIE=/tmp/pulse/cookie

# 日本語
RUN locale-gen ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8

# タイムゾーン
ENV TZ=Asia/Tokyo

# 日本語入力
ENV GTK_IM_MODULE=fcitx \
    QT_IM_MODULE=fcitx \
    XMODIFIERS=@im=fcitx \
    DefalutIMModule=fcitx

# docker内で使うユーザを作成。
# ホストと同じUIDにする。ホストのpulseaudioのcookieを触るときに、permision deniedにならない。
ARG DOCKER_UID=1000
ARG DOCKER_USER=docker
ARG DOCKER_PASSWORD=docker
RUN useradd -m --uid ${DOCKER_UID} --groups sudo --shell /bin/bash ${DOCKER_USER} && echo ${DOCKER_USER}:${DOCKER_PASSWORD} | chpasswd

WORKDIR /home/${DOCKER_USER}

# lxterminalの設定。フォントをIPAフォントにし、カラースキームを変更しています。
RUN curl -L https://raw.githubusercontent.com/tayusa/docker-jwm/master/config/lxterminal.conf -o ./.config/lxterminal/lxterminal.conf

# jwmの設定。menuにlxterminalとepiphany-browserを追加しています。
# フォントをIPAフォントに変更しています。キーバインドも変更しています。
RUN curl -L https://raw.githubusercontent.com/tayusa/docker-jwm/master/config/jwmrc -o ./.jwmrc

RUN chown -R ${DOCKER_USER} ./

USER ${DOCKER_USER}

CMD jwm

インストールするパッケージ一覧

パッケージ名 概要
x11-xserver-utils X window system (GUI)
xinit X window system (GUI)
tzdata TimeZone
language-pack-ja-base 日本語
language-pack-ja 日本語
sudo
jwm 軽量なスタック型 window manger
lxterminal ターミナル
alsa-utils
pulseaudio
fonts-ipafont-gothic 日本語フォント
dbus-x11 Xクライアントの通信。日本語入力するのに必要。
fcitx-mozc 日本語入力
fcitx-imlist fcitxの設定をコマンドで行うために必要
vim-gtk3 エディタ
libcurl4 ブラウザの依存パッケージ
epiphany-browser ブラウザ
curl ファイルダウンロード用

作成・起動

argを指定しないと uid=1000,user=docker,password=docker になります。

docker build \
    -t ubuntu-jwm \
    --build-arg DOCKER_UID=$(id -u) \
    --build-arg DOCKER_USER='ユーザ名' \
    --build-arg DOCKER_PASSWORD='パスワード' .

環境変数DISPLAYを:1にした場合は、Xephyr -resizeable :1を実行後にdocker runを実行します。

docker run \
    -v /tmp/.X11-unix/:/tmp/.X11-unix/ \
    -v /run/user/$UID/pulse/native:/tmp/pulse/native \
    -v $HOME/.config/pulse/cookie:/tmp/pulse/cookie \
    -it --rm ubuntu-jwm

dockerの起動を楽にする

毎回、コマンドを打ってdockerを起動するのは辛いので関数を書きます。

function jwm() {
  docker info &> /dev/null \
    || { echo 'Is the docker daemon running?' && return ;}
  [[ -e /tmp/.X11-unix/X1 ]] \
    || Xephyr -wr -resizeable :1 &> /dev/null &
  docker run \
    -v /tmp/.X11-unix/:/tmp/.X11-unix/ \
    -v /run/user/$UID/pulse/native:/tmp/pulse/native \
    -v $HOME/.config/pulse/cookie:/tmp/pulse/cookie \
    -it --rm ubuntu-jwm &> /dev/null
  pkill Xephyr
}