[Windows]Dockerにてライブラリが使用できるC++競技プログラミング環境構築

ネット上の方法を試してみてもC＋＋でデバックができ、ACライブラリも使用できるWindows上の環境をうまく作成できなかったので、今回はDockerDesktop上で環境含む競プロ環境の構築を行う。

# Dockerの導入

こちらを参考に。。
https://qiita.com/techpit-jp/items/f4a1319a909dd508f372

# VScode上でコンテナを立てる
今回以下のようなディレクトリ構造を想定します。
```
Atcoder
|─.devcontainer
 |─devcontainer.json
 |─docker-compose.yml
 |─Dockerfile
|─.library
||─ac-library //配布されているACLを解凍したもの
|─CPLUS
||─.vscode
|||─c_cpp_properties.json
|||─lauch.json
|||─setting.json
|||─task.json
||─ABC_100
||─ABC_200
```

libディレクトリとCPLUSディレクトリ以下をボリュームマウントし、これらのディレクトリの内容はWindowsとDocker上のUbuntuの間で同期することができます。VScodeにRemoteの拡張機能をいれることでDocker上のUbuntu にあるファイルを編集します。

## .devcontainerの中身
``` Dockerfile:Dockerfile
# Ubuntuの公式コンテナを軸に環境構築
FROM ubuntu:20.04

# インタラクティブモードにならないようにする
ARG DEBIAN_FRONTEND=noninteractive
# タイムゾーンを日本に設定
ENV TZ=Asia/Tokyo

# インフラを整備
RUN apt-get update && \
    apt-get install -y zsh time tzdata tree git curl

# デフォルトシェルをZ shellにする
RUN chsh -s /bin/zsh

# C++, Python3, PyPy3の3つの環境想定
RUN apt-get update && \
    apt-get install -y gcc-9 g++-9 python3.9 python3-pip pypy3 nodejs npm gdb

# 一般的なコマンドで使えるように設定
# e.g. python3.8 main.py => python main.py
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 30 && \
    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 30 && \
    update-alternatives --install /usr/bin/python python /usr/bin/python3.8 30 && \
    update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 30 && \
    update-alternatives --install /usr/bin/pypy pypy /usr/bin/pypy3 30 && \
    update-alternatives --install /usr/bin/node node /usr/bin/nodejs 30

# AtCoderでも使えるPythonライブラリをインストール
RUN pip install numpy==1.18.2 && \
    pip install scipy==1.4.1 && \
    pip install scikit-learn==0.22.2.post1 && \
    pip install numba==0.48.0 && \
    pip install networkx==2.4

# C++でAtCoder Library(ACL)を使えるようにする
RUN git clone https://github.com/atcoder/ac-library.git /lib/ac-library
ENV CPLUS_INCLUDE_PATH /lib/ac-library

# Pythonでの競技プログラミング用データ構造をインストール
RUN pip install git+https://github.com/hinamimi/ac-library-python && \
    pip install git+https://github.com/hinamimi/python-sortedcontainers

# コンテスト補助アプリケーションをインストール
RUN pip install online-judge-tools==11.3.0
RUN npm install -g atcoder-cli@2.1.1

# atcoder-cliの設定
RUN acc config-dir && \
    acc config default-template python && \
    acc config default-test-dirname-format test

# # AHC用のRustのinstall
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH $PATH:/home/root/.cargo/bin

WORKDIR /root/problems
WORKDIR /root/library

```


``` yml:docker-compose.yml
version: '3'
services:
  dev:
    build:
      context: .
      dockerfile: Dockerfile

    # イメージ名を指定
    image: hinamimi/atcoder:dev

    # localとcontainer間のファイルを同期させる
    # ${local}:${container}
    volumes:
      - ../problems:/root/problems:cached
      - ../library:/root/library:cached
      - ../acc-template-python:/root/.config/atcoder-cli-nodejs/python:cached
      - ../.vscode:/root/.vscode:cached

    # オプション これらのconfigファイルが必要なければコメントアウト
      - ../dotfiles/.zshrc:/root/.zshrc
      - ../dotfiles/.zinit:/root/.zinit
      - ../dotfiles/.zsh_history:/root/.zsh_history
      - ../dotfiles/.aliases:/root/.aliases

    # Overrides default command so things don't shut down after the process ends.
    command: /bin/sh -c "while sleep 1000; do :; done"
```

