Dockerのコンテナ内でgithubのssh認証を使えるようにする(入門)

# はじめに

皆さん開発ではgitをよく使われると思います。

近年githubでは二段階認証が義務化されたことにより、今までpush等をするときにパスワードを打っていたけどssh key等に頼リ始めた人も多いと思います。

https://cloud.watch.impress.co.jp/docs/news/1484808.html

しかし、ssh接続を用いた認証で困るのはDockerで開発中のアプリのコンテナを作成したときです。

なぜなら、sshキーがコンテナ内に無いのでgitでpush等するときに毎回~~クソめんどくさい~~二段階認証をする必要があるからです。

本記事ではdockerでgithubに接続するための二段階認証をssh-agentを用いて安全に自動化する方法について解説します。

使用するOSはWindows 11 Homeです。

# ssh-agentとは

Dockerのコンテナ内でgithubのssh認証を最も手っ取り早く使う方法はコンテナ内にsshキーをコピーして使うことです。(実際そういう風に指導している記事も結構あります)

しかし、imageの中にsshキーのファイルをコピーしてしまうと、imageをDocker hub等で公開したときや、他人にimageを共有した時に、ssh keyが漏洩してしまう危険があります。

そこで、コンテナ内にssh keyをコピーするのでは無く、ssh-agentというSSHキーの管理と認証を効率的に行うためのツールを用いてより事故が起こらない様にします。

そこで本記事ではアプリを作成するコンテナとssh-agentでssh keyを管理するコンテナを分けることによってssh keyを開発環境にコピーすること無くssh認証が出来るようにします。

開発用のコンテナで作業している時に、ssh keyを管理するコンテナがssh-agentを貸し出し、githubとのssh接続を可能とします。

本記事ではアプリ用のコンテナはpythonで作るものとします。


# Step 1: ssh keyをgithubに登録しよう

まず二段階認証を行うためには、githubにssh keyを登録する必要があります。

これについてはとてもわかりやすい記事があるので以下の記事を参考にしてください。

https://qiita.com/shizuma/items/2b2f873a0034839e47ce

# Step 2:docker-compose.ymlを書こう

まず、アプリ用のDockerfileとssh-agent用のDockerfileをどのように関連付けるかを定義するためにdocker-compose.ymlを書きます。

ディレクトリ構成は以下のようにしてください。

    workspace/
        │
        ┣ ─ docker-compose.yml
        │
        ┣ ─ requirements.txt
        │
        ┣ ─ app/
        │    │
        │    ┣ ─ Dockerfile
        │ 
        │
        ┣ ─ ssh/
             │
             ┣ ─ Dockerfile
             │
             ┣ ─ init.sh

docker-compose.ymlは以下のようなファイルにしてください。

```yml:docker-compose.yml
    
version: '3.10'

services:

  web:

    build:
      context: ./
      dockerfile: /app/Dockerfile
    tty: true
    ports:
      - "8000:8000"
    #sshコンテナと通信できるようにする
    networks:
      - ssh_net

  ssh:

    build: ./ssh
    #web containerが立ち上がるのと同時に立ち上がるようにする
    depends_on:
      - web
    tty: true
    # ssh keyをマウント
    volumes:
      - type: bind
        source: ~/.ssh
        target : /root/.ssh
    #web containerと通信できるようにする
    networks:
      - ssh_net

networks:
  ssh_net:

```

これによって、sshコンテナはwebコンテナと共に立ち上がるようになりました。

appディレクトリのDockerfileを以下のように書いてください。

```dockerfile:Dockerfile
FROM python:3.10.11

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
    
RUN apt-get -y install git

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

#ssh serverを立ち上げる為のライブラリをインストール
RUN apt-get install -y openssh-server

# SSHの設定
RUN mkdir /var/run/sshd
RUN echo 'root:Docker!' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config

RUN pip install --upgrade pip==23.2.1
RUN pip install --upgrade setuptools

WORKDIR /root/workspaces

COPY . .

#ssh接続用のポート
EXPOSE 22

#アプリ用のポート
EXPOSE 8000

RUN pip install -r requirements.txt

#ssh serverを立ち上げ
CMD ["/usr/sbin/sshd", "-D"]
```

これにより、22番ポートでssh接続をwebコンテナは受け付けるようになります。

RUN echo 'root:Docker!' | chpasswd
の部分は適時変更してください。

次にsshディレクトリのDockerfileを以下のようにしてください

```dockerfile:Dockerfile

FROM ubuntu:latest

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
    
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

#ssh接続用のライブラリをインストール
RUN apt-get install -y openssh-server

COPY . root/sh

#shell scriptを起動
ENTRYPOINT ["root/sh/init.sh"]
```

これによって、sshコンテナが起動するたびにsshディレクトリのinit.shが実行されるようになりました。

次に、sshコンテナが起動したときに、webコンテナにssh-agentを転送するために、init.shを以下のようにしてください

```bash:init.sh
#!/bin/bash

PASSWORD = "Docker!"

#ssh agentを起動
eval "$(ssh-agent)"

#初めてのコンテナ起動の時
if [ -z "$first_flag" ]; then
  export first_flag=0 

  #ssh-agentにssh keyの登録
  ssh-add

  #ssh keyの権限変更
  chmod 600 /root/.ssh/*
  chmod 600 /root/.ssh/id_rsa

　#ssh接続
  echo "yes" "$PASSWORD"| ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -A web

else

　#ssh接続
  echo "PASSWORD" | ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -A web

fi
```

これによってssh-agentがwebコンテナへとssh接続で転送されるようになります。
PASSWORD = "Docker!"
の部分は適時変更してください。

# Step 3:コンテナを立ち上げる。

Powershellに

```bash:Powershell
docker-compose up
```
と打てば、webコンテナとsshコンテナが起動し、自動的にsshコンテナがssh-agentをwebコンテナへと転送します。

これによってwebコンテナ内でgithubのssh認証が使えるようになりました。

# おわりに

OSがLinuxやMacであれば、環境変数SSH_AUTH_SOCKをコンテナにコピーするだけでssh-agentをコンテナに移植することができるのですが、Windowsでは~~厄介なことに~~SSH_AUTH_SOCKを使用せずにssh-agentが動いているのでその方法をとることが出来ませんでした。

Dockerを使えば環境の差を埋めることが出来ますが、完全に消せるわけでは無いって事を痛感しました