Ubuntu18.04でDockerとCaddyを使用してGUIアプリケーションにリモートアクセスする方法
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
クラウドサービスの人気が高まっているにもかかわらず、ネイティブアプリケーションを実行する必要性は依然として存在します。
noVNCおよびTigerVNCを使用すると、 Docker コンテナー内でネイティブアプリケーションを実行し、Webブラウザーを使用してそれらにリモートでアクセスできます。 さらに、ローカルで利用できるよりも多くのシステムリソースを備えたサーバーでアプリケーションを実行できるため、大規模なアプリケーションを実行する際の柔軟性が向上します。
このチュートリアルでは、Dockerを使用して、メールクライアントである MozillaThunderbirdをコンテナ化します。 その後、セキュリティで保護し、 CaddyWebサーバーを使用してリモートアクセスを提供します。
終了すると、Webブラウザだけを使用して任意のデバイスからThunderbirdにアクセスできるようになります。 オプションで、WebDAVを使用してローカルからファイルにアクセスすることもできます。 また、どこでも実行できる完全に自己完結型のDockerイメージがあります。
前提条件
このガイドを開始する前に、次のものが必要です。
- 少なくとも2GBのRAMと4GBのディスクスペースを備えた1台のUbuntu18.04サーバー。
- root以外のユーザー
sudo
特権。 - サーバーにDockerがセットアップされました。 Ubuntu18.04にDockerをインストールして使用する方法に従うことができます。
ステップ1—作成 supervisord
構成
サーバーが実行され、Dockerがインストールされたので、アプリケーションのコンテナーの構成を開始する準備が整いました。 コンテナは複数のコンポーネントで構成されているため、プロセスマネージャを使用してそれらを起動および監視する必要があります。 ここでは、supervisordを使用します。 supervisord
はPythonで記述されたプロセスマネージャーであり、複雑なコンテナーを調整するためによく使用されます。
まず、というディレクトリを作成して入力します thunderbird
あなたのコンテナのために:
- mkdir ~/thunderbird
- cd ~/thunderbird
次に、というファイルを作成して開きます supervisord.conf
を使用して nano
またはお好みの編集者:
- nano supervisord.conf
次に、この最初のコードブロックをに追加します supervisord.conf
、supervisordのグローバルオプションを定義します。
[supervisord]
nodaemon=true
pidfile=/tmp/supervisord.pid
logfile=/dev/fd/1
logfile_maxbytes=0
このブロックでは、構成しています supervisord
自体。 設定する必要があります nodaemon
に true
Dockerコンテナ内でエントリポイントとして実行されるためです。 したがって、フォアグラウンドで実行し続ける必要があります。 あなたも設定しています pidfile
root以外のユーザーがアクセスできるパス(これについては後で詳しく説明します)、および logfile
ログを表示できるようにstdoutに。
次に、別の小さなコードブロックをに追加します supervisord.conf
. このブロックは、VNC/X11サーバーを組み合わせたTigerVNCを起動します。
...
[program:x11]
priority=0
command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
このブロックでは、X11サーバーをセットアップしています。 X11 は、GUIアプリケーションの実行を可能にするディスプレイサーバープロトコルです。 将来的にはWaylandに置き換えられますが、リモートアクセスはまだ開発中であることに注意してください。
このコンテナには、TigerVNCとその組み込みVNCサーバーを使用しています。 これには、個別のX11サーバーとVNCサーバーを使用するよりも多くの利点があります。
- GUI描画は、中間フレームバッファ(画面のコンテンツを格納するメモリ)に対して行われるのではなく、VNCサーバーに対して直接行われるため、応答時間が短縮されます。
- 画面の自動サイズ変更。これにより、リモートアプリケーションは、クライアント(この場合はWebブラウザーウィンドウ)に合わせて自動的にサイズ変更できます。
必要に応じて、の引数を変更できます -desktop
からのオプション Thunderbird
あなたが選んだ他の何かに。 サーバーは、アプリケーションへのアクセスに使用されるWebページのタイトルとして選択内容を表示します。
次に、コードの3番目のブロックをに追加しましょう supervisord.conf
始めること easy-novnc
:
...
[program:easy-novnc]
priority=0
command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
このブロックでは、 easy-novnc をセットアップします。これは、noVNCのラッパーを提供するスタンドアロンサーバーです。 このサーバーは2つの役割を果たします。 まず、接続のオプションを構成したり、デフォルトのオプションを設定したりできる簡単な接続ページを提供します。 次に、 WebSocket を介してVNCをプロキシします。これにより、通常のWebブラウザーからアクセスできるようになります。
通常、サイズ変更はクライアント側で行われます(つまり 画像スケーリング)、しかしあなたは使用しています resize=remote
TigerVNCのリモート解像度調整を最大限に活用するオプション。 これにより、ローエンドのChromebookなどの低速デバイスでのレイテンシも低くなります。
注:このチュートリアルでは easy-novnc
. ご希望の場合は、 websockify
代わりに別のWebサーバー。 の利点 easy-novnc
メモリ使用量と起動時間が大幅に少なく、自己完結型であるということです。 easy-novnc
また、デフォルトのnoVNCページよりもクリーンな接続ページを提供し、このセットアップに役立つデフォルトのオプションを設定できます( resize=remote
).
次に、次のブロックを構成に追加して、ウィンドウマネージャーであるOpenBoxを起動します。
...
[program:openbox]
priority=1
command=/usr/bin/openbox
environment=DISPLAY=:0
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
このブロックでは、軽量のX11ウィンドウマネージャーであるOpenBoxをセットアップしています。 この手順をスキップすることもできますが、この手順がないと、タイトルバーがないか、ウィンドウのサイズを変更できません。
最後に、最後のブロックをに追加しましょう supervisord.conf
、メインアプリケーションを起動します:
...
[program:app]
priority=1
environment=DISPLAY=:0
command=/usr/bin/thunderbird
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
この最後のブロックでは、設定しています priority
に 1
Thunderbirdがafter TigerVNCを起動するようにするため。そうしないと、競合状態が発生し、ランダムに起動に失敗します。 また、設定します autorestart=true
誤って閉じた場合にアプリケーションを自動的に再度開きます。 The DISPLAY
環境変数は、前に設定したVNCサーバーに表示するようにアプリケーションに指示します。
これがあなたの完成したものです supervisord.conf
次のようになります:
[supervisord]
nodaemon=true
pidfile=/tmp/supervisord.pid
logfile=/dev/fd/1
logfile_maxbytes=0
[program:x11]
priority=0
command=/usr/bin/Xtigervnc -desktop "Thunderbird" -localhost -rfbport 5900 -SecurityTypes None -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -AcceptSetDesktopSize -SendCutText -AcceptCutText :0
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
[program:easy-novnc]
priority=0
command=/usr/local/bin/easy-novnc --addr :8080 --host localhost --port 5900 --no-url-password --novnc-params "resize=remote"
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
[program:openbox]
priority=1
command=/usr/bin/openbox
environment=DISPLAY=:0
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
[program:app]
priority=1
environment=DISPLAY=:0
command=/usr/bin/thunderbird
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
別のアプリケーションをコンテナ化する場合は、 /usr/bin/thunderbird
アプリケーションの実行可能ファイルへのパスを使用します。 それ以外の場合は、GUIのメインメニューを構成する準備ができています。
ステップ2—OpenBoxメニューの設定
プロセスマネージャが設定されたので、OpenBoxメニューを設定しましょう。 このメニューを使用すると、コンテナ内でアプリケーションを起動できます。 必要に応じて、デバッグ用の端末とプロセスモニターも含まれます。
アプリケーションのディレクトリ内で、 nano
または、お気に入りのテキストエディタを使用して、という新しいファイルを作成して開きます。 menu.xml
:
- nano ~/thunderbird/menu.xml
次に、次のコードをに追加します menu.xml
:
<?xml version="1.0" encoding="utf-8"?>
<openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/ file:///usr/share/openbox/menu.xsd">
<menu id="root-menu" label="Openbox 3">
<item label="Thunderbird">
<action name="Execute">
<execute>/usr/bin/thunderbird</execute>
</action>
</item>
<item label="Terminal">
<action name="Execute">
<execute>/usr/bin/x-terminal-emulator</execute>
</action>
</item>
<item label="Htop">
<action name="Execute">
<execute>/usr/bin/x-terminal-emulator -e htop</execute>
</action>
</item>
</menu>
</openbox_menu>
このXMLファイルには、デスクトップを右クリックしたときに表示されるメニュー項目が含まれています。 各アイテムは、ラベルとアクションで構成されています。
別のアプリケーションをコンテナ化する場合は、 /usr/bin/thunderbird
アプリケーションの実行可能ファイルへのパスを使用して、 label
アイテムの。
ステップ3—Dockerfileを作成する
OpenBoxが構成されたので、すべてを結び付けるDockerfileを作成します。
コンテナのディレクトリにDockerfileを作成します。
- nano ~/thunderbird/Dockerfile
まず、ビルドするコードを追加しましょう easy-novnc
:
FROM golang:1.14-buster AS easy-novnc-build
WORKDIR /src
RUN go mod init build && \
go get github.com/geek1011/[email protected] && \
go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
最初の段階では、あなたは構築しています easy-novnc
. これは、単純化とスペースの節約のために別の段階で行われます。最終的な画像にGoツールチェーン全体を含める必要はありません。 に注意してください @v1.1.0
ビルドコマンドで。 これにより、結果が決定論的であることが保証されます。これは、Dockerが各ステップの結果をキャッシュするため重要です。 明示的なバージョンを指定しなかった場合、Dockerは最新バージョンの easy-novnc
イメージが最初に作成されたとき。 さらに、特定のバージョンの easy-novnc
、CLIインターフェイスに重大な変更が加えられた場合。
次に、最終的なイメージになる2番目のステージを作成しましょう。 ここでは、ベースイメージとしてDebian 10(バスター)を使用します。 これはコンテナで実行されているため、サーバーで実行しているディストリビューションに関係なく機能することに注意してください。
次に、次のブロックを Dockerfile
:
...
FROM debian:buster
RUN apt-get update -y && \
apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && \
rm -rf /var/lib/apt/lists && \
mkdir -p /usr/share/desktop-directories
この手順では、Debian 10をベースイメージとしてインストールしてから、コンテナでGUIアプリケーションを実行するために最低限必要なものをインストールします。 実行することに注意してください apt-get update
Dockerからのキャッシュの問題を防ぐための同じ命令の一部として。 スペースを節約するために、後でダウンロードしたパッケージリストも削除します(キャッシュされたパッケージ自体はデフォルトで削除されます)。 あなたも作成しています /usr/share/desktop-directories
一部のアプリケーションは既存のディレクトリに依存しているためです。
別の小さなコードブロックを追加しましょう:
...
RUN apt-get update -y && \
apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && \
rm -rf /var/lib/apt/lists
この手順では、いくつかの便利な汎用ユーティリティとパッケージをインストールします。 ここで特に興味深いのは xdg-utils
(Linux上のデスクトップアプリケーションで使用される基本コマンドを提供します)および ca-certificates
(ルート証明書をインストールして、HTTPSサイトにアクセスできるようにします)。
これで、メインアプリケーションの手順を追加できます。
...
RUN apt-get update -y && \
apt-get install -y --no-install-recommends thunderbird && \
rm -rf /var/lib/apt/lists
以前と同様に、ここではアプリケーションをインストールしています。 別のアプリケーションをコンテナ化する場合は、これらのコマンドを特定のアプリのインストールに必要なコマンドに置き換えることができます。 一部のアプリケーションは、Docker内で実行するためにもう少し作業が必要になります。 たとえば、Chrome、Chromium、またはQtWebEngineを使用するアプリをインストールする場合は、コマンドライン引数を使用する必要があります --no-sandbox
Docker内ではサポートされないためです。
次に、最後のいくつかのファイルをコンテナに追加するための手順の追加を開始しましょう。
...
COPY /bin/easy-novnc /usr/local/bin/
COPY menu.xml /etc/xdg/openbox/
COPY supervisord.conf /etc/
EXPOSE 8080
ここでは、前に作成した構成ファイルをイメージに追加し、 easy-novnc
最初の段階からのバイナリ。
この次のコードブロックは、データディレクトリを作成し、アプリの専用ユーザーを追加します。 一部のアプリケーションはrootとしての実行を拒否するため、これは重要です。 コンテナ内であっても、rootとしてアプリケーションを実行しないこともお勧めします。
...
RUN groupadd --gid 1000 app && \
useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && \
mkdir -p /data
VOLUME /data
一貫性を確保するため UID/GID
ファイルの場合、両方を明示的に設定しています 1000
. また、データディレクトリにボリュームをマウントして、再起動してもボリュームが持続するようにします。
最後に、すべてを起動するための手順を追加しましょう。
...
CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
デフォルトのコマンドをに設定する supervisord
、マネージャーは、アプリケーションの実行に必要なプロセスを起動します。 この場合、使用しています CMD
それよりも ENTRYPOINT
. ほとんどの場合、違いはありませんが、 CMD
いくつかの理由から、この目的に適しています。 初め、 supervisord
私たちに関連する引数を取りません。コンテナに引数を指定すると、それらは置き換えられます。 CMD
およびに追加されます ENTRYPOINT
. 第二に、 CMD
まったく異なるコマンドを提供できます(これはによって実行されます /bin/sh -c
)コンテナに引数を渡す場合。これにより、デバッグが容易になります。
そして最後に、あなたは実行する必要があります chown
開始する前にルートとして supervisord
データボリュームのパーミッションの問題を防ぎ、子プロセスを開くことができるようにするため stdout
. これはまた、あなたが使用する必要があることを意味します gosu
の代わりに USER
ユーザーを切り替えるための指示。
これがあなたの完成したものです Dockerfile
次のようになります:
FROM golang:1.14-buster AS easy-novnc-build
WORKDIR /src
RUN go mod init build && \
go get github.com/geek1011/[email protected] && \
go build -o /bin/easy-novnc github.com/geek1011/easy-novnc
FROM debian:buster
RUN apt-get update -y && \
apt-get install -y --no-install-recommends openbox tigervnc-standalone-server supervisor gosu && \
rm -rf /var/lib/apt/lists && \
mkdir -p /usr/share/desktop-directories
RUN apt-get update -y && \
apt-get install -y --no-install-recommends lxterminal nano wget openssh-client rsync ca-certificates xdg-utils htop tar xzip gzip bzip2 zip unzip && \
rm -rf /var/lib/apt/lists
RUN apt-get update -y && \
apt-get install -y --no-install-recommends thunderbird && \
rm -rf /var/lib/apt/lists
COPY /bin/easy-novnc /usr/local/bin/
COPY menu.xml /etc/xdg/openbox/
COPY supervisord.conf /etc/
EXPOSE 8080
RUN groupadd --gid 1000 app && \
useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && \
mkdir -p /data
VOLUME /data
CMD ["sh", "-c", "chown app:app /data /dev/stdout && exec gosu app supervisord"]
保存して閉じます Dockerfile
. これで、コンテナをビルドして実行し、GUIアプリケーションであるThunderbirdにアクセスする準備が整いました。
ステップ4—コンテナの構築と実行
次のステップは、コンテナをビルドし、起動時に実行するように設定することです。 また、再起動と更新の間でアプリケーションデータを保持するボリュームを設定します。
まず、コンテナを作成します。 これらのコマンドは、必ず ~/thunderbird
ディレクトリ:
- docker build -t thunderbird .
次に、アプリのコンテナ間で共有される新しいネットワークを作成します。
- docker network create thunderbird-net
次に、アプリケーションデータを保存するボリュームを作成します。
- docker volume create thunderbird-data
最後に、それを実行し、自動的に再起動するように設定します。
- docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-app thunderbird
必要に応じて、 thunderbird-app
後に --name
別の名前のオプション。 選択したものが何であれ、アプリケーションはコンテナ化されて実行されます。 それでは、Caddy Webサーバーを使用してサーバーを保護し、リモートで接続してみましょう。
ステップ5—キャディを設定する
このステップでは、認証と、オプションでWebDAVを介したリモートファイルアクセスを提供するようにCaddyWebサーバーを設定します。 簡単にするため、また既存のリバースプロキシで使用できるようにするために、別のコンテナで実行します。
新しいディレクトリを作成し、その中に移動します。
- mkdir ~/caddy
- cd ~/caddy
今すぐ新しいを作成します Dockerfile
を使用して nano
またはお好みの編集者:
- nano ~/caddy/Dockerfile
次に、次のディレクティブを追加します。
FROM golang:1.14-buster AS caddy-build
WORKDIR /src
RUN echo 'module caddy' > go.mod && \
echo 'require github.com/caddyserver/caddy/v2 v2.1.1' >> go.mod && \
echo 'require github.com/mholt/caddy-webdav v0.0.0-20200523051447-bc5d19941ac3' >> go.mod
RUN echo 'package main' > caddy.go && \
echo 'import caddycmd "github.com/caddyserver/caddy/v2/cmd"' >> caddy.go && \
echo 'import _ "github.com/caddyserver/caddy/v2/modules/standard"' >> caddy.go && \
echo 'import _ "github.com/mholt/caddy-webdav"' >> caddy.go && \
echo 'func main() { caddycmd.Main() }' >> caddy.go
RUN go build -o /bin/caddy .
FROM debian:buster
RUN apt-get update -y && \
apt-get install -y --no-install-recommends gosu && \
rm -rf /var/lib/apt/lists
COPY /bin/caddy /usr/local/bin/
COPY Caddyfile /etc/
EXPOSE 8080
RUN groupadd --gid 1000 app && \
useradd --home-dir /data --shell /bin/bash --uid 1000 --gid 1000 app && \
mkdir -p /data
VOLUME /data
WORKDIR /data
CMD ["sh", "-c", "chown app:app /data && exec gosu app /usr/local/bin/caddy run -adapter caddyfile -config /etc/Caddyfile"]
このDockerfileは、WebDAVプラグインを有効にしてCaddyをビルドし、ポートで起動します 8080
とともに Caddyfile
で /etc/Caddyfile
. ファイルを保存して閉じます。
次に、CaddyWebサーバーを構成します。 名前の付いたファイルを作成します Caddyfile
作成したディレクトリ:
- nano ~/caddy/Caddyfile
次に、次のコードブロックを Caddyfile
:
{
order webdav last
}
:8080 {
log
root * /data
reverse_proxy thunderbird-app:8080
handle_path /files/* {
file_server browse
}
redir /files /files/
handle /webdav/* {
webdav {
prefix /webdav
}
}
redir /webdav /webdav/
basicauth /* {
{env.APP_USERNAME} {env.APP_PASSWORD_HASH}
}
}
これ Caddyfile
ルートディレクトリをにプロキシします thunderbird-app
手順4で作成したコンテナー(Dockerはそれを正しいIPに解決します)。 また、読み取り専用のWebベースのファイルブラウザも提供します。 /files
でWebDAVサーバーを実行します /webdav
これをローカルにマウントしてファイルにアクセスできます。 ユーザー名とパスワードは環境変数から読み取られます APP_USERNAME
と APP_PASSWORD_HASH
.
次に、コンテナを作成します。
- docker build -t thunderbird-caddy .
Caddy v.2では、希望するパスワードをハッシュする必要があります。 次のコマンドを実行し、置き換えることを忘れないでください mypass
選択した強力なパスワードを使用して:
- docker run --rm -it thunderbird-caddy caddy hash-password -plaintext 'mypass'
このコマンドは、文字列を出力します。 次のコマンドを実行する準備として、これをクリップボードにコピーします。
これで、コンテナを実行する準備が整いました。 必ず交換してください myuser
選択したユーザー名で置き換え、 mypass-hash
前の手順で実行したコマンドの出力を使用します。 ポートを変更することもできます(8080
ここ)別のポートでサーバーにアクセスするには:
- docker run --detach --restart=always --volume=thunderbird-data:/data --net=thunderbird-net --name=thunderbird-web --env=APP_USERNAME="myuser" --env=APP_PASSWORD_HASH="mypass-hash" --publish=8080:8080 thunderbird-caddy
これで、アプリケーションにアクセスしてテストする準備が整いました。
ステップ6—アプリケーションのテストと管理
アプリケーションにアクセスして、機能していることを確認しましょう。
まず、開く http://your_server_ip:8080
Webブラウザーで、前に選択した資格情報を使用してログインし、接続をクリックします。
これで、アプリケーションを操作できるようになり、ブラウザウィンドウに合わせて自動的にサイズが変更されます。
黒いデスクトップを右クリックすると、端末にアクセスできるメニューが表示されます。 中クリックすると、ウィンドウのリストが表示されます。
開催中 http://your_server_ip:8080/files/
Webブラウザで。 ファイルにアクセスできるはずです。
オプションで、マウントを試すことができます http://your_server_ip:8080/webdav/
WebDAVクライアントで。 ファイルに直接アクセスして変更できるはずです。 Windowsエクスプローラーでマップネットワークドライブオプションを使用する場合は、リバースプロキシを使用してHTTPSを追加するか、設定する必要があります。 HKLM\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\BasicAuthLevel
に DWORD:2
.
いずれの場合も、ネイティブGUIアプリケーションをリモートで使用できるようになります。
結論
これで、Thunderbird用のDockerコンテナーが正常にセットアップされ、Caddyを使用して、Webブラウザーを介したコンテナーへのアクセスが構成されました。 アプリをアップグレードする必要がある場合は、コンテナーを停止して実行します docker rm thunderbird-app thunderbird-web
、イメージを再構築してから、 docker run
上記の前の手順のコマンド。 データはボリュームに保存されるため、引き続き保持されます。
基本的なDockerコマンドについて詳しく知りたい場合は、このチュートリアルまたはこのチートシートをお読みください。 長期間使用する場合は、セキュリティを強化するためにHTTPS(これにはドメインが必要です)を有効にすることも検討してください。
さらに、複数のアプリケーションをデプロイする場合は、各コンテナーを手動で起動する代わりに、DockerComposeまたはKubernetesを使用することをお勧めします。 また、このチュートリアルは、サーバー上で次のような他のLinuxアプリケーションを実行するためのベースとして機能することを忘れないでください。
- Wine 、LinuxでWindowsアプリケーションを実行するための互換性レイヤー。
- GIMP 、オープンソースの画像エディタ。
- Cutter 、オープンソースのリバースエンジニアリングプラットフォーム。
この最後のオプションは、GUIアプリケーションをコンテナ化してリモートアクセスする大きな可能性を示しています。 この設定により、Cutterのようなリソースを大量に消費するツールを実行するために、ローカルで使用するよりもかなり多くの計算能力を備えたサーバーを使用できるようになります。