🖋

Ubuntu 20.04にdotnet開発環境を構築する。アプリを作りコンテナー化する。

2022/02/17に公開

はじめに

仮想環境のUbuntu 20.04環境にdotnet開発環境を構築する。
コンソールアプリを作成し、コンテナー化(docker)する。
本資料のコマンドラインやキャプチャーはmacベースだがWindowsでも動作確認済み。

↓の手順でセットアップした環境を使用する。

環境

  • .NET SDK: 6.0.200
  • Microsoft.NETCore.App 6.0.2
  • Microsoft.AspNetCore.App 6.0.2

.NET SDK

インストール

信頼されたキーの一覧にMicrosoftパッケージ署名キーを追加し、パッケージ リポジトリを追加する。[1]

ubuntu@docker-vm:~$ curl -O https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb
ubuntu@docker-vm:~$ sudo dpkg -i packages-microsoft-prod.deb
ubuntu@docker-vm:~$ rm packages-microsoft-prod.deb

.NET SDK 6.0インストールする。

ubuntu@docker-vm:~$ sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-6.0
dotnet --info
ubuntu@docker-vm:~$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.200
 Commit:    4c30de7899

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  20.04
 OS Platform: Linux
 RID:         ubuntu.20.04-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.200/

Host (useful for support):
  Version: 6.0.2
  Commit:  839cdfb0ec

.NET SDKs installed:
  6.0.200 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

ランタイムの追加

# AspNetCore 5.0系をランタイムをインストール
ubuntu@docker-vm:~$ sudo apt-get install -y aspnetcore-runtime-5.0
dotnet --info
$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.200
 Commit:    4c30de7899

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  20.04
 OS Platform: Linux
 RID:         ubuntu.20.04-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.200/

Host (useful for support):
  Version: 6.0.2
  Commit:  839cdfb0ec

.NET SDKs installed:
  6.0.200 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 5.0.14 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 5.0.14 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download
# NETCore 5.0系をランタイムのみをインストール
ubuntu@docker-vm:~$ sudo apt-get install -y dotnet-runtime-5.0
dotnet --info
$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.200
 Commit:    4c30de7899

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  20.04
 OS Platform: Linux
 RID:         ubuntu.20.04-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.200/

Host (useful for support):
  Version: 6.0.2
  Commit:  839cdfb0ec

.NET SDKs installed:
  6.0.200 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 5.0.14 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

アンインストール

# すべてをアンインストールする
ubuntu@docker-vm:~$ sudo apt-get remove dotnet-host

コンソールアプリ

プロジェクト作成

作業をフォルダーを作成し、コンソールプロジェクトを作成する。

ubuntu@docker-vm:~$ mkdir docker-working
ubuntu@docker-vm:~$ cd docker-working
ubuntu@docker-vm:~/docker-working$ dotnet new console -o App -n DotNet.Docker
The template "Console App" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on /home/ubuntu/docker-working/App/DotNet.Docker.csproj...
  Determining projects to restore...
  Restored /home/ubuntu/docker-working/App/DotNet.Docker.csproj (in 105 ms).
Restore succeeded.
フォルダー構成
docker-working
└── App
    ├── DotNet.Docker.csproj
    ├── Program.cs
    └── obj
        ├── DotNet.Docker.csproj.nuget.dgspec.json
        ├── DotNet.Docker.csproj.nuget.g.props
        ├── DotNet.Docker.csproj.nuget.g.targets
        ├── project.assets.json
        └── project.nuget.cache

プロジェクトを実行する。

ubuntu@docker-vm:~/docker-working$ cd App/
ubuntu@docker-vm:~/docker-working/App$ dotnet run
Hello, World!

カウンターアプリ作成

VS Codeで仮想環境内のプロジェクトを開いて編集する。

プロジェクトを開く


「エクスプローラー」→「フォルダーを開く」を選択する。
「/home/ubuntu/docker-working/」フォルダーへ移動して「OK」ボタンを押す。

C#プラグインインストール

プロジェクトから「Program.cs」を開いた時にプラグインが未インストールだと表示される。

VS CodeにC#プラグインインストールのサジェストが表示される。
インストールボタンを押す。

インストールが完了するまで待つ。

「YES」ボタンを押す。
「拡張機能: C#」タブを閉じる。

「F5」キーを押してプロジェクトを実行する。
「Hello, World!」が表示される。

コードを編集

Program.cs
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

↑から↓のように書き換える。

Program.cs
var counter = 0;
var max = args.Length != 0 ? Convert.ToInt32(args[0]) : -1;
while (max == -1 || counter < max)
{
    Console.WriteLine($"Counter: {++counter}");
    await Task.Delay(1000);
}

「F5」キーを押し実行する。
デバッグコンソールに「Counter: 1」から順番にカウントアップすることを確認する。
上部の「□」ボタンを押して停止する。

アプリを作成

VS Codeのターミナルを開く。[2]
publishコマンドでアプリを作成する。

