Docker 便利なコンテナを作成できるDockerfileを紹介させてください

# 投稿目的
<ul>
<li>よりよい方法をご教授いただきたい</li>
</ul>



# 本題
### きっかけ
個人開発やちょっとした検証を行う際、WSL上に環境を作成するのではなく、Dockerのコンテナを作成し、その中に環境を作成しています。
これまでは、作成したコンテナ内の環境とGitリポジトリを紐づける際に、「`ssh-keygen`コマンドをコンテナ内で実行」 → 「GitHubにSSH鍵を登録」という流れを踏んでいました。
このため、コンテナが増えるにつれてGitHubのSSH鍵の数が肥大化してきていました。 (数えたら**15個**ありました...多い...)

この状況を解決するため、WSL上に存在するSSH鍵を、そのまま新しく作成するコンテナでも用いることができるようなDockerfileを作成し、このDockerfileをもとにコンテナを作成するように改めました。



### Dockerfileの作成
今回Dockerfileを作成するディレクトリは以下の通りとします。
```bash
# ホームディレクトリの下の「dockerfiles」ディレクトリ
$ pwd
~/dockerfiles

# Dockerfileを作成する
$ vi Dockerfile
```
Dockerfileの中身は以下の通りです。
```Dockerfile
FROM ubuntu:latest

# 必要なパッケージ類のインストール(ご自身が必要と思うものを追加してください)
RUN apt-get upgrade && apt-get update && apt-get install -y \
  sudo\
  wget\
  git\
  curl\
  tree\
  ssh\
  net-tools\
  docker.io\
  docker-compose-v2\
  python3-setuptools

# ユーザを追加し、sudoをパスワードなしで有効化する
ARG USERNAME=<あなたのユーザ名>
ARG GROUPNAME=<あなたのグループ名>
ARG UID=<あなたのユーザID>
ARG GID=<あなたのグループID>
ARG PASSWORD=<あなたのパスワード>
RUN groupadd -g $GID $GROUPNAME && \
    useradd -m -s /bin/bash -u $UID -g $GID -G sudo $USERNAME && \
    echo $USERNAME:$PASSWORD | chpasswd && \
    echo "$USERNAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER $USERNAME
WORKDIR /home/$USERNAME/

# Gitのタブ補完を有効化するためのスクリプトを取得
RUN wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -O ~/.git-completion.bash
RUN wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -O ~/.git-prompt.sh

# このDockerfileが存在するディレクトリにgit-prompt-sample.txtを作成し、.bashrcに記載したい内容を書いておく
COPY git-prompt-sample.txt /home/$USERNAME/git-prompt-sample
RUN cat git-prompt-sample >> .bashrc

# SSH鍵のコピー
COPY <秘密鍵のファイル名> /home/$USERNAME/.ssh/<秘密鍵のファイル名>
COPY <公開鍵のファイル名> /home/$USERNAME/.ssh/<公開鍵のファイル名>
```

ポイントは以下です。

