Číst v angličtině

Sdílet prostřednictvím


Kurz: Kontejnerizace aplikace .NET

Volba verze .NET

V tomto kurzu se naučíte kontejnerizovat aplikaci .NET pomocí Dockeru. Kontejnery mají mnoho funkcí a výhod, jako je neměnná infrastruktura, poskytuje přenosnou architekturu a umožňuje škálovatelnost. Image se dá použít k vytvoření kontejnerů pro místní vývojové prostředí, privátní cloud nebo veřejný cloud.

V tomto kurzu:

  • Vytvoření a publikování jednoduché aplikace .NET
  • Vytvoření a konfigurace souboru Dockerfile pro .NET
  • Vytvořit Docker image
  • Vytvoření a spuštění kontejneru Dockeru

Prozkoumáte sestavení kontejneru Dockeru a nasadíte úlohy pro aplikaci .NET. Platforma Dockeru používá modul Dockeru k rychlému sestavování a balení aplikací jako imagí Dockeru. Tyto image jsou napsané ve formátu Dockerfile, který se má nasadit a spustit ve vrstveném kontejneru.

Tip

Pokud vás zajímá, jak vytvořit aplikaci .NET jako kontejner bez nutnosti Dockeru nebo podmanu, viz Kontejnerizace aplikace .NET pomocí dotnet publish.

Poznámka

Tento kurz není pro aplikace ASP.NET Core. Pokud používáte ASP.NET Core, podívejte se na kurz "Naučte se kontejnerizovat aplikaci ASP.NET Core".

Požadavky

Nainstalujte následující požadavky:

  • .NET SDK 8+ balíček.
    Pokud máte nainstalovanou technologii .NET, pomocí příkazu dotnet --info určete, kterou sadu SDK používáte.
  • Docker Community Edition.
  • Dočasná pracovní složka pro ukázkovou aplikaci Dockerfile a .NET. V tomto kurzu se jako pracovní složka používá název docker-working.

Vytvoření aplikace .NET

Potřebujete aplikaci .NET, na které běží kontejner Dockeru. Otevřete terminál, vytvořte pracovní složku, pokud jste to ještě neudělali, a zadejte ji. Spuštěním následujícího příkazu v pracovní složce vytvořte nový projekt v podadresáři s názvem App:

dotnet new console -o App -n DotNet.Docker

Strom složek vypadá podobně jako následující adresářová struktura:

📁 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

Příkaz dotnet new vytvoří novou složku s názvem App a vygeneruje konzolovou aplikaci Hello World. Teď změníte adresáře a přejdete do složky App ze své relace terminálu. Ke spuštění aplikace použijte příkaz dotnet run. Aplikace se spustí a vytiskne Hello World! pod příkazem:

cd App
dotnet run
Hello World!

Výchozí šablona vytvoří aplikaci, která se vytiskne do terminálu a pak se okamžitě ukončí. Pro účely tohoto kurzu použijete aplikaci, která se bude opakovat po neomezenou dobu. Otevřete soubor Program.cs v textovém editoru.

Tip

Pokud používáte Visual Studio Code, zadejte z předchozí relace terminálu následující příkaz:

code .

Tento příkaz otevře složku App, která obsahuje projekt v editoru Visual Studio Code.

Program.cs by měl vypadat jako následující kód jazyka C#:

Console.WriteLine("Hello World!");

Nahraďte soubor následujícím kódem, který počítá čísla každou sekundu:

var counter = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;

while (max is -1 || counter < max)
{
    Console.WriteLine($"Counter: {++counter}");

    await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}
var counter = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;

while (max is -1 || counter < max)
{
    Console.WriteLine($"Counter: {++counter}");

    await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}

Uložte soubor a znovu otestujte program pomocí dotnet run. Mějte na paměti, že tato aplikace běží neomezeně dlouho. Pomocí příkazu zrušit Ctrl+C ho zastavte. Představte si následující příklad výstupu:

dotnet run
Counter: 1
Counter: 2
Counter: 3
Counter: 4
^C

Pokud do aplikace předáte číslo na příkazovém řádku, omezí se počet na danou částku a pak se ukončí. Zkuste to s dotnet run -- 5 počítat do pěti.

Důležité

Všechny parametry po -- se nepředají do příkazu dotnet run a místo toho se předají do vaší aplikace.

Publikování aplikace .NET

