はじめに
こんにちは、テクノロジー本部の田中です。
アドベントカレンダー13日目です。
今回は、以前に個人的興味があってやってみた話「Docker上の仮想環境でブラウザを動かしてみた」を書きたいと思います。
よくあるパターン : NoVNC を利用したブラウザから動かす仮想環境
この手の話題でよくあるのが、ブラウザから動かす仮想環境の話です。
VNC は Virtual Network Computing というリモートデスクトップのソフトウェアで、NoVNCは、それの OSS です。
これを用いて、Docker上で仮想環境を動かしてブラウザを起動します。
どうやるか
以下が NoVNC を動作させる Dockerfile と docker-compose.yml です。 (謎に tor-browser を入れているのは個人的な趣味です...w)
- Dockerfile
FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt update -y && apt install --no-install-recommends -y xfce4 xfce4-goodies tigervnc-standalone-server novnc websockify sudo xterm init systemd snapd vim net-tools curl wget git tzdata RUN apt update -y && apt install -y dbus-x11 x11-utils x11-xserver-utils x11-apps RUN apt install software-properties-common -y RUN add-apt-repository ppa:mozillateam/ppa RUN apt update RUN apt -y install firefox-esr firefox-esr-locale-ja RUN apt -y install vlc RUN apt update -y && apt install -y xubuntu-icon-theme RUN apt update -y && apt install -y fonts-noto-cjk RUN apt update -y && apt install -y locales RUN locale-gen ja_JP.UTF-8 ENV LANG=ja_JP.UTF-8 ENV LANGUAGE=ja_JP:ja ENV LC_ALL=ja_JP.UTF-8 RUN touch /root/.Xauthority RUN apt update && apt install -y sudo ARG USERNAME=user ARG GROUPNAME=user ARG UID=1000 ARG GID=1000 ARG PASSWORD=admin RUN groupadd -g $GID $GROUPNAME && \ useradd -m -s /bin/bash -u $UID -g $GID -G sudo $USERNAME && \ echo $USERNAME:$PASSWORD | chpasswd && \ echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers USER $USERNAME WORKDIR /home/$USERNAME/ RUN wget https://www.torproject.org/dist/torbrowser/13.5.2/tor-browser-linux-x86_64-13.5.2.tar.xz RUN tar -Jxvf tor-browser-linux-x86_64-13.5.2.tar.xz EXPOSE 5901 EXPOSE 6080 CMD ["bash", "-c", "vncserver -localhost no -SecurityTypes None -geometry 1920x1080 --I-KNOW-THIS-IS-INSECURE && openssl req -new -subj '/C=JP' -x509 -days 365 -nodes -out self.pem -keyout self.pem && websockify -D --web=/usr/share/novnc/ --cert=self.pem 6080 localhost:5901 && tail -f /dev/null"]
- docker-compose.yml
services: tor-browser: build: context: . tty: true container_name: 'tor-browser' ports: - 8080:6080
動作させると以下の画面が出てきます。
問題点
日本語がバグる!
こっちは早急に解決!
Locale を日本設定と日本語フォントを入れました。
余談ですが、日本語入力は未だできない...
音声が出ない!
こっちが割と根が深い問題でして...
Ubuntu の音声は PulseAudio というソフトウェアを用いています。
それが、ブラウザから取得できないという感じです。
ネットワーク越しに音声を出力するための解決策
- PulseAudio を利用
この場合は音声を出力する Port の設定とそれをブラウザに通す能力が必要です。
速攻、あきらめました。 (解決策が、PulseAudio 内の javascript をいじるまでは、わかるがブラウザもいじらないといけないことに絶望) - Bluetooth 接続 または、それ以外の方法で音声を出力 ( Chrome の RDP 拡張機能を使うとか)
これは選択肢として微妙でした... ( Bluetooth は Docker 周りが上記のやつ同様面倒だし、RDP は単純に利用が煩わしくなる)
結局どうしたか : Docker上で直にブラウザを呼び出してみる
色々、考えた結果....
xeyes を起動できるコンテナを作成してみる。
↓
xeyes から Firefox や Google Chrome に置き換える。
↓
音声や画面などは、WSL2 の bus 周りから取得すれば動作可能。
ということで、Chat-GPT などで壁打ちしながら完成しました...!
以下のファイルで $ docker-compose up -d
をすると Firefox が起動します。
- Dockerfile
FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive ARG UID=1000 # ホストのユーザーIDと一致させる RUN sed -i.org -e 's|ports.ubuntu.com|jp.archive.ubuntu.com|g' /etc/apt/sources.list \ && apt update \ && apt install -y software-properties-common \ && add-apt-repository ppa:mozillateam/ppa \ && apt install -y \ firefox-esr \ firefox-esr-locale-ja \ tzdata \ dbus-x11 \ fcitx-mozc \ pulseaudio \ fonts-noto-cjk \ locales \ libpci-dev \ && ln -s -f /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \ && dpkg-reconfigure tzdata \ && locale-gen ja_JP.UTF-8 \ && touch /root/.Xauthority \ && apt clean \ && rm -rf /var/lib/apt/lists/* \ && usermod -l user $(getent passwd ${UID} | cut -d: -f1) || useradd -m -u ${UID} user ENV LANG=ja_JP.UTF-8 ENV LANGUAGE=ja_JP:ja ENV LC_ALL=ja_JP.UTF-8 ENV XMODIFIERS=@im=fcitx ENV GTK_IM_MODULE=fcitx ENV QT_IM_MODULE=fcitx RUN echo '#!/bin/bash\nfcitx &\nexec firefox-esr' > /usr/local/bin/start.sh \ && chmod +x /usr/local/bin/start.sh CMD ["/usr/local/bin/start.sh"]
- docker-compose.yml
services: firefox: build: context: . network_mode: bridge shm_size: '4096m' environment: - DISPLAY=${DISPLAY} - PULSE_COOKIE=/tmp/pulse/cookie - PULSE_SERVER=unix:/tmp/pulse/native - XMODIFIERS=@im=fcitx - GTK_IM_MODULE=fcitx - QT_IM_MODULE=fcitx - DefaultIMModule=fcitx - DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus volumes: - /tmp/.X11-unix:/tmp/.X11-unix - /run/user/1000/pulse/native:/tmp/pulse/native - ~/.config/pulse/cookie:/tmp/pulse/cookie:ro - /run/user/1000/bus:/run/user/1000/bus user: "${UID:-1000}" tty: true
補足
コンテナ側の環境変数 DISPLAY をホスト側の DISPLAY をセットすることが必要です。
WSL2 だと $ echo $DISPLAY
で値が出てくると思いますので、うまく調整してください。
成功すると...
まとめ
ということで、無事に完成しました!
色々と最適化されていない問題とか音声がたまに流れないとかありますが...
ともあれ、やりたいことができたので無問題です。