[Docker入門]コンテナにsshでアクセスするための設定メモ

- [目的](#目的)
- [やりたいこと](#やりたいこと)
- [この記事でわかること](#この記事でわかること)
- [環境](#環境)
- Dockerfile ※すみません、上手く記事内にリンクできませんでした。
- [まとめ](#まとめ)
- [参考](#参考)
- [補足:シェルスクリプトでsshdを起動する方法](#補足)

#[目的]#
Dockerの使い方を勉強していて、sshで接続するところで苦労したので、やり方をメモっておきます。初心者が試行錯誤した結果なので、もっと良い方法があると思います。もしご存知でしたら教えていただけますと幸いです。

#[やりたいこと]#
以下やりたいことです。

- 公式のubuntu18.04のイメージを使って、sshが設定済みのイメージを作成したい。
- sshでのアクセスでは公開鍵認証を使用したい。
- 必要な設定はビルド時、つまりDockerfileで完了させたい。
- コンテナを起動したら直ぐに、sshコマンドでホスト側からアクセスできる状態にしたい。

以下やりたく無いことです。

- コンテナにアクセスして、手動で直接設定を修正することはやりたくない。

#[この記事でわかること]#

ビルド時にsshの設定を完了させて、コンテナを起動した時点でホスト側から公開鍵を使ってsshでアクセスできるようにする方法がわかります。

#[環境]#
[ホスト側]

- MacOS Mojave
- Docker Desktop Community 2.1.0.5

[コンテナ側]

- ubuntu18.04

#[Dockerfile]#

作成したDockerfileです。公開鍵(id_rsa.pub)をイメージにコピーしていますが、id_rsa.pubの配置場所は、Dockerfileがあるフォルダ下作成したconfigフォルダです。

```dockerfile:Dockerfile
# どのイメージを基にするか
FROM ubuntu:18.04

# 作成したユーザの情報
LABEL maintainter="kuboshu83"

# sshサーバをインストールします
RUN apt-get update && apt-get install -y openssh-server
# これが無いとsshdが起動しないっぽい
RUN mkdir /var/run/sshd
# rootのパスワードをrootpasswdに設定します。ただし、公開鍵認証でのアクセスなので使用しませんが。。
RUN echo 'root:rootpassws' | chpasswd
# sshのrootでのアクセスを許可します。ただし、パスワードでのアクセスは無効
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
# sshのポートを22 => 20022に変更します
RUN sed -i 's/#Port 22/Port 20022/' /etc/ssh/sshd_config
# ホスト側にある公開鍵をイメージ側に登録します
COPY ./config_files/id_rsa.pub /root/.ssh/authorized_keys

EXPOSE 20022
CMD ["/usr/sbin/sshd", "-D"]
```

# [接続方法] #
## ＜イメージのビルド＞ ##
以下のコマンドでビルドします。今回はイメージの名前とタグをそれぞれ*default_repo*と*default_tag*にしています。

```shell
docker build -t default_repo:default_tag .
```

## ＜コンテナの起動＞ ##
以下のコマンドで作成したイメージからコンテナを起動します。

```shell
docker run -itd -p 20021:20022 default_repo:default_tag
```

## ＜ホスト側からコンテナに接続＞ ##
ホスト側からは以下のコマンドで接続できます。ホスト(localhost)の20021ポートに接続すると、コンテナ側の20022ポートに
転送されます。

```shell
ssh root@localhost -p 20021
```

# [まとめ] #
ubuntu18.04を基にsshでアクセスできるイメージをビルドし、ホスト側からsshでアクセスできるようになりました。

# [参考] #
[Dockerドキュメント:sshdデーモン用サービスのDocker化](http://docs.docker.jp/engine/examples/running_ssh_service.html)

# [補足] #
色々試している中で、上以外の方法でも起動できたので一応メモっておきます。ざっくりいうと、sshdの起動をDockerfileで行わず、sshdの再起動用のシェルスクリプト(setup.sh)を作成して、コンテナ起動時に.bashrcで実行するというものです。この方法だと、setup.shに書き込む内容によって、色々設定が可能なので個人的には便利だと思っています。このような方法をやって良いか悪いかは今の僕の知識では判断できませんが(^^;

## ＜作成したファイル＞ ##
この方法では、Dockerfileとsshd再起動用のシェルスクリプト(setup.sh)を作成します。

### Dockerfile ###
```dockerfile:Dockerfile
# どのイメージを基にするか
FROM ubuntu:18.04

# 作成したユーザの情報
LABEL maintainter="kuboshu83"

# RUN: docker buildする時に実行される
RUN apt-get update && \
apt-get install -y --no-install-recommends openssh-server

# ビルド時にsshd_configを修正
RUN sed -i 's/#PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/#Port 22/Port 20022/' /etc/ssh/sshd_config
# ビルド時に公開鍵を登録
COPY ./config_files/id_rsa.pub /root/.ssh/authorized_keys

# コンテナの起動時にsshdを再起動するようにする
COPY ./config_files/setup.sh /root/
RUN  chmod a+x /root/setup.sh
RUN  echo "/root/setup.sh" >> /root/.bashrc
```

### setup.sh ###

setup.shの配置場所は、Dockerfileを配置したディレクトリ下に作成したconfigファイルです。

```bash:./config/setup.sh
#!/bin/bash 
echo "restart ssh service"
service ssh restart
```

## ＜接続方法＞ ##
接続方法は先ほどと同じです。