すぐ使えるSSH実験用Dockerの作成

# TL;DR

## Packageのinstall

```Dockerfile
RUN apk add --no-cache openssh openrc
```

## sshdの起動

```Dockerfile
RUN rc-update add sshd && rc-status
RUN mkdir -p /run/openrc/ && touch /run/openrc/softlevel
```

## Port Forwardingの設定

```Dockerfile
RUN sed -i 's/^AllowTcpForwarding no/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
RUN sed -i 's/^GatewayPorts no/GatewayPorts yes/g' /etc/ssh/sshd_config
RUN sed -i 's/^X11Forwarding no/X11Forwarding yes/g' /etc/ssh/sshd_config
```

## ユーザーの作成、Password付与(パスワードないと、なぜかpublicKeyでもloginできない)

```Dockerfile
RUN adduser -D ssh-user
# It will cause an ssh login error if user has no password
RUN echo "ssh-user:ssh-pass" | chpasswd
# If need sudo
RUN apk add --no-cache sudo
RUN echo "ssh-user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
```

## 公開秘密鍵の作成&導入

```Dockerfile
RUN mkdir $HOME/.ssh
RUN ssh-keygen -m PEM -t rsa -b 1024 -C "ssh-user@example.com" -N "" -f $HOME/.ssh/id_rsa
RUN cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys
```

# はじめに
先日、筆者は[『SSHポートフォワーディングのプチ魔術』](https://qiita.com/jerrywdlee/items/ab866de2c1b6781f5e4f)という記事を書きました。
当時はAWS EC2を一台借りでSSHの実験をしましたが、どうももったいないと思いました。

実は昔からVagrantでSSHの実験をしましたが、今回はあえてDockerで同じことできるようにします。

# Dockerfile

このようなDockerfileを作成しました。一番サイズが小さいと言われる`alpine`を使いました。筆者の都合で`node`のコンテナを選びましたが、[alpine](https://hub.docker.com/_/alpine)のみでも結構です。

```Dockerfile
FROM node:10.15.3-alpine
LABEL maintainer="Iuliana Augusta <iuliana.augusta@gmail.com>"
RUN set -x && apk update && apk upgrade \
  && apk add --no-cache openssh openrc

# For debug
# RUN apk add --no-cache bash vim

RUN rc-update add sshd && rc-status
RUN mkdir -p /run/openrc/ && touch /run/openrc/softlevel

# Enable Port Forwarding
RUN sed -i 's/^AllowTcpForwarding no/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
RUN sed -i 's/^GatewayPorts no/GatewayPorts yes/g' /etc/ssh/sshd_config
RUN sed -i 's/^X11Forwarding no/X11Forwarding yes/g' /etc/ssh/sshd_config

RUN adduser -D ssh-user
# It will cause an ssh login error if user has no password
RUN echo "ssh-user:ssh-pass" | chpasswd
# If need sudo
# RUN apk add --no-cache sudo
# RUN echo "ssh-user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

USER ssh-user
RUN mkdir $HOME/.ssh
RUN ssh-keygen -m PEM -t rsa -b 1024 -C "ssh-user@example.com" -N "" -f $HOME/.ssh/id_rsa
RUN cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys

USER root
RUN cp /home/ssh-user/.ssh/id_rsa $HOME/ssh-user.pem

CMD /etc/init.d/sshd start && tail -f /dev/null

```

# Docker Compose
前述した`Dockerfile`をそのまま起動しても構いませんが、`docker-compose.yml`を作成すれば、より省力化できると思います。

```docker-compose.yml
version: '3.7'
services:
  ssh-test:
    # image: node:10.15.3-alpine
    container_name: ssh-test
    build:
      context: ./
      dockerfile: ./Dockerfile
    working_dir: /root
    volumes:
      - ./share:/root/share
    ports:
      - "20080:80"
      - "20443:443"
      - "20022:22"
      - "23000:3000"
      - "23030:3030"
      - "28000:8000"
      - "28080:8080"
    command: /bin/sh -c "/etc/init.d/sshd start && tail -f /dev/null"
```

よく使われる`80, 443, 22, 3000, 3030, 8000, 8080`を全部開放しました。  
わかりやすくするために、全部のポートをプラス`20000`のポートを、ホストに割り当てます。

これで準備が完了しました、`docker-compose build`でコンパイルしてみれば、本体が85.1MBでベースの`node:10.15.3-alpine`を併せても、150MBくらいしかありません。


```sh
$ docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
ssh_test_ssh-test                latest              13b7daa0eaad        29 minutes ago      85.1MB
node                             10.15.3-alpine      94f3c8956482        3 weeks ago         71MB
```

# SSH接続

上記`Dockerfile`が書いたように、秘密鍵が`/root/ssh-user.pem`にコピーされたので、それをホストマシーンに持って行けばOKです。

```sh
$ docker exec ssh-test cat /root/ssh-user.pem > ssh-user.pem 
$ chmod 600 ssh-user.pem
```

早速ポートフォワードで試してみましょう。

```sh
# localhost:3030 にサーバーが動いているとして
$ ssh -R 8080:localhost:3030 -i ssh-user.pem ssh-user@localhost -p 20022
```

こうすれば、`localhost:3030`のサーバーが`localhost:28080`でアクセスできるようになります。


# 参考
https://wiki.alpinelinux.org/wiki/Setting_up_a_ssh-server
https://blog.adachin.me/archives/4177