Aby byla aplikace vhodná pro vytvoření image, musí se zkompilovat. Příkaz dotnet publish je nejvýstižnější, protože sestavuje a publikuje aplikaci. Podrobné informace najdete v dokumentaci k příkazu dotnet build a dotnet publish.

dotnet publish -c Release

Tip

Pokud vás zajímá publikování aplikace .NET jako kontejneru, aniž byste potřebovali Docker, podívejte se na Kontejnerizace aplikace .NET s dotnet publish.

Příkaz dotnet publish zkompiluje vaši aplikaci do složky publikace. Cesta z pracovní složky ke složce publish by měla být ./App/bin/Release/<TFM>/publish/:

Pomocí příkazu ls získejte výpis adresáře a ověřte, že byl vytvořen DotNet.Docker.dll soubor.

me@DESKTOP:/docker-working/app$ ls bin/Release/net9.0/publish
DotNet.Docker.deps.json  DotNet.Docker.dll  DotNet.Docker.exe  DotNet.Docker.pdb  DotNet.Docker.runtimeconfig.json
me@DESKTOP:/docker-working/app$ ls bin/Release/net8.0/publish
DotNet.Docker.deps.json  DotNet.Docker.dll  DotNet.Docker.exe  DotNet.Docker.pdb  DotNet.Docker.runtimeconfig.json

Vytvoření souboru Dockerfile

Soubor Dockerfile používá příkaz docker build k vytvoření image kontejneru. Tento soubor je textový soubor s názvem Dockerfile, který nemá příponu.

Vytvořte soubor s názvem Dockerfile v adresáři obsahujícím .csproj a otevřete ho v textovém editoru. Tento návod používá image ASP.NET Core runtime (která obsahuje image .NET runtime) a je přizpůsoben pro .NET konzolovou aplikaci.

FROM mcr.microsoft.com/dotnet/sdk:9.0@sha256:3fcf6f1e809c0553f9feb222369f58749af314af6f063f389cbd2f913b4ad556 AS build
WORKDIR /App

# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:9.0@sha256:b4bea3a52a0a77317fa93c5bbdb076623f81e3e2f201078d89914da71318b5d8
WORKDIR /App
COPY --from=build /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

Poznámka

Image modulu runtime ASP.NET Core se zde používá záměrně, i když se místo toho dá použít image mcr.microsoft.com/dotnet/runtime:9.0.

FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:35792ea4ad1db051981f62b313f1be3b46b1f45cadbaa3c288cd0d3056eefb83 AS build
WORKDIR /App

# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0@sha256:6c4df091e4e531bb93bdbfe7e7f0998e7ced344f54426b7e874116a3dc3233ff
WORKDIR /App
COPY --from=build /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

Poznámka

Image modulu runtime ASP.NET Core se zde používá záměrně, i když se místo toho dá použít image mcr.microsoft.com/dotnet/runtime:8.0.

Důležité

Osvědčeným postupem je zahrnutí zabezpečeného hashovacího algoritmu (SHA) za značku image do souboru Dockerfile. Tím se zajistí, že image nebude manipulována a že image bude stejná jako ta, kterou očekáváte. Sha je jedinečný identifikátor obrázku. Další informace najdete v tématu Docs Dockeru: Stažení image hodnotou digest.

Tip

Dockerfile používá vícefázové sestavení, které optimalizuje konečnou velikost obrazu vrstvením a odstraněním nepotřebných částí sestavení. Další informace najdete v Docker Docs: vícefázové procesy.

Klíčové slovo FROM vyžaduje plně kvalifikovaný název image kontejneru Dockeru. Microsoft Container Registry (MCR, mcr.microsoft.com) je syndikát Docker Hubu, který hostuje veřejně přístupné kontejnery. Segment dotnet je úložiště kontejneru, zatímco sdk nebo aspnet segment je název image kontejneru. Obrázek je označený 9.0, který se používá k verzování. Proto mcr.microsoft.com/dotnet/aspnet:9.0 je modul runtime .NET 9.0. Ujistěte se, že načtete verzi modulu runtime, která odpovídá modulu runtime, na který cílí vaše sada SDK. Například aplikace vytvořená v předchozí části používala sadu .NET 9.0 SDK a základní image uvedená v souboru Dockerfile je označena 9.0.

Důležité

