(自分用)docker+code-server、cloud9でC#環境作ってみる

## はじめに
[この記事](https://qiita.com/mototoke/items/a1377ea860c76923f7f8)の続きみたいな感じです。
dockerでcode-serverを構築して、そこでC#環境作れるか試してみます。

## code-server_1
以下のようなディレクトリを作ります。

```bash:
ls
> Dockerfile  code-server  docker-compose.yml  projects
```

Dockerfileとdocker-compose.ymlはこんな感じです。
公式のdocker-imageを使ってそこに.net coreをinstallしています。

<details><summary>Dockerfile</summary><div>

```dockerfile:Dockerfile
FROM codercom/code-server:3.8.0

USER root

# Install wget and other module
RUN apt-get update && apt-get install -y \
	wget

# Install code-server plugin
# ※commandからのextension installは効かない?
RUN code-server --install-extension ms-dotnettools.csharp

# Install .NET5
ENV DOTNET_ROOT=/usr/share/dotnet
ENV PATH=/usr/share/dotnet:/root/.dotnet/tools:$PATH
# 以下の環境変数を変える必要あり
# 詳細1： https://github.com/dotnet/core/issues/2186
# 詳細2： https://github.com/dotnet/core/blob/master/Documentation/build-and-install-rhel6-prerequisites.md
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

RUN wget -O dotnet.tar.gz https://download.visualstudio.microsoft.com/download/pr/a0487784-534a-4912-a4dd-017382083865/be16057043a8f7b6f08c902dc48dd677/dotnet-sdk-5.0.101-linux-x64.tar.gz \
    && wget -O dotnet_runtime.tar.gz https://download.visualstudio.microsoft.com/download/pr/6bea1cea-89e8-4bf7-9fc1-f77380443db1/0fb741b7d587cce798ebee80732196ef/aspnetcore-runtime-5.0.1-linux-x64.tar.gz \
    && dotnet_sha512='398d88099d765b8f5b920a3a2607c2d2d8a946786c1a3e51e73af1e663f0ee770b2b624a630b1bec1ceed43628ea8bc97963ba6c870d42bec064bde1cd1c9edb' \
    && echo "$dotnet_sha512  dotnet.tar.gz" | sha512sum -c - \
    && dotnet_runtime_sha512='fec655aed2e73288e84d940fd356b596e266a3e74c37d9006674c4f923fb7cde5eafe30b7dcb43251528166c02724df5856e7174f1a46fc33036b0f8db92688a' \
    && echo "$dotnet_runtime_sha512  dotnet_runtime.tar.gz" | sha512sum -c - \
    && mkdir -p "/usr/share/dotnet" \
    && mkdir -p "/usr/bin/dotnet" \
    && mkdir -p "/root/.dotnet/tools" \
    && tar zxf dotnet.tar.gz -C "/usr/share/dotnet" \
    && rm dotnet.tar.gz \
    && tar zxf dotnet_runtime.tar.gz -C "/usr/share/dotnet" \
    && rm dotnet_runtime.tar.gz \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \
    && dotnet help

USER coder
```
</div></details>


<details><summary>docker-compose.yml</summary><div>

```yaml:docker-compose.yml
version: "3"
services:
  code:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    environment:
      PUID: 1000
      PGID: 1000
      PASSWORD: password
    ports:
      - 20000:8080
    volumes:
      - ./projects:/home/coder/project
      - ./code-server:/home/coder/.local/share/code-server
```

</div></details>

起動します。

```
docker-compose up -d --build
```

URLにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/e12fd197-e369-49d3-5808-7b87202f8254.png)

DockerfileのこのコマンドでC#の拡張機能を入れたつもりなのですが
どうも入っていないみたい？です。
ターミナルから同じようにコマンドを叩いてもUIの方には反映されませんでした。

```
RUN code-server --install-extensions ms-dotnettools.csharp
```

仕方ないので拡張機能は手動で入れます。
主だった3つを入れてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/7398c950-a978-ba89-33d8-66fbd66cd819.png)

適当なプロジェクトを作ってみます。

```C#:
dotnet new console -o tutorial
ls
> Program.cs  tutorial.csproj
```

tutorialフォルダ以下にファイルを追加します。
C# extensionsが使えそうな雰囲気があるのですがファイルの生成はしてくれませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/61ce15b9-4e40-05da-25d0-35ad3cc33ae2.png)

仕方ないので通常のファイル作成で名前を`Calc.cs`とします。
Program.csとCalc.csを以下の内容にします。

<details><summary>Calc.cs</summary><div>

```csharp:Calc.cs
using System;

namespace tutorial2
{
    class Calc
    {
        public static double Add(double a, double b)
        {
            return a + b;
        }
    }
}

```
</div></details>

<details><summary>Program.cs</summary><div>

```csharp:Program.cs
using System;
using tutorial2;

namespace tutorial
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var ret = Calc.Add(1, 3);
            Console.WriteLine($"Cal Result is {ret}");
        }
    }
}
```
</div></details>

ターミナルから実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/04d4d5c0-fde9-f691-06c8-be753e754451.png)
実行できました。

