Docker + atcoder-cli 環境構築

# 目的
- 以下の内容の Docker イメージを作成する
    - C++ コンパイラのインストール
    - atcoder-cli + online-judge-tools のインストール
    - GitHub から Atcoder 作業用リポジトリのクローン


# 環境
- OS: Ubuntu 20.04 (WSL2)
- Docker version 20.10.6


# 成果物
https://github.com/ktsn-ht/docker-atcoder-cli


# Docker イメージ詳細

## 事前準備
- GitHub に Atcoder 作業用リポジトリを準備する
- ssh キーを作成し、秘密鍵を ssh ディレクトリに保存、公開鍵を GitHub にアップロードする
- Atcoder 用テンプレートファイルを修正する

    ```cpp:main.cpp(デフォルト)
    #include<bits/stdc++.h>
    using namespace std;

    int main() {

      return 0;
    }
    ```

## Dockerfile
- イメージ元の指定

    ```dockerfile:Dockerfile
    FROM centos:centos8
    ```
    - 今回は centos8 から作成
- 環境変数の定義
    
    ```dockerfile:Dockerfile
    ARG username
    ARG reponame
    ```
    - github のユーザー名・リポジトリ名を変数として定義
- 必要なパッケージのインストール

    ```dockerfile:Dockerfile
    RUN yum update -y && yum install -y git gcc-c++ python3 nodejs
    ```

    - ```git```  
GitHub 連携 
    - ```gcc-c++```  
C++ コンパイラ (gcc 8.4.1)
    - ```python3```  
pip3 のインストール
    - ```nodejs```  
npm のインストール
- atcoder-cli のインストール

    ```dockerfile:Dockerfile
    RUN npm update -g npm && npm install -g atcoder-cli
    ```
- online-judge-tools のインストール

    ```dockerfile:Dockerfile
    RUN pip3 install online-judge-tools
    ```
- atcoder-cli の設定

    ```dockerfile:Dockerfile
    RUN acc config oj-path /usr/local/bin/oj \
     && acc config default-test-dirname-format test \
     && acc config default-template cpp \
     && acc config default-task-choice all
    ```
    - ```acc config oj-path /usr/local/bin/oj```  
atcoder-cli と online-judge-tools の連携
    - ```acc config default-test-dirname-format test```  
サンプルテストファイルの保存先ディレクトリを online-judge-tools に合わせる
    - ```acc config default-template cpp```  
テンプレートファイルの保存先ディレクトリを指定
    - ```acc config default-task-choice all```  
コンテスト用ディレクトリを一度にすべて作成するように設定
- テンプレートファイルのコピー

    ```dockerfile:Dockerfile
    COPY cpp /root/.config/atcoder-cli-nodejs/cpp
    ```
    - ローカルに用意したテンプレートファイルを Docker イメージにコピーする
- ssh 設定

    ```dockerfile:Dockerfile
    COPY ssh /root/.ssh
    ```
    - ローカルに用意した ssh 設定を Docker イメージにコピーする
- Atcoder 作業用リポジトリのクローン

    ```dockerfile:Dockerfile
    WORKDIR /work
    RUN chmod 600 /root/.ssh/* \
     && git clone git@github.com:${username}/${reponame}.git
    ```
    - 作業ディレクトリ```/work```を作成
    - ```chmod 600 /root/.ssh/*```  
秘密鍵の権限を変更
    - ```git clone git@github.com:${username}/${reponame}.git```  
Atcoder 作業用リポジトリのクローン

- 以上をまとめる

    ```dockerfile:Dockerfile
    FROM centos:centos8
    ARG username
    ARG reponame

    RUN yum update -y && yum install -y \
        git \
        gcc-c++ \
        python3 \
        nodejs \
     && npm update -g npm && npm install -g atcoder-cli \
     && pip3 install online-judge-tools \
     && acc config oj-path /usr/local/bin/oj \
     && acc config default-test-dirname-format test \
     && acc config default-template cpp \
     && acc config default-task-choice all
    COPY cpp /root/.config/atcoder-cli-nodejs/cpp
    COPY ssh /root/.ssh

    WORKDIR /work
    RUN chmod 600 /root/.ssh/* \
     && git clone git@github.com:${username}/${reponame}.git
    ```

## docker-compose.yml
- バージョンの指定

    ```yml:docker-compose.yml
    version: "3"
    ```
    - 最新バージョン
- ビルド

    ```yml:docker-compose.yml
    build:
      context: .
      args:
        username: ktsn-ht
        reponame: atcoder
    ```
    - ```context: .```  
Dockerfile のあるディレクトリ
    - ```args: ~```  
Atcoder 作業用リポジトリのユーザー名・リポジトリ名を指定  
自分の場合: https://github.com/ktsn-ht/atcoder
- イメージ名の指定

    ```yml:docker-compose.yml
    image: atcoder-cli
    ```
- コンテナ名の指定

    ```yml:docker-compose.yml
    container_name: atcoder-cli
    ```
- コンテナを起動し続ける

    ```yml:docker-compose.yml
    tty: true
    ```

- 以上をまとめる

    ```yml:docker-compose.yml
    version: "3"
    services:
      app:
        build:
          context: .
          args:
            username: ktsn-ht
            reponame: atcoder
        image: atcoder-cli
        container_name: atcoder-cli
        tty: true
    ```

# コンテナの起動・作業・終了
- コンテナ起動

    ```console:
    $ docker-compose up -d --build  # イメージビルド・コンテナ起動
    $ docker-compose exec atcoder-cli /bin/bash  # コンテナに入る
    ```
- コンテナ内作業

    ```console
    # acc login  # atcoder-cli でログイン
    # oj login https://beta.atcoder.jp/  # online-judge-tools でログイン

    # acc new <contest id>  # コンテストディレクトリ作成
    # oj t  # 作成したプログラムのテスト
    # acc submit  # 提出
    # git push  # GitHub に push
    ```

- コンテナ終了

    ```console
    # exit  # コンテナから出る
    $ docker-compose down  # コンテナ終了・削除
    ```

# おわりに
Docker の勉強のために Atcoder 環境のイメージを作成してみました。間違いやもっと良いやり方などある場合はご指摘いただければ幸いです。

せっかくつくったので久しぶりにコンテストも参加しようかな。。

# 参考
- [atcoder-cli チュートリアル | わたしろぐ](http://tatamo.81.la/blog/2018/12/07/atcoder-cli-tutorial/)
- [Dockerfile リファレンス — Docker-docs-ja 20.10 ドキュメント](https://docs.docker.jp/engine/reference/builder.html)
- [Compose file version 3 reference](https://docs.docker.com/compose/compose-file/compose-file-v3/)
- [DockerでAtCoderができる環境を作る【Python・C++】 - Qiita](https://qiita.com/hinamimi/items/b3dd159f956628cebdbb)
- [AtCoder のディレクトリ作成・サンプルケースのテスト・提出を自動化する。atcoder-cli と online-judge-tools - Qiita](https://qiita.com/takeaship/items/d0718066922612648eaa)
- [atcoder初心者こそ環境構築しよう！(atcoder-cli,online-judge-toolsのインストール、使い方） - Qiita](https://qiita.com/Adaachill/items/3d4ddad56c5c2cc372cd)
- [Dockerで作るGitHub環境 - Qiita](https://qiita.com/Y-Kanoh/items/94b3ea3df97fcd1546ce)
- [docker-compose up したコンテナを起動させ続ける方法 - Qiita](https://qiita.com/sekitaka_1214/items/2af73d5dc56c6af8a167)