sshログインした時に任意の画像を出現させるようにするのをDockerでしてみた

# TL;DR
* 画像ファイルを指定するとPPM形式もどきの画像を出力するコンテナ作った
* URLでも画像を指定できるようにした
* ``/etc/motd``に置くとSSHログイン時に画像が出てきて楽しい
* 任意と言っても32x32くらいのサイズの画像でないと微妙

実行例
![スクリーンショット 2018-10-15 00.12.07.png](https://qiita-image-store.s3.amazonaws.com/0/116209/bd49edec-6462-35f9-1f5d-ee2998819a14.png)

# 背景
以前この記事でmotdの存在を知った。
[AWSにsshログインした時にスライムを出現するようにしてみた。](https://qiita.com/tu-kun/items/d38452161bfb9da54bcd)

SSHログインした際に``/etc/motd``に書かれたテキストが表示されるが、そこに特殊な形式の画像を置いておくと画像が表示されるとのこと。
当然他の画像でもやってみたいと思ったが、そもそもこの画像もどきが何者なのかがわからなかったので調べてみると、以下の記事が見つかった。
[サーバーログイン時に超力技でドット絵を表示する](https://qiita.com/hasegit/items/3e9a08ef3c743c17806c)

この画像もどきは基本的にはPPM形式の画像（テキストデータでドット単位の色が指定された画像形式）だが、PPM表記のRGBをANSI Color表記に置き換えたものらしい。
そして、ImageMagickを使うとJPGやPNGなどの一般的な画像形式からPPMに変換できるらしい。

確かに簡単にできるが、いちいちどこかのサーバで画像を作って持っていくのは手間だし、
無闇矢鱈とImageMagickをインストールするのも嫌である。

ということでDockerコンテナ化して気軽に使えるようにしてみた。
おそらく簡単なシェルスクリプト実行するだけのコンテナ作成の参考にもなるかと思う。
ちなみに、イメージのサイズは77.7MBです。

# 方法
1. Dockerfile作成
2. 画像を取得する（コンテナrun時に引数として指定）
3. 2の画像をImageMagickでPPM形式の画像に変換する
4. PPM表記のRGBをANSI Color表記に変換する
5. 変換結果を出力（コンテナrun時の出力）

実際に行ったことは、Dockerfileの作成と引用元のシェルスクリプトを若干変更しただけ。

# コード

## Dockerfile

```bash:Dockerfile
FROM alpine:3.6

RUN apk update --no-cache \
    && apk --no-cache add \
        imagemagick \
        curl \
        wget \
        bash

COPY ./make_sprite_motd.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/make_sprite_motd.sh
```

スクリプト改変すればbash不要かもしれないが、そこまで作り込む必要性も感じないので気にせずインストールしている。
curlはインストールしておかないとImageMagickの実行でエラーが出る。

## 変換スクリプト

なるべく引用元のスクリプトをそのまま使おうとしたが、利便性を考慮して以下の3箇所だけ変更

* 画像をURL指定でも実行できるように画像変換部分にif文追加した``(14～20行目)``
  * wgetでコンテナ内部に画像を保存しているだけ（コンテナ削除で一緒に消える）
  * 先頭が``http``かどうかで判定しているが、もっと良い判定方法ある気がする
* 出力結果をディスプレイにも表示するようにcat追加した``(57行目)``
  * ファイルに出力するだけだと、コンテナ内部に結果が出力された後にコンテナごと消えてしまう
  * catしておけば、コンテナrunの結果をリダイレクトすればホスト側にファイルを出力できる
* 透過色を引数で指定可能にした``(7～10行目)``
  * デフォルトは白(255;255;255)にしているが、背景色が白でない場合も引数で対応可能に  
  （場合によっては最大が255ではなく65535の場合もあるようなので、それにも対応可能）

```bash:make_sprite_motd.sh
#!/bin/bash
# Description : convert dot image to motd
# Author      : hasegit Fork S_SenSq
# Notes       : install imagemagick before

# for replace transparent color
transparent_before_r=${2:-255}
transparent_before_g=${3:-255}
transparent_before_b=${4:-255}
transparent_before="${transparent_before_r};${transparent_before_g};${transparent_before_b}"
transparent_after="0;0;0"

# convert image to ppm and output to stdout
if [[ $1 =~ ^http ]] ;
then
  wget $1 -O img > /dev/null 2>&1
  ppm=$(convert img -compress none ppm:- 2>/dev/null)
else
  ppm=$(convert ${1:-a} -compress none ppm:- 2>/dev/null)
fi

# convert error check
if [ -z "${ppm}" ] ; then
    echo -e "Convert Error or Imagemagick is not installed.\nUsage: ${0} <any dot image>"
    exit 1
fi

# set ppm data to positional parameter,
# get cols, then discard ppm parameters
set ${ppm}
cols=${2}
shift 4

{
    # get three each values (rgb) from ppm
    for i in $(eval echo {1..${#}..3})
    do
        j=$((i+1))
        k=$((i+2))

        rgb="${!i};${!j};${!k}"

        # replace transparent color
        if [ ${rgb} == ${transparent_before} ] ; then
          rgb=${transparent_after}
        fi

        # start a new line when reach cols
        if [ $(( (${i} + 2) / 3 % ${cols} )) -eq 0 ] ; then
          echo -e "\033[48;2;${rgb}m  \033[m"
        else
          echo -en "\033[48;2;${rgb}m  \033[m"
        fi
    done
} > ./dot_image

cat ./dot_image

exit 0
```

# 使い方

## ディレクトリ構成

docker-composeを使うほどでも無いので、Dockerfileとスクリプトファイルを置いておくだけ。

```bash
. (カレントディレクトリ)
└── build
    ├── Dockerfile
    └── make_sprite_motd.sh
```

## イメージのビルド

buildディレクトリを指定して普通にビルドするだけ。
タグ（名前）を指定しないと扱うのが面倒になるので``-t``オプションだけ指定

```bash
docker build build/ -t motd
```

## 実行

URL指定の場合は単純

```bash
docker run --rm motd make_sprite_motd.sh http://hogehoge.png
# --rmを付けないと死んだコンテナが残り続けてしまう
```

ローカルファイル指定の場合はコンテナにマウントする必要があるので若干長い

```bash
docker run --rm -v $PWD/hogehoge.png:/image motd make_sprite_motd.sh /image
# カレントにhogehoge.pngという名前の画像ファイルを置いておく
# ホスト側の$PWD/hogehoge.pngをコンテナ側に/imageとしてマウントする
```

ホスト側の``/etc/motd``に置く場合は単純にリダイレクトするだけ。

```bash
docker run --rm motd make_sprite_motd.sh http://hogehoge.png > /etc/motd
```

これだけでSSHログイン時に画像が出力されるようになる。
なお、文字サイズにもよりますが、32x32px程度のサイズの画像でちょうどいい大きさです。
``vi``とかで普通に編集できるので、無駄な余白が気になる場合は適当に行削除して下さい。

## 実行例

```bash
docker run --rm motd make_sprite_motd.sh https://img.atwikiimg.com/www65.atwiki.jp/pixelmon-jp/attach/15/5/001.png 65535 65535 65535
```

![スクリーンショット 2018-10-15 00.12.07.png](https://qiita-image-store.s3.amazonaws.com/0/116209/bd49edec-6462-35f9-1f5d-ee2998819a14.png)

ふしぎだね