ubuntu@docker-vm:~/docker-working$ cd App/
ubuntu@docker-vm:~/docker-working/App$ dotnet publish -c Release
Microsoft (R) Build Engine version 17.1.0+ae57d105c for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  DotNet.Docker -> /home/ubuntu/docker-working/App/bin/Release/net6.0/DotNet.Docker.dll
  DotNet.Docker -> /home/ubuntu/docker-working/App/bin/Release/net6.0/publish/
# ファイルの確認
ubuntu@docker-vm:~/docker-working/App$ ls bin/Release/net6.0/publish
DotNet.Docker            DotNet.Docker.dll  DotNet.Docker.runtimeconfig.json
DotNet.Docker.deps.json  DotNet.Docker.pdb

コンテナー化

この項目内はコマンドを読みやすくするために「ubuntu@docker-vm:~/docker-working/App$」を「$」と省略します。

イメージ

Dockerfile作成

Appの下にDockerfileを作成する。

フォルダー構成
docker-working
└── App
    ├── Dockerfile
    ├── DotNet.Docker.csproj
    ├── Program.cs
    ├── bin
    │   ├── Debug
    │   │   └── 〜以下略〜
    │   └── Release
    │       └── net6.0
    │           ├── 〜略〜
    │           └── publish
    │               ├── DotNet.Docker
    │               ├── DotNet.Docker.deps.json
    │               ├── DotNet.Docker.dll
    │               ├── DotNet.Docker.pdb
    │               └── DotNet.Docker.runtimeconfig.json
    └── obj
〜略〜

Dockerfileの内容は下記の通り。

Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:6.0

COPY bin/Release/net6.0/publish/ App/
WORKDIR /App
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
SDKを使用したい場合

「aspnet:6.0」→「sdk:6.0」へ変更する。

Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:6.0

COPY bin/Release/net6.0/publish/ App/
WORKDIR /App
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
.NET Coreランタイムのみ(ASP.NET Coreランタイムが不要な場合)

「aspnet:6.0」→「runtime:6.0」へ変更する。

Dockerfile
FROM mcr.microsoft.com/dotnet/runtime:6.0

COPY bin/Release/net6.0/publish/ App/
WORKDIR /App
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

作成

カウンターアプリのイメージを作成する。

$ docker build -t counter-image -f Dockerfile .
Sending build context to Docker daemon  1.023MB
Step 1/4 : FROM mcr.microsoft.com/dotnet/aspnet:6.0
6.0: Pulling from dotnet/aspnet
5eb5b503b376: Pull complete 
1d0c01fc21b0: Pull complete 
a0a88332a3eb: Pull complete 
312960dda1eb: Pull complete 
8ad6f1875aa9: Pull complete 
Digest: sha256:299dce0ad496ffd8ec987c420e5d66129422247b02ffa7c5779c7a9911770d0a
Status: Downloaded newer image for mcr.microsoft.com/dotnet/aspnet:6.0
 ---> 09231bfea5df
Step 2/4 : COPY bin/Release/net6.0/publish/ App/
 ---> 78f302cb2f87
Step 3/4 : WORKDIR /App
 ---> Running in 38d4b9e21aa6
Removing intermediate container 38d4b9e21aa6
 ---> c0ca06bc2a55
Step 4/4 : ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
 ---> Running in 63e26e64276d
Removing intermediate container 63e26e64276d
 ---> 206de2aeb877
Successfully built 206de2aeb877
Successfully tagged counter-image:latest

作成されたイメージを確認する。

$ docker images
REPOSITORY                        TAG       IMAGE ID       CREATED              SIZE
counter-image                     latest    206de2aeb877   About a minute ago   208MB
mcr.microsoft.com/dotnet/aspnet   6.0       09231bfea5df   8 days ago           208MB
〜略〜

削除

イメージの削除をする。