#### sudoを有効化
[Spritaro 様 「Dockerコンテナに一般ユーザーを追加するときのDockerfileの設定」](https://qiita.com/Spritaro/items/602118d946a4383bd2bb)
コンテナ作成後に`tree`コマンドや`netstat`コマンドをインストールしたいのに「`sudo`が使えないから`apt-get install tree net-tools`ができない...」ということがあったため、`sudo`を有効化しています。
```Dockerfile
# 必要なパッケージ類のインストール(ご自身が必要と思うものを追加してください)
RUN apt-get upgrade && apt-get update && apt-get install -y \
  sudo\
  ...

# ユーザを追加し、sudoをパスワードなしで有効化する
ARG USERNAME=<あなたのユーザ名>
ARG GROUPNAME=<あなたのグループ名>
ARG UID=<あなたのユーザID>
ARG GID=<あなたのグループID>
ARG PASSWORD=<あなたのパスワード>
RUN groupadd -g $GID $GROUPNAME && \
    useradd -m -s /bin/bash -u $UID -g $GID -G sudo $USERNAME && \
    echo $USERNAME:$PASSWORD | chpasswd && \
    echo "$USERNAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER $USERNAME
WORKDIR /home/$USERNAME/
```

#### Gitのタブ補完を有効化・プロンプトにブランチを表示
[shun 様 「Gitコマンドの補完とGit情報のプロンプト表示」](https://zenn.dev/okuma/articles/43488b1882515d)
[caad1229 様 「プロンプトをカスタマイズしてgitブランチを表示する」](https://qiita.com/caad1229/items/6d71d84933c8a87af0c4)
Gitのコマンドを使う際、いちいち `--force-with-lease`などを打つのは手間なので、タブ補完を有効化しておきます。(aliasを設定しても良いですが)
また、いちいち`git status`を実行して現在のブランチを確認しなくてもよいように、ターミナルのプロンプトに現在のブランチを表示させます。

まずは、WSL上で`git-prompt-sample.txt`ファイルを作成しておきます。
```bash
$ pwd
~/dockerfiles

$ vi git-prompt-sample.txt
```
```git-prompt-sample.txt
function parse_git_branch {
    git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ [\1]/'
}
function promps {
    # 色は気分で変えたいかもしれないので変数宣言しておく
    local  BLUE="\[\e[1;34m\]"
    local  RED="\[\e[1;31m\]"
    local  GREEN="\[\e[1;32m\]"
    local  WHITE="\[\e[00m\]"
    local  GRAY="\[\e[1;37m\]"

    case $TERM in
        xterm*) TITLEBAR='\[\e]0;\W\007\]';;
        *)      TITLEBAR="";;
    esac
    local BASE="\u@\h"
    PS1="${TITLEBAR}${GREEN}${BASE}${WHITE}:${BLUE}\w${GREEN}\$(parse_git_branch)${BLUE}\$${WHITE} "
}
promps
source /usr/share/bash-completion/completions/git
```

`COPY git-prompt-sample.txt /home/$USERNAME/git-prompt-sample`のところで、WSL上の`~/dockerfiles/git-prompt-sample.txt`がコンテナ内の`~/git-prompt-sample`というファイルにコピーされます。
コンテナ内の`.bashrc`に`git-prompt-sample`の内容を追記することで、Gitコマンドのタブ補完とプロンプトへのブランチ表示ができます。
```Dockerfile
# Gitのタブ補完を有効化するためのスクリプトを取得
RUN wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -O ~/.git-completion.bash
RUN wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -O ~/.git-prompt.sh

# このDockerfileが存在するディレクトリにgit-prompt-sample.txtを作成し、.bashrcに記載したい内容を書いておく
COPY git-prompt-sample.txt /home/$USERNAME/git-prompt-sample
RUN cat git-prompt-sample >> .bashrc
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519885/ce4c4ac1-b6ec-deaa-5b55-d190553ca20c.png)

#### SSH鍵をコンテナにコピー
WSL上で、公開鍵・秘密鍵のファイルをDockerfileがあるディレクトリにコピーしておきます。
```bash
$ pwd
~/dockerfiles

# 既存のSSH鍵をコピ-
$ cp ~/.ssh/<秘密鍵のファイル名> <秘密鍵のファイル名>
$ cp ~/.ssh/<公開鍵のファイル名> <公開鍵のファイル名>
```
Dockerfileを実行する際、WSL上(`~/dockerfiles/`ディレクトリ配下)のSSH鍵のファイルが、コンテナ内の`~/.ssh`ディレクトリ配下にコピーされます。
```Dockerfile
# SSH鍵のコピー
COPY <秘密鍵のファイル名> /home/$USERNAME/.ssh/<秘密鍵のファイル名>
COPY <公開鍵のファイル名> /home/$USERNAME/.ssh/<公開鍵のファイル名>
```

### Docker image / Docker containerの作成
`~/dockerfiles/Dockerfile`が完成したら、下記を実行します。
コンテナ作成時の`-v`オプションについては、下記記事をご覧ください。
[mk3kohei 様 「【初心者】Dockerコンテナ内でDockerコマンドを使いたい！」](https://qiita.com/mk3kohei/items/e6998b684ccc39267aa4)
```bash
$ pwd
~/dockerfiles

# Docker imageを作成
$ docker image build -t <Docker imageの名前> .

# Docker containerを作成
$  docker run -it  -v /var/run/docker.sock:/var/run/docker.sock --name <Docker containerの名前> <Docker imageの名前>
```
上記を実行すると、ターミナルがコンテナ内で開かれている状態になります。
このまま、すぐにGitHubからリポジトリをcloneすることができます。
```bash
$ pwd
~

$ git clone <リポジトリのURL(SSH)>
Receiving objects: 100% (687/687), 686.19 KiB | 1.00 MiB/s, done.
Resolving deltas: 100% (335/335), done.
```



# まとめ
いかがだったでしょうか。
「便利ではあるけどSSHとか面倒だな...」と感じていたDockerですが、今回の方法でさらに簡単に環境が構築できるようになりました。

とはいえ、セキュリティ面などでの心配もあります... (SSH鍵ってそもそも使いまわしていいんだっけ? etc..)
また、Docker imageを作成する際、下記のようなwarningが発生します。
これも解決したいですね。
```bash
1 warning found (use docker --debug to expand):
 - SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "PASSWORD") (line 19)
```

参考記事もぜひご確認ください。
よりよい方法がありましたら、コメントなどでご教示いただけますと幸いです m(_ _)m