Při použití imagí kontejnerů založených na Systému Windows je třeba zadat značku image nad rámec jednoduše 9.0, například mcr.microsoft.com/dotnet/aspnet:9.0-nanoserver-1809 místo mcr.microsoft.com/dotnet/aspnet:9.0. Vyberte název image podle toho, jestli používáte Nano Server nebo Jádro Windows Serveru a jakou verzi tohoto operačního systému používáte. Úplný seznam všech podporovaných značek najdete na stránce Docker Hubu .NET .

Uložte soubor Dockerfile. Adresářová struktura pracovní složky by měla vypadat takto. Některé soubory a složky na hlubší úrovni jsou vynechány, aby se ušetřilo místo v článku:

📁 docker-working
    └──📂 App
        ├── Dockerfile
        ├── DotNet.Docker.csproj
        ├── Program.cs
        ├──📂 bin
        │   └───📂 Release
        │        └───📂 net9.0
        │             ├───📂 publish
        │             │    ├─── DotNet.Docker.deps.json
        │             │    ├─── DotNet.Docker.dll
        │             │    ├─── DotNet.Docker.exe
        │             │    ├─── DotNet.Docker.pdb
        │             │    └─── DotNet.Docker.runtimeconfig.json
        │             ├─── DotNet.Docker.deps.json
        │             ├─── DotNet.Docker.dll
        │             ├─── DotNet.Docker.exe
        │             ├─── DotNet.Docker.pdb
        │             └─── DotNet.Docker.runtimeconfig.json
        └──📁 obj
            └──...

Klíčové slovo FROM vyžaduje plně kvalifikovaný název image kontejneru Dockeru. Microsoft Container Registry (MCR, mcr.microsoft.com) je syndikát Docker Hubu, který hostuje veřejně přístupné kontejnery. Segment dotnet je úložiště kontejneru, zatímco sdk nebo aspnet segment je název image kontejneru. Obrázek je označený 8.0, které se používá pro verzování. Proto mcr.microsoft.com/dotnet/aspnet:8.0 je modul runtime .NET 8.0. Ujistěte se, že načtete verzi modulu runtime, která odpovídá modulu runtime, na který cílí vaše sada SDK. Například aplikace vytvořená v předchozí části používala sadu .NET 8.0 SDK a základní image uvedená v souboru Dockerfile je označena 8.0.

Důležité

Při použití imagí kontejnerů založených na Systému Windows je třeba zadat značku image nad rámec jednoduše 8.0, například mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-1809 místo mcr.microsoft.com/dotnet/aspnet:8.0. Vyberte název image podle toho, jestli používáte Nano Server nebo Jádro Windows Serveru a jakou verzi tohoto operačního systému používáte. Úplný seznam všech podporovaných značek najdete na stránce Docker Hubu .NET .

Uložte soubor Dockerfile. Adresářová struktura pracovní složky by měla vypadat takto. Některé soubory a složky na hlubší úrovni jsou vynechány, aby se ušetřilo místo v článku:

📁 docker-working
    └──📂 App
        ├── Dockerfile
        ├── DotNet.Docker.csproj
        ├── Program.cs
        ├──📂 bin
        │   └──📂 Release
        │       └──📂 net8.0
        │           └──📂 publish
        │               ├── DotNet.Docker.deps.json
        │               ├── DotNet.Docker.exe
        │               ├── DotNet.Docker.dll
        │               ├── DotNet.Docker.pdb
        │               └── DotNet.Docker.runtimeconfig.json
        └──📁 obj
            └──...

Instrukce ENTRYPOINT nastaví dotnet jako hostitele DotNet.Docker.dll. Místo toho je ale možné definovat ENTRYPOINT jako samotný spustitelný soubor aplikace, který se spoléhá na operační systém jako hostitele aplikace:

ENTRYPOINT ["./DotNet.Docker"]

To způsobí, že se aplikace spustí přímo bez dotneta místo toho spoléhá na hostitele aplikace a základní operační systém. Další informace o nasazení binárních souborů pro různé platformy najdete v tématu Vytvoření binárního souboru pro různé platformy.

Kontejner sestavíte spuštěním následujícího příkazu z terminálu:

docker build -t counter-image -f Dockerfile .

Docker zpracovává každý řádek v souboru Dockerfile. . v příkazu docker build nastaví kontext sestavení image. Přepínač -f je cesta k Dockerfile souboru . Tento příkaz sestaví obraz a vytvoří místní úložiště s názvem obraz čítače, které odkazuje na tento obraz. Po dokončení tohoto příkazu spusťte docker images a zobrazte seznam nainstalovaných imagí:

REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
counter-image    latest    1c1f1433e51d   32 seconds ago   223MB
docker images
REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
counter-image    latest    2f15637dc1f6   10 minutes ago   217MB

Úložiště counter-image je název obrazu. Značka obrázku, identifikátor obrázku, velikost a jeho vytvoření jsou navíc součástí výstupu. Posledními kroky souboru Dockerfile jsou vytvoření kontejneru z image, běh aplikace, zkopírování publikované aplikace do kontejneru a definování vstupního bodu.

FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /App
COPY --from=build /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
COPY --from=build /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

Příkaz FROM určuje základní image a značku, které se mají použít. Příkaz WORKDIR změní aktuální adresář uvnitř kontejneru na App.

Příkaz COPY říká Dockeru, aby zkopíroval zadaný zdrojový adresář do cílové složky. V tomto příkladu publikovat obsah ve vrstvě build jsou výstupem do složky s názvem App/out, takže se jedná o zdroj, ze které se má kopírovat. Veškerý publikovaný obsah v adresáři App/out se zkopíruje do aktuálního pracovního adresáře (App).

Další příkaz, ENTRYPOINT, řekne Dockeru, aby nakonfigurovali kontejner tak, aby běžel jako spustitelný soubor. Po spuštění kontejneru se spustí příkaz ENTRYPOINT. Jakmile tento příkaz skončí, kontejner se automaticky zastaví.

Tip

Před .NET 8 mohou kontejnery nakonfigurované tak, aby běžely jako jen pro čtení, selhat s Failed to create CoreCLR, HRESULT: 0x8007000E. Pokud chcete tento problém vyřešit, zadejte DOTNET_EnableDiagnostics proměnnou prostředí jako 0 (těsně před krokem ENTRYPOINT):

ENV DOTNET_EnableDiagnostics=0

Další informace o různých proměnných prostředí .NET najdete v tématu proměnné prostředí .NET.

Poznámka

.NET 6 standardizuje předponu DOTNET_ místo COMPlus_ pro proměnné prostředí, které konfigurují chování za běhu .NET. Předpona COMPlus_ ale bude i nadále fungovat. Pokud používáte předchozí verzi modulu runtime .NET, měli byste stále používat předponu COMPlus_ pro proměnné prostředí.

Vytvoření kontejneru

Teď, když máte image, která obsahuje vaši aplikaci, můžete vytvořit kontejner. Kontejner můžete vytvořit dvěma způsoby. Nejprve vytvořte nový kontejner, který je zastavený.

docker create --name core-counter counter-image

Tento příkaz docker create vytvoří kontejner založený na image čítače obrazu. Výstup příkazu docker create ukazuje ID kontejneru kontejneru (váš identifikátor se bude lišit):

d0be06126f7db6dd1cee369d911262a353c9b7fb4829a0c11b4b2eb7b2d429cf

Pokud chcete zobrazit seznam všech kontejnerů, použijte příkaz docker ps -a:

docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS    PORTS     NAMES
d0be06126f7d   counter-image   "dotnet DotNet.Docke…"   12 seconds ago   Created             core-counter

Správa kontejneru

Kontejner byl vytvořen s konkrétním názvem core-counter. Tento název slouží ke správě kontejneru. Následující příklad používá příkaz docker start ke spuštění kontejneru a potom pomocí příkazu docker ps zobrazí pouze spuštěné kontejnery:

docker start core-counter
core-counter

docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS     NAMES
cf01364df453   counter-image   "dotnet DotNet.Docke…"   53 seconds ago   Up 10 seconds             core-counter

Podobně příkaz docker stop kontejner zastaví. Následující příklad pomocí příkazu docker stop zastaví kontejner a pak pomocí příkazu docker ps zobrazí, že nejsou spuštěné žádné kontejnery:

docker stop core-counter
core-counter

docker ps
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

Připojení ke kontejneru

Po spuštění kontejneru se k němu můžete připojit a zobrazit výstup. Pomocí příkazů docker start a docker attach spusťte kontejner a prohlédněte si výstupní datový proud. V tomto příkladu se k odpojení od spuštěného kontejneru používá Ctrl+C stisknutí klávesy. Toto stisknutí klávesy ukončí proces v kontejneru, pokud není uvedeno jinak, čímž by se kontejner zastavil. Parametr --sig-proxy=false zajišťuje, že Ctrl+C proces v kontejneru nezastaví.