デバッグはどうでしょうか？
launch.jsonに.Net Core Launchを指定し、ブレークポイントを置いて実行してみます。

???以下のようなエラーがDEBUG CONSOLEに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/14ad1bea-bc87-395e-9fd3-ae9f99b7cdf5.png)

[このURL](https://github.com/OmniSharp/omnisharp-vscode/wiki/Microsoft-.NET-Core-Debugger-licensing-and-Microsoft-Visual-Studio-Code)を見てみると、デバッガーはMicrosoftのIDEでないと動作しないライセンスになっているみたいです。
code-serverでの[issue](https://github.com/cdr/code-server/issues/473)にも挙がっていて[独自デバッガー？](https://github.com/Samsung/netcoredbg)でやる方法しかないみたいです。。。
issueもライセンスの問題により標準デバッガーは使えないという事で閉じられていました。

## code-server_2

`linuxserver/code-server`にDotNetCoreを入れて有志の方が作った
[image](https://github.com/ptr727/VSCode-Server-DotNetCore)があったのでそっちも乗っけておきます。

```
git clone https://github.com/ptr727/VSCode-Server-DotNetCore.git
cd VSCode-Server-DotnetCore
docker-compose up -d # 起動
```

## cloud9
おまけでcloud9でも試してみます。

Dockerfileとdocker-compose.ymlはこんな感じです。
`linuxserver/cloud9`にDotNetCoreを入れる形にしてみました。

<details><summary>Dockerfile</summary><div>

```dockerfile:Dockerfile
FROM linuxserver/cloud9:version-1.27.4

RUN mkdir -p /code/projects

# Install wget
RUN apt-get update \
    # Install wget
    && apt-get install -y wget

# Install .NET5
ENV DOTNET_ROOT=/usr/share/dotnet
ENV PATH=/usr/share/dotnet:/root/.dotnet/tools:$PATH
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

RUN wget -O dotnet.tar.gz https://download.visualstudio.microsoft.com/download/pr/a0487784-534a-4912-a4dd-017382083865/be16057043a8f7b6f08c902dc48dd677/dotnet-sdk-5.0.101-linux-x64.tar.gz \
    && wget -O dotnet_runtime.tar.gz https://download.visualstudio.microsoft.com/download/pr/6bea1cea-89e8-4bf7-9fc1-f77380443db1/0fb741b7d587cce798ebee80732196ef/aspnetcore-runtime-5.0.1-linux-x64.tar.gz \
    && dotnet_sha512='398d88099d765b8f5b920a3a2607c2d2d8a946786c1a3e51e73af1e663f0ee770b2b624a630b1bec1ceed43628ea8bc97963ba6c870d42bec064bde1cd1c9edb' \
    && echo "$dotnet_sha512  dotnet.tar.gz" | sha512sum -c - \
    && dotnet_runtime_sha512='fec655aed2e73288e84d940fd356b596e266a3e74c37d9006674c4f923fb7cde5eafe30b7dcb43251528166c02724df5856e7174f1a46fc33036b0f8db92688a' \
    && echo "$dotnet_runtime_sha512  dotnet_runtime.tar.gz" | sha512sum -c - \
    && mkdir -p "/usr/share/dotnet" \
    && mkdir -p "/usr/bin/dotnet" \
    && mkdir -p "/root/.dotnet/tools" \
    && tar zxf dotnet.tar.gz -C "/usr/share/dotnet" \
    && rm dotnet.tar.gz \
    && tar zxf dotnet_runtime.tar.gz -C "/usr/share/dotnet" \
    && rm dotnet_runtime.tar.gz \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \
    && dotnet help
```

</div></details>


<details><summary>docker-compose.yml</summary><div>

```yaml:docker-compose.yml
version: "3"
services:
  code:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Tokyo
      - GITURL=https://github.com/linuxserver/docker-cloud9.git #optional
      - USERNAME=user #optional
      - PASSWORD=password #optional
    ports:
      - 50000:8000
    volumes:
      - ./projects:/code/projects
      - ./docker.sock:/var/run/docker.sock #optional

```
</div></details>

URLにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/dba7fc51-221c-07fe-f734-3fc5beb57762.png)

code-server同様に適当なプロジェクトをターミナルから作って試します。
割愛しますが、code-server同様`dotnet run`までちゃんとできました。
cloud9はインテリセンスやヒストリーがちゃんと効くのでいいですね。

デバッグはどうでしょうか？
ブレークポイントは置けますがRunnerをどう作るのかわからず断念しました。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/59c6b84c-980a-21b4-7a33-b2f445e670e2.png)
AWS Cloud9の方だとできるみたいですがこっちだとどうなのでしょうね？

## 結論
web-ide自体は有用で便利だと思いますが
構築後にも周辺知識が必要だったり、拡張機能がうまく効かない等で本格的な開発はまだ難しそうという印象を受けました。
もっとレベルの高い人だと出来るのでしょうが私ではちょっと。。。
現状は大人しくwindows+visual studioでC#の開発を行うのがやはり無難でしょうか。
ただ、docker+code-server or cloud9でpythonとかの記事はちらほらあるのでそっちだと問題なく使えるのでしょうか。
気が向いたらpython+αで試してみたいと思いました。