``` js:devcontainer.js
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.154.0/containers/docker-existing-docker-compose
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
	"name": "AtCoder Environment",

	// Update the 'dockerComposeFile' list if you have more compose files or use different names.
	// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
	"dockerComposeFile": [
		"docker-compose.yml"
	],

	// The 'service' property is the name of the service for the container that VS Code should
	// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
	"service": "dev",

	// The optional 'workspaceFolder' property is the path VS Code should open by default when
	// connected. This is typically a file mount in .devcontainer/docker-compose.yml
	"workspaceFolder": "/root",

	// Add the IDs of extensions you want installed when the container is created.
	"extensions": [
		"sanaajani.taskrunnercode", // Run tasks from Explorer pane
		"ms-python.python", // Python IntelliSense (Microsoft)
		"ms-python.vscode-pylance", // Python language server (Microsoft)
		"ms-vscode.cpptools", // C/C++ IntelliSense (Microsoft)
		"visualstudioexptteam.vscodeintellicode", // AI-assisted development (Microsoft)
		"yzhang.markdown-all-in-one", // Markdown
		"zainchen.json" // Json
	],

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Uncomment the next line if you want start specific services in your Docker Compose config.
	// "runServices": [],

	// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
	// "shutdownAction": "none",

	// Run commands after the container is created.
	"postCreateCommand": "pip3 install -U online-judge-tools"

	// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
	// "remoteUser": "vscode"
}

```

### 参考
https://qiita.com/hinamimi/items/b3dd159f956628cebdbb

## .vscodeの中身
``` js:c_cpp_properfies.json
{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "/lib/ac-library/atcoder",
                "/root/library",
                "${workspaceFolder}/**"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "compilerPath": "/bin/gcc"
        }
    ],
    "version": 4
}
```

``` json:launch.json
{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "build and debug active file",
      "type": "cppdbg",
      "request": "launch",
      //
      "program": "${workspaceFolder}/problem",
      "args": [],
      "stopAtEntry": false,
      //
      "cwd": "${workspaceFolder}",
      "environment": [],
      //
      "externalConsole": false,
      "MIMode": "gdb",
      "miDebuggerPath": "/usr/bin/gdb",
      "setupCommands": [
        {
          "description": "gdb の再フォーマットを有効にする",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "g++-9 build active file"
    }
  ]
}
```

``` js:settings.json
{
  "files.associations": {
    "Untitled-*": "cpp",
    "*.dat": "diff",
    "*.txt": "diff",
    "ostream": "cpp",
    "iostream": "cpp",
    "array": "cpp",
    "bitset": "cpp",
    "string_view": "cpp",
    "initializer_list": "cpp",
    "regex": "cpp",
    "utility": "cpp",
    "valarray": "cpp"
  },
  "C_Cpp.errorSquiggles": "Disabled",
}
```

``` js:tasks.json
{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "g++ build active file",
      "command": "/bin/g++",
      "args": [
        "-g",
        "${file}",
        "-I /lib/ac-library",
        "-I /root/library/ac-library",
        "-o",
        "${workspaceFolder}/problem"
      ],
      "options": {
        "cwd": "/bin"
      },
      "problemMatcher": [
        "$gcc"
      ],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "type": "shell",
      "label": "g++-9 build active file",
      "command": "/usr/bin/g++-9",
      "args": [
        "-g",
        "${file}",
        "-I /lib/ac-library",
        "-I /root/library/ac-library",
        "-o",
        "${workspaceFolder}/problem"
      ],
      "options": {
        "cwd": "/usr/bin"
      }
    }
  ]
}
```



## コマンド
Vscodeのターミナル上で以下のようなコマンドにより、Dockeのイメージ作成→コンテナ作成→コンテナを起動。コマンドを打つときのカレントディレクトリに注意
``` cpp :コマンド
...\Atcoder> docker build -f .devcontainer/Dockerfile -t atcoder:cpp .
//atcoder:ccpという名前のイメージを作成、最後の.を忘れず！！

...\Atcoder> docker create -it -v ${pwd}/.library:/root/library -v ${pwd}/CPLUS:/root/problems --name="atcoder_cpp" atcoder:cpp /bin/bash
//atcoder_cppという名前のコンテナを作成

...\Atcoer> docker start atcoder_cpp
```

## 起動しなくなったら
DockerDesktopをタスクマネージャーから落として再起動してみると大体治ります

<h2>参考</h2>
Dockerfileの書き方
https://blog.codecamp.jp/docker-file-how-to

Dockerコマンド
https://qiita.com/zono_0/items/7a25d283cd4b09d6ffb0


WSL2 + VSCode + Docker 開発環境
https://qiita.com/EBIHARA_kenji/items/12c7a452429d79006450

DockerでC++開発環境構築（ubuntu版）
https://qiita.com/yuzutarogo/items/8898377739b5c674743f