📤

Dockerコンテナ上でGUIアプリを表示する(Linux)

2021/12/11に公開

前提

  • Dockerインストール済みLinux

概要

準備

  • bashで実行することを想定
  • ホストマシンにログインしているユーザのIDを確認し「ARG UID」に記載(デフォルト:1000)
  • イメージ名を決める(デフォルト:xeyes_container)

イメージ作成

Dockerfileを準備

host bash
touch Dockerfile
vim Dockerfile
Dockerfile
FROM ubuntu:latest

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-get update && apt-get install -y \
       x11-apps \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && useradd -m -u ${UID} user

イメージをビルド

host bash
docker build -t xeyes_container .

起動

host bash
docker run \
  --net=bridge \
  --shm-size=4096m \
  --rm \
  -t \
  -e DISPLAY \
  -v /tmp/.X11-unix/X0:/tmp/.X11-unix/X0 \
  -u `id -u` \
  xeyes_container xeyes

これでコンテナ内のGUIアプリが起動できます。

解説

要点

user idを共通にする

Xの認証を通すためにホストのユーザーと同じUIDで起動する必要があります。
(参考)
ユーザIDを揃えないと認証エラーとなります。

host bash
$ docker run --net=bridge --shm-size=4096m --rm -t -e DISPLAY -v /tmp/.X11-unix/X0:/tmp/.X11-unix/X0 xeyes_container xeyes
Authorization required, but no authorization protocol specified
Error: Can't open display: :0

DISPLAYを共有する

Xサーバ名をホスト側から伝える必要があります。
(参考)

host bash
$ echo $DISPLAY
:0

$DISPLAYにはサーバ名とサーバ番号が記載されています。「(ホスト名):(サーバ番号)」
今回の例は「(localhost):(0番のXサーバ)」という意味。

X11用のunixドメインソケットを共有する

Xの通信を行うためにX用のドメインソケットを共有します。

Dockerfile解説

Dockerfile
FROM ubuntu:latest

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-get update && apt-get install -y \
       x11-apps \ # テスト用アプリをインストール
    && apt-get clean \ # キャッシュ削除
    && rm -rf /var/lib/apt/lists/* \ # キャッシュ削除
    && useradd -m -u ${UID} user # 一般ユーザ追加

起動コマンド解説

host bash
docker run \
  --net=bridge \ # ネットワークモード
  --shm-size=4096m \ # メモリサイズ
  --rm \ # コンテナ終了時削除
  -t \ # tty
  -e DISPLAY \ # X サーバ名
  -v /tmp/.X11-unix/X0:/tmp/.X11-unix/X0 \ # X サーバソケット
  -u `id -u` \ # ホスト側のユーザIDと同じユーザIDを指定する
  xeyes_container xeyes # イメージ名とコマンドを指定する

Discussion