podman で shiny-server

## 0. はじめに
* きっかけ：
Debian でいろいろと運用している。shiny-server は Debian のパッケージと、それとは別に入れたパッケージが混在して状態で運用していた。Debian 12 にしたときに、shiny-server が動かなくなった。このストレスから開放されるために、コンテナを利用する。
* この文章の目的：
  * コンテナを扱ったことがなかった私の備忘録として
  * docker でなく podman を使った場合の例として
  * shiny-server を立ち上げる手順として

## 1. インストール
### 1.1 podman
```bash:
apt update
apt upgrade
apt install podman
```
### 1.2 名前空間の設定
ファイルを編集して、次のような記述を追加する。この記述は、uid,gid それぞれ、500000から、65536個分という意味になる。すでにエントリーがある場合には、重ならないように設定する必要があるので注意する。先頭に# を入れればコメントになるので説明を入れておくと良い。username のところは、自分のログイン名とする。
```bash:/etc/subuid
# for podman
username:500000:65536
```
```bash:/etc/subgid
# for podman
username:500000:65536
```
設定を反映させるためにシステムを再起動する。（再起動させないで反映させる方法がありそうだけど。）
## 2. 基本操作
hello-world を例に、基本的な操作についてまとめる。
### 2.1 イメージの取得
``podman pull docker.io/hello-world``
### 2.2 イメージからコンテナを作成して実行
``podman run hello-world``
run では、pull(ダウンロード)したイメージから新しいコンテナを作成して実行する。（巷のdockerの解説に表示されているようなことが表示される。）
### 2.3 コンテナ一覧
* ps
``podman ps``
この段階では、実行中のものはない。hello-world は、文字列を表示して終了している。そこで何も表示されない。
* ps -a
``podman ps -a``
実行中でないものも含めてコンテナが表示される。そこで、ここではhello-world のコンテナが表示される。
### 2.4 停止と再稼働
* 停止
``podman stop [コンテナIDか名前]``
* 再稼働
``podman start [コンテナIDか名前]``
### 2.5 コンテナの削除
``podman rm [コンテナIDか名前]``
で、削除。イメージは削除されない。
### 2.6 イメージの操作
* イメージの一覧
``podman images``
* イメージの削除（コンテナを削除しないと削除できない）
``podman rmi [イメージIDまたはイメージ名:タグ]``
### 2.7 その他の重要な情報
* コンテナをデタッチモード（バックグラウンド）で実行
``podman run -d ....``
* コンテナのポートに外部からアクセス（ホストマシンのポートを転送）
``podman run -p [ホストのポート]:[コンテナのポート] ....``
* コンテナからホストのファイルにアクセス（マウント）
``podman run -v [ホストのパス]:[コンテナのパス] ....``
　※ -v は複数指定できる。
* コンテナ内のbash を立ち上げる。
``podman exec -it [コンテナ名またはID] bash``
### 2.8 システム起動時に自動起動
systemd を利用する。具体例を以下のshiny-server の項で示す。

## 3. shiny-sever の導入
### 3.1 イメージそのままでの実行
これまでの情報だけで運用できるかな？
```bash:
podman pull docker.io/rocker/shiny
podman -d -p 3838:3838 -v /srv/shiny-server:/srv/shiny-server rocker/shiny
```
これで、http://(podmanを動かしているマシン):3838/ にアクセスすれば、shiny-server が動いていることが確認できる。
良かった！すばらしい！ここまでは…。
### 3.2 カスタムイメージ
ところが、私は、R にいくつかのパッケージを入れて運用している。それを入れなければ動かない。起動する度に、bash で入ってパッケージを入れるのは困難だ。そこで、イメージをカスタマイズする。
適当なディレクトリで、次の Dockerfile を作成する。
```bash:Dockerfile
# ベースイメージとしてrocker/shinyを使用
FROM rocker/shiny:latest

# 必要なシステム依存関係をインストール
RUN apt-get update && apt-get install -y \
    libnetcdf-dev \
    netcdf-bin

# Rパッケージをインストール
RUN R -e "install.packages('ncdf4', dependencies=TRUE)"
```
その上で、次のコマンドを実行する。
``podman build -t custom-shiny-app .``
これで、新しいイメージ `custum-shiny-app` ができたので、これを run すれば良い。
　
注意:
* ファイル中の RUN 以降はコマンドになっている。rocker/shiny のベースのシステムは Ubuntu なので、apt を使っている。
　
* カスタムイメージを更に変更するには、`FROM` の部分を `FROM localhost/custom-shiny-app` と、先程作ったイメージを指定すればよい。 
### 3.3 自動起動
※ 以下に systemd を使う方法を書いたが、うまくいかない。→ とりあえず、crontab で起動時に実行するようにする。
　→ crontab でもうまく動かないようだ。保留。
1. ~~設定ファイルを作る~~
``` bash:/etc/systemd/system/myshiny.service
[Unit]
Description=My Shiny Container

[Service]
Restart=always
ExecStart=/usr/bin/podman start [コンテナIDか名前]
ExecStop=/usr/bin/podman stop [コンテナIDか名前]

[Install]
WantedBy=multi-user.target
```
~~この設定ファイルでは、一度、shiny-server のコンテナを作成して実行していることを前提としている。テストしてから自動起動に移行すると思うので、それで問題ないはず。~~
　
2\. ~~登録~~
```bash:
sudo systemctl daemon-reload
sudo systemctl enable myshiny.service
```

## 4. コメント
* Debian のパッケージ vs コンテナ
コンテナは、動くことが（かなり）確実なので手軽に使える。しかし、手を加えようとすると敷居が高くなる。多くのパッケージ依存性があるアプリを、安定的に運用するのにはコンテナが良さそうだ。
 　
 
 * ~~自動起動で実行するのは root
自動起動にする場合には、スーパーユーザー(root)になってしまう。podman にした意味があまりないような気もする。~~