Docker で Shiny Server を立てる

shinyとは、統計言語RでインタラクティブなWebアプリケーションを開発するためのパッケージです。

Shinyアプリを実際に稼働させるとなるといろいろな方法があります。実際にどんな方法があるかはhttps://shiny.rstudio.com/articles/#deploymentを参考にするとよいかと思います。

さて、今回はいろいろな方法の中でもShiny Serverを用いる方法を試してみます。とはいえ、Shiny Serverは現在Linux上でしか動かすことができませんし、Linuxに慣れている方でないとインストールと設定が少し億劫に感じるかもしれません。そこで今回はdockerを用いてShiny Serverを立て、Shinyアプリをデプロイしてみたいと思います。

ありがたいことに Docker Hub に Shiny Server のコンテナが存在するのでこちらを使わせていただきます。単純にコンテナを走らせるだけなら以下のコマンドをdockerを使える権限を持つユーザで打ちます(場合によってはrootで)。tidyverse がプリインストールされているものを使いたい場合は rocker/shiny-verse を用いましょう。

docker run --rm -p 3838:3838 rocker/shiny

ここでブラウザから http://localhost:3838 にアクセスしてみます。Shinyのサンプルページが表示されたら成功です。

ただし、これは一時的なものなので常時起動できるようにしたいと思います。また、自作アプリをデプロイするとき、わざわざファイルをコンテナ内に移すのは面倒なので、ホストのディレクトリにコンテナ内のShinyアプリを保存するディレクトリをマウントします(ついでにログ用のディレクトリもホスト側にマウントされるようにしておきます)。

docker run -d -p 80:3838 \
    -v /srv/shinyapps/:/srv/shiny-server/ \
    -v /srv/shinylog/:/var/log/shiny-server/ \
    rocker/shiny

まず -d オプションでバックグランドで起動することを指定しています。また、 -p 80:3838 とすることでShiny Serverがパケットを受け付ける3838ポートをホストの80にポートフォワーディングすることができます。80番は一般的なHTTPプロトコルのポートとなっているので、ブラウザでわざわざポート番号をURLの後ろにつける必要がなくなります(すでにホストの80番を他のソフト(例えばapache)で使っている場合は不可)。

-v /srv/shinyapps/:/srv/shiny-server/ および -v /srv/shinylog/:/var/log/shiny-server/ の部分はそれぞれ、コンテナ内の /srv/shiny-server/ をホストの /srv/shinyapps/に、/var/log/shiny-server をホストの /srv/shinylog/ にマウントしています。前者はアプリのファイルを格納する場所、後者はログが吐き出される場所です。それぞれの環境に合わせてディレクトリを決めましょう。

この状態でもう一度 http://localhost にアクセスしてみます。今度は :3838 はいりません。すると先程マウントしたホスト側のディレクトリに何も保存していない場合は「Index of /」のような表示しか現れないと思います。

そこで簡単に最初のページを自作して先程マウントした場所(例では /srv/shinyapps/index.html として保存してみたいと思います。

index.htmlの例

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>Shinyアプリ置き場</title>
  </head>
  <body>
    <h1>Shinyアプリ置き場</h1>
    <p>ようこそ、ここでは自作Shinyアプリが利用できます。</p>
    <ul>
      <li><a href="/AppName/">AppName</a></li>
    </ul>
  </body>
</html>

http://localhost にアクセスして先程のindex.htmlの内容が見えていれば成功です。

あとは自作のアプリのディレクトリ(app.R または ui.Rserver.R の組が保存されているディレクトリ)を /srv/shinyapps/ 配下にコピーすればアプリをデプロイすることができます。ディレクトリをコピーできたら http://localhost/AppName/ (AppNameは適宜変えてください)にアクセスし、アプリが使えたら成功です。すぐにアプリのアドレスにアクセスできるように先程作った最初のページにリンクを貼っておくと便利でしょう。

最後に、自作アプリが他のRパッケージに依存している場合についてですが、 apt install r-cran-* は使わず、 R上で install.packages を使ってインストールします。コンテナ内に一回入ってシェルからRを起動したりしてでもできますが、以下のコマンドでいちいちコンテナ内に入らなくてもできると思います。

docker exec コンテナ名 R --vanilla -e 'install.packages(c("パッケージ名1", "パッケージ名2"), repos = "CRANミラーのアドレス")

割と簡単にShiny Serverを立てることができました。ちなみに、マシンを再起動するとDockerコンテナが停止してしまうのでその時はまたコンテナも起動させないといけません。