Po odpojení od kontejneru se znovu připojte, abyste ověřili, že stále běží a počítá.

docker start core-counter
core-counter

docker attach --sig-proxy=false core-counter
Counter: 7
Counter: 8
Counter: 9
^C

docker attach --sig-proxy=false core-counter
Counter: 17
Counter: 18
Counter: 19
^C

Odstranění kontejneru

Pro tento článek nechcete, aby kontejnery zůstávaly, když nic nedělají. Odstraňte kontejner, který jste vytvořili dříve. Pokud kontejner běží, zastavte ho.

docker stop core-counter

V následujícím příkladu jsou uvedeny všechny kontejnery. Potom pomocí příkazu docker rm kontejner odstraní a pak znovu zkontroluje všechny spuštěné kontejnery.

docker ps -a
CONTAINER ID    IMAGE            COMMAND                   CREATED          STATUS                        PORTS    NAMES
2f6424a7ddce    counter-image    "dotnet DotNet.Dock…"    7 minutes ago    Exited (143) 20 seconds ago            core-counter

docker rm core-counter
core-counter

docker ps -a
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

Jedno spuštění

Docker poskytuje docker run příkaz k vytvoření a spuštění kontejneru jako jediný příkaz. Tento příkaz eliminuje potřebu spouštět docker create a pak docker start. Tento příkaz můžete také nastavit tak, aby se kontejner po zastavení kontejneru automaticky odstranil. Například pomocí docker run -it --rm můžete udělat dvě věci: nejprve automaticky použít aktuální terminál pro připojení ke kontejneru, a poté, co kontejner dokončí svou práci, ho odstranit.

docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
^C

Kontejner také předává parametry do spuštění aplikace .NET. Pokud chcete aplikaci .NET dát pokyn, aby se počítaly jenom do tří, předejte 3.

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

V docker run -itzastaví příkaz Ctrl+C proces spuštěný v kontejneru, který zase zastaví kontejner. Vzhledem k tomu, že byl zadaný parametr --rm, kontejner se po zastavení procesu automaticky odstraní. Ověřte, že neexistuje:

docker ps -a
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

Změna ENTRYPOINTu

Příkaz také umožňuje upravit příkaz ze souboru Dockerfile a spustit něco jiného, ale jenom pro tento kontejner. Například pomocí následujícího příkazu spusťte bash nebo cmd.exe. Podle potřeby upravte příkaz.

V tomto příkladu se ENTRYPOINT změní na bash. Příkaz exit se spustí, který proces ukončí a zastaví kontejner.

docker run -it --rm --entrypoint "bash" counter-image
root@9f8de8fbd4a8:/App# ls
DotNet.Docker  DotNet.Docker.deps.json  DotNet.Docker.dll  DotNet.Docker.pdb  DotNet.Docker.runtimeconfig.json
root@9f8de8fbd4a8:/App# dotnet DotNet.Docker.dll 7
Counter: 1
Counter: 2
Counter: 3
^C
root@9f8de8fbd4a8:/App# exit
exit

Poznámka

Tento příklad funguje jenom v kontejnerech Linuxu. Kontejnery Windows nemají bash.

Základní příkazy

Docker má mnoho různých příkazů, které vytvářejí, spravují a pracují s kontejnery a imagemi. Tyto příkazy Dockeru jsou nezbytné pro správu kontejnerů:

Vyčistěte prostředky

V tomto kurzu jste vytvořili kontejnery a image. Pokud chcete, odstraňte tyto prostředky. Pomocí následujících příkazů

  1. Seznam všech kontejnerů

    docker ps -a
    
  2. Zastavte kontejnery, které běží podle jejich názvu.

    docker stop core-counter
    
  3. Odstranění kontejneru

    docker rm core-counter
    

Dále odstraňte všechny image, které už na počítači nechcete. Odstraňte image vytvořený vaším souborem Dockerfile a pak odstraňte image .NET, na které byl založen soubor Dockerfile . Můžete použít ID image nebo REPOSITORY:TAG formátovaný řetězec.

docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:9.0
docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:8.0

Pomocí příkazu docker images zobrazte seznam nainstalovaných imagí.

Tip

Soubory obrázků můžou být velké. Obvykle byste při testování a vývoji aplikace odebrali dočasné kontejnery, které jste vytvořili. Pokud plánujete vytvářet další image založené na daném modulu runtime, obvykle zachováte základní image s nainstalovaným modulem runtime.

Další kroky