$ docker rmi counter-image:latest
Untagged: counter-image:latest
Deleted: sha256:206de2aeb877bb38687c988e10783a86251b5500e1a458ae06543727a5a6213a
Deleted: sha256:c0ca06bc2a551008718337ce37c94966b9a96d4c1d53b59f64a9c09c7b14066d
Deleted: sha256:78f302cb2f87415313967a98a2b3ed5b13ed3781480d70dd72842256c5effb72
Deleted: sha256:339fb4bf539580dc1f09b22d1a0b9defa90e54c44f307fdb6bd1acd55325f593
$ docker rmi mcr.microsoft.com/dotnet/aspnet:6.0
Untagged: mcr.microsoft.com/dotnet/aspnet:6.0
Untagged: mcr.microsoft.com/dotnet/aspnet@sha256:299dce0ad496ffd8ec987c420e5d66129422247b02ffa7c5779c7a9911770d0a
Deleted: sha256:09231bfea5df094c8fe14ad0cd4905fcc1ffee95fc91041c3bf6f607b24ff40a
Deleted: sha256:a805346469f528735c7bc396c9dbd1f33ecfeb219faaebf7eb07b21c0d64cc38
Deleted: sha256:cb571dae3d5aac905296acb190a64a6cad7b88e3a631d1aac46d199bb8a72fb7
Deleted: sha256:61300747b0169f1b3cc20952506c0ea1397eba89e48a8c28b4fa8d1bbe8f283a
Deleted: sha256:8276c9b27c9a87e163ccbe8b23bd78418e453d97f444196cbca290133373dc5a
Deleted: sha256:7d0ebbe3f5d26c1b5ec4d5dbb6fe3205d7061f9735080b0162d550530328abd6
$ docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
コンテナーが削除されていないとイメージは削除できない
$ docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS     NAMES
30b687176d1b   counter-image   "dotnet DotNet.Docke…"   54 seconds ago   Up 46 seconds             core-counter
# コンテナーが動いている状態ではイメージは削除できない
$ docker rmi counter-image:latest
Error response from daemon: conflict: unable to remove repository reference "counter-image:latest" (must force) - container 30b687176d1b is using its referenced image 831fce097bc5
# コンテナーを止める
$ docker stop core-counter
core-counter
# コンテナー登録されている状態ではイメージは削除できない
$ docker rmi counter-image:latest
Error response from daemon: conflict: unable to remove repository reference "counter-image:latest" (must force) - container 30b687176d1b is using its referenced image 831fce097bc5
# コンテナーを削除する
$ docker rm core-counter
core-counter
# イメージが削除できる
$ docker rmi counter-image:latest
Untagged: counter-image:latest
Deleted: sha256:831fce097bc51c70e8ed4208a646dd1b1d198e83ce76cac99aeab795cf96bb9c
Deleted: sha256:7d00db4662b0e8ad7b842c60f3f6d371eaf711af954f2a05ba233fa80ba1cac5
Deleted: sha256:b01f2788cbd39cee9c0be02e5710438c54af57f55ae6d6acad301370c69bf567
Deleted: sha256:919259a2766b656e6aba5ff2da7dc1b6f467738457d74117ce9eda55eee8329d

コンテナー操作

作成

counter-imageからcore-counterコンテナーを作成する。

$ docker create --name core-counter counter-image
84fc51f048981cf69f2e4d9ed1c0ceb3f2a6396fd819d251e2745aa2b8cc445b
$ docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS    PORTS     NAMES
84fc51f04898   counter-image   "dotnet DotNet.Docke…"   17 seconds ago   Created             core-counter

起動

core-counterを起動する。

$ docker start core-counter
core-counter
$ docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED         STATUS         PORTS     NAMES
84fc51f04898   counter-image   "dotnet DotNet.Docke…"   2 minutes ago   Up 3 seconds             core-counter

停止

core-counterを停止する。

$ docker stop core-counter
core-counter
$ docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED         STATUS                      PORTS     NAMES
84fc51f04898   counter-image   "dotnet DotNet.Docke…"   4 minutes ago   Exited (143) 1 second ago             core-counter

接続

実行状態のコンテナーに接続し、出力を確認する。

$ docker start core-counter
core-counter
$ docker attach --sig-proxy=false core-counter
Counter: 61
Counter: 62
Counter: 63
Counter: 64
# control + cで終了。
^C

削除

core-counterを削除する。

$ docker stop core-counter
core-counter
$ docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS                       PORTS     NAMES
84fc51f04898   counter-image   "dotnet DotNet.Docke…"   16 minutes ago   Exited (143) 4 seconds ago             core-counter
$ docker rm core-counter
core-counter
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

単一実行

1つのコマンドでコンテナー作成と実行する。
コンテナー停止後に、自動でコンテナーは削除される。

$ docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
# control + cで終了。
^C
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

パラメーターをつけて実行する。

$ docker run -it --rm counter-image 3
Counter: 1
Counter: 2
Counter: 3

コンテナーのシェルを使ってログインする。
entrypointを変更することでプログラムではなくシェルを実行する。

$ docker run -it --rm --entrypoint "bash" counter-image
root@7562009fdbf6:/App# ls
DotNet.Docker            DotNet.Docker.dll  DotNet.Docker.runtimeconfig.json
DotNet.Docker.deps.json  DotNet.Docker.pdb
root@7562009fdbf6:/App# dotnet DotNet.Docker.d
DotNet.Docker.deps.json  DotNet.Docker.dll        
# 実行する
root@7562009fdbf6:/App# dotnet DotNet.Docker.dll 3
Counter: 1
Counter: 2
Counter: 3
root@7562009fdbf6:/App# exit
exit
$ 

Docker拡張

VS CodeのDocker拡張できる操作。

イメージ操作

単一実行(Run)やRegistriesの操作ができる。

RunするとCONTAINERSに実行状態が表示されるようになる。

コンテナー操作

ログ表示(View Logs)、シェルアクセス(Attach Shell)、コンテナー操作ができる。


ログ表示(View Logs)をするとターミナルにログが表示される。

シェルアクセス(Attach Shell)をするとターミナルでコンテナー内のシェルが使用できる。

参考にしたサイト

脚注
  1. wslで「curl: (6) Could not resolve host: packages.microsoft.com」が出る場合。一度WSLから抜けて「wsl --shutdown」を行い入り直すと直る。それでもダメな場合は「WSL2 で dns の名前解決ができなくなって ネット接続できなくなった場合の対処方法 - Qiita」という方法もあるようだ。 ↩︎

  2. メニューの「ターミナル」→「新しいターミナル」で開く ↩︎

Discussion