Zelfstudie: Een .NET-app containeriseren
In deze zelfstudie leert u hoe u een .NET-toepassing in een container kunt opnemen met Docker. Containers hebben veel functies en voordelen, zoals een onveranderbare infrastructuur, die een draagbare architectuur biedt en schaalbaarheid mogelijk maakt. De installatiekopieën kunnen worden gebruikt om containers te maken voor uw lokale ontwikkelomgeving, privécloud of openbare cloud.
In deze zelfstudie hebt u:
- Een eenvoudige .NET-app maken en publiceren
- Een Dockerfile maken en configureren voor .NET
- Een Docker-installatiekopie maken
- Een Docker-container maken en uitvoeren
U krijgt inzicht in de Docker-containerbuild en -implementatietaken voor een .NET-toepassing. Het Docker-platform maakt gebruik van de Docker-engine om snel apps te bouwen en te verpakken als Docker-installatiekopieën. Deze installatiekopieën worden geschreven in de Dockerfile-indeling die moet worden geïmplementeerd en uitgevoerd in een gelaagde container.
Notitie
Deze zelfstudie is niet bedoeld voor ASP.NET Core-apps. Als u ASP.NET Core gebruikt, raadpleegt u de zelfstudie Meer informatie over het in een container zetten van een ASP.NET Core-toepassing .
Vereisten
Installeer de volgende vereisten:
- .NET 8+ SDK
Als u .NET hebt geïnstalleerd, gebruikt u dedotnet --info
opdracht om te bepalen welke SDK u gebruikt. - Docker Community Edition
- Een tijdelijke werkmap voor de Dockerfile - en .NET-voorbeeld-app. In deze zelfstudie wordt de naam docker-working gebruikt als de werkmap.
- .NET 7+ SDK
Als u .NET hebt geïnstalleerd, gebruikt u dedotnet --info
opdracht om te bepalen welke SDK u gebruikt. - Docker Community Edition
- Een tijdelijke werkmap voor de Dockerfile - en .NET-voorbeeld-app. In deze zelfstudie wordt de naam docker-working gebruikt als de werkmap.
Een .NET-app maken
U hebt een .NET-app nodig die door de Docker-container wordt uitgevoerd. Open de terminal, maak een werkmap als u dat nog niet hebt gedaan en voer deze in. Voer in de werkmap de volgende opdracht uit om een nieuw project te maken in een submap met de naam App:
dotnet new console -o App -n DotNet.Docker
De mapstructuur ziet er als volgt uit:
📁 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
Met de dotnet new
opdracht maakt u een nieuwe map met de naam App en genereert u een consoletoepassing 'Hallo wereld'. Wijzig mappen en navigeer vanuit uw terminalsessie naar de map App . Gebruik de dotnet run
opdracht om de app te starten. De toepassing wordt uitgevoerd en wordt onder de opdracht afgedrukt Hello World!
:
cd App
dotnet run
Hello World!
Met de standaardsjabloon wordt een app gemaakt die naar de terminal wordt afgedrukt en vervolgens onmiddellijk wordt beëindigd. Voor deze zelfstudie gebruikt u een app die voor onbepaalde tijd wordt herhaald. Open het Program.cs-bestand in een teksteditor.
Tip
Als u Visual Studio Code gebruikt, typt u in de vorige terminalsessie de volgende opdracht:
code .
Hiermee opent u de app-map die het project in Visual Studio Code bevat.
De Program.cs moet eruitzien als de volgende C#-code:
Console.WriteLine("Hello World!");
Vervang het bestand door de volgende code waarmee elke seconde getallen worden geteld:
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));
}
Sla het bestand op en test het programma opnieuw met dotnet run
. Houd er rekening mee dat deze app voor onbepaalde tijd wordt uitgevoerd. Gebruik de opdracht Annuleren Ctrl+C om deze te stoppen. Hier volgt een voorbeeld van uitvoer:
dotnet run
Counter: 1
Counter: 2
Counter: 3
Counter: 4
^C
Als u een getal op de opdrachtregel doorgeeft aan de app, telt het alleen tot dat bedrag en sluit u af. Probeer het met dotnet run -- 5
om te tellen tot vijf.
Belangrijk
Parameters die --
niet aan de dotnet run
opdracht zijn doorgegeven en in plaats daarvan worden doorgegeven aan uw toepassing.
.NET-app publiceren
Voordat u de .NET-app toevoegt aan de Docker-installatiekopieën, moet deze eerst worden gepubliceerd. Het is raadzaam dat de container de gepubliceerde versie van de app uitvoert. Voer de volgende opdracht uit om de app te publiceren:
dotnet publish -c Release
Met deze opdracht wordt uw app gecompileerd naar de publicatiemap . Het pad naar de publicatiemap uit de werkmap moet zijn .\App\bin\Release\net8.0\publish\
.
Met deze opdracht wordt uw app gecompileerd naar de publicatiemap . Het pad naar de publicatiemap uit de werkmap moet zijn .\App\bin\Release\net7.0\publish\
.
Haal in de map App een map op van de publicatiemap om te controleren of het DotNet.Docker.dll bestand is gemaakt.
dir .\bin\Release\net8.0\publish\
Directory: C:\Users\default\App\bin\Release\net8.0\publish
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 9/22/2023 9:17 AM 431 DotNet.Docker.deps.json
-a--- 9/22/2023 9:17 AM 6144 DotNet.Docker.dll
-a--- 9/22/2023 9:17 AM 157696 DotNet.Docker.exe
-a--- 9/22/2023 9:17 AM 11688 DotNet.Docker.pdb
-a--- 9/22/2023 9:17 AM 353 DotNet.Docker.runtimeconfig.json
dir .\bin\Release\net7.0\publish\
Directory: C:\Users\default\App\bin\Release\net7.0\publish
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/13/2023 1:52 PM 431 DotNet.Docker.deps.json
-a--- 2/13/2023 1:52 PM 6144 DotNet.Docker.dll
-a--- 2/13/2023 1:52 PM 153600 DotNet.Docker.exe
-a--- 2/13/2023 1:52 PM 11052 DotNet.Docker.pdb
-a--- 2/13/2023 1:52 PM 253 DotNet.Docker.runtimeconfig.json
Het Dockerfile maken
Het Dockerfile-bestand wordt gebruikt door de docker build
opdracht om een containerinstallatiekopieën te maken. Dit bestand is een tekstbestand met de naam Dockerfile dat geen extensie heeft.
Maak een bestand met de naam Dockerfile in de map met de .csproj en open het in een teksteditor. In deze zelfstudie wordt gebruikgemaakt van de ASP.NET Core Runtime-installatiekopieën (die de .NET Runtime-installatiekopieën bevat) en komt overeen met de .NET-consoletoepassing.
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /App
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
Notitie
De ASP.NET Core Runtime-installatiekopieën worden hier opzettelijk gebruikt, hoewel de mcr.microsoft.com/dotnet/runtime:8.0
installatiekopieën mogelijk zijn gebruikt.
Tip
Dit Dockerfile maakt gebruik van builds met meerdere fasen, waarmee de uiteindelijke grootte van de installatiekopieën wordt geoptimaliseerd door de build gelaagd te maken en alleen vereiste artefacten achter te laten. Zie Docker Docs: builds met meerdere fasen voor meer informatie.
Voor het FROM
trefwoord is een volledig gekwalificeerde Naam van docker-containerinstallatiekopieën vereist. Microsoft Container Registry (MCR, mcr.microsoft.com) is een syndicate van Docker Hub, die openbaar toegankelijke containers host. Het dotnet
segment is de containeropslagplaats, terwijl het sdk
of aspnet
segment de naam van de containerinstallatiekopieën is. De installatiekopieën zijn gelabeld met 8.0
, die worden gebruikt voor versiebeheer. mcr.microsoft.com/dotnet/aspnet:8.0
Is dus de .NET 8.0-runtime. Zorg ervoor dat u de runtimeversie ophaalt die overeenkomt met de runtime waarop uw SDK is gericht. De app die in de vorige sectie is gemaakt, heeft bijvoorbeeld de .NET 8.0 SDK gebruikt en de basisinstallatiekopieën waarnaar wordt verwezen in het Dockerfile , zijn gelabeld met 8.0.
Belangrijk
Wanneer u containerinstallatiekopieën op basis van Windows gebruikt, moet u de installatiekopieëntag niet alleen 8.0
opgeven, mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-1809
bijvoorbeeld in plaats van mcr.microsoft.com/dotnet/aspnet:8.0
. Selecteer een installatiekopieënnaam op basis van of u Nano Server of Windows Server Core gebruikt en welke versie van dat besturingssysteem. U vindt een volledige lijst met alle ondersteunde tags op. Docker Hub-pagina van NET.
Sla het Dockerfile-bestand op. De mapstructuur van de werkmap moet er als volgt uitzien. Sommige bestanden en mappen op dieper niveau zijn weggelaten om ruimte te besparen in het artikel:
📁 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
└──...
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /App
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
Notitie
De ASP.NET Core Runtime-installatiekopieën worden hier opzettelijk gebruikt, hoewel de mcr.microsoft.com/dotnet/runtime:7.0
installatiekopieën mogelijk zijn gebruikt.
Tip
Dit Dockerfile maakt gebruik van builds met meerdere fasen, waarmee de uiteindelijke grootte van de installatiekopieën wordt geoptimaliseerd door de build gelaagd te maken en alleen vereiste artefacten achter te laten. Zie Docker Docs: builds met meerdere fasen voor meer informatie.
Voor het FROM
trefwoord is een volledig gekwalificeerde Naam van docker-containerinstallatiekopieën vereist. Microsoft Container Registry (MCR, mcr.microsoft.com) is een syndicate van Docker Hub, die als host fungeert voor openbaar toegankelijke containers. Het dotnet
segment is de containeropslagplaats, terwijl het sdk
of aspnet
segment de naam van de containerinstallatiekopieën is. De installatiekopieën zijn gelabeld met 7.0
, die worden gebruikt voor versiebeheer. mcr.microsoft.com/dotnet/aspnet:7.0
Is dus de .NET 7.0-runtime. Zorg ervoor dat u de runtimeversie ophaalt die overeenkomt met de runtime waarop uw SDK is gericht. De app die in de vorige sectie is gemaakt, heeft bijvoorbeeld de .NET 7.0 SDK gebruikt en de basisinstallatiekopieën waarnaar wordt verwezen in het Dockerfile , zijn getagd met 7.0.
Sla het Dockerfile-bestand op. De mapstructuur van de werkmap moet er als volgt uitzien. Sommige bestanden en mappen op dieper niveau zijn weggelaten om ruimte te besparen in het artikel:
📁 docker-working
└──📂 App
├── Dockerfile
├── DotNet.Docker.csproj
├── Program.cs
├──📂 bin
│ └──📂 Release
│ └──📂 net7.0
│ └──📂 publish
│ ├── DotNet.Docker.deps.json
│ ├── DotNet.Docker.exe
│ ├── DotNet.Docker.dll
│ ├── DotNet.Docker.pdb
│ └── DotNet.Docker.runtimeconfig.json
└──📁 obj
└──...
Voer vanuit de terminal de volgende opdracht uit:
docker build -t counter-image -f Dockerfile .
Docker verwerkt elke regel in het Dockerfile. .
Met de docker build
opdracht wordt de buildcontext van de installatiekopieën ingesteld. De -f
switch is het pad naar het Dockerfile. Met deze opdracht wordt de installatiekopieën gebouwd en wordt een lokale opslagplaats gemaakt met de naam counter-image die naar die installatiekopieën verwijst. Nadat deze opdracht is voltooid, voert u de opdracht uit docker images
om een lijst met geïnstalleerde installatiekopieën weer te geven:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
counter-image latest 2f15637dc1f6 10 minutes ago 217MB
De counter-image
opslagplaats is de naam van de installatiekopieën. De latest
tag is de tag die wordt gebruikt om de afbeelding te identificeren. Dit 2f15637dc1f6
is de afbeeldings-id. Dit 10 minutes ago
is het tijdstip waarop de installatiekopieën zijn gemaakt. De 217MB
grootte van de afbeelding is. De laatste stappen van het Dockerfile zijn het maken van een container op basis van de installatiekopie en het uitvoeren van de app, het kopiëren van de gepubliceerde app naar de container en het invoerpunt definiëren.
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
counter-image latest 2f15637dc1f6 10 minutes ago 208MB
De counter-image
opslagplaats is de naam van de installatiekopieën. De latest
tag is de tag die wordt gebruikt om de afbeelding te identificeren. Dit 2f15637dc1f6
is de afbeeldings-id. Dit 10 minutes ago
is het tijdstip waarop de installatiekopieën zijn gemaakt. De 208MB
grootte van de afbeelding is. De laatste stappen van het Dockerfile zijn het maken van een container op basis van de installatiekopie en het uitvoeren van de app, het kopiëren van de gepubliceerde app naar de container en het invoerpunt definiëren.
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
Met COPY
de opdracht moet Docker de opgegeven map op uw computer kopiëren naar een map in de container. In dit voorbeeld wordt de publicatiemap gekopieerd naar een map met de naam App/out in de container.
Met WORKDIR
de opdracht wordt de huidige map in de container gewijzigd in App.
Met de volgende opdracht geeft ENTRYPOINT
Docker de opdracht om de container te configureren voor uitvoering als uitvoerbaar bestand. Wanneer de container wordt gestart, wordt de ENTRYPOINT
opdracht uitgevoerd. Wanneer deze opdracht eindigt, stopt de container automatisch.
Tip
Voordat .NET 8 is geconfigureerd, kunnen containers die zijn geconfigureerd om als alleen-lezen te worden uitgevoerd, mislukken met Failed to create CoreCLR, HRESULT: 0x8007000E
. Als u dit probleem wilt oplossen, geeft u een DOTNET_EnableDiagnostics
omgevingsvariabele op als 0
(net vóór de ENTRYPOINT
stap):
ENV DOTNET_EnableDiagnostics=0
Zie .NET-omgevingsvariabelen voor meer informatie over verschillende .NET-omgevingsvariabelen.
Notitie
.NET 6 standaardiseert het voorvoegsel DOTNET_
in plaats van COMPlus_
voor omgevingsvariabelen die .NET-runtimegedrag configureren. COMPlus_
Het voorvoegsel blijft echter werken. Als u een eerdere versie van de .NET-runtime gebruikt, moet u nog steeds het COMPlus_
voorvoegsel voor omgevingsvariabelen gebruiken.
Een container maken
Nu u een installatiekopieën hebt die uw app bevat, kunt u een container maken. U kunt op twee manieren een container maken. Maak eerst een nieuwe container die is gestopt.
docker create --name core-counter counter-image
Met deze docker create
opdracht maakt u een container op basis van de installatiekopieën van de tellerinstallatiekopieën . In de uitvoer van deze opdracht ziet u de CONTAINER-id (die van u anders is) van de gemaakte container:
d0be06126f7db6dd1cee369d911262a353c9b7fb4829a0c11b4b2eb7b2d429cf
Gebruik de docker ps -a
opdracht om een lijst met alle containers weer te geven:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d0be06126f7d counter-image "dotnet DotNet.Docke…" 12 seconds ago Created core-counter
De container beheren
De container is gemaakt met een specifieke naam core-counter
. Deze naam wordt gebruikt om de container te beheren. In het volgende voorbeeld wordt de docker start
opdracht gebruikt om de container te starten en wordt vervolgens de docker ps
opdracht gebruikt om alleen containers weer te geven die worden uitgevoerd:
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
Op dezelfde manier stopt de docker stop
opdracht de container. In het volgende voorbeeld wordt de opdracht gebruikt om de docker stop
container te stoppen en gebruikt u vervolgens de docker ps
opdracht om aan te geven dat er geen containers worden uitgevoerd:
docker stop core-counter
core-counter
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Verbinding maken naar een container
Nadat een container wordt uitgevoerd, kunt u er verbinding mee maken om de uitvoer te zien. Gebruik de docker start
en docker attach
opdrachten om de container te starten en de uitvoerstroom te bekijken. In dit voorbeeld wordt de toetsaanslag Ctrl+C gebruikt om los te koppelen van de actieve container. Met deze toetsaanslag wordt het proces in de container beëindigd, tenzij anders is opgegeven, waardoor de container wordt gestopt. De --sig-proxy=false
parameter zorgt ervoor dat Ctrl+C het proces in de container niet stopt.
Nadat u de container loskoppelt, koppelt u deze opnieuw om te controleren of deze nog steeds wordt uitgevoerd en geteld.
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
Een container verwijderen
Voor dit artikel wilt u niet dat containers rondhangen die niets doen. Verwijder de container die u eerder hebt gemaakt. Als de container wordt uitgevoerd, stopt u deze.
docker stop core-counter
In het volgende voorbeeld ziet u alle containers. Vervolgens wordt de docker rm
opdracht gebruikt om de container te verwijderen en vervolgens een tweede keer te controleren op actieve containers.
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
Eén uitvoering
Docker biedt de opdracht om de docker run
container als één opdracht te maken en uit te voeren. Deze opdracht elimineert de noodzaak om uit te voeren docker create
en vervolgens docker start
. U kunt deze opdracht ook instellen om de container automatisch te verwijderen wanneer de container stopt. Gebruik bijvoorbeeld docker run -it --rm
om twee dingen uit te voeren, eerst de huidige terminal automatisch te gebruiken om verbinding te maken met de container en vervolgens wanneer de container is voltooid, verwijdert u deze:
docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
^C
De container geeft ook parameters door aan de uitvoering van de .NET-app. Als u de .NET-app wilt instrueren om slechts drie te tellen, geeft u 3 door.
docker run -it --rm counter-image 3
Counter: 1
Counter: 2
Counter: 3
Met docker run -it
de opdracht Ctrl+C stopt u het proces dat wordt uitgevoerd in de container, waardoor de container op zijn beurt wordt gestopt. Omdat de --rm
parameter is opgegeven, wordt de container automatisch verwijderd wanneer het proces wordt gestopt. Controleer of deze niet bestaat:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Het ENTRYPOINT wijzigen
Met docker run
de opdracht kunt u ook de ENTRYPOINT
opdracht wijzigen vanuit het Dockerfile en iets anders uitvoeren, maar alleen voor die container. Gebruik bijvoorbeeld de volgende opdracht om uit te voeren bash
of cmd.exe
. Bewerk de opdracht indien nodig.
In dit voorbeeld ENTRYPOINT
wordt dit gewijzigd in cmd.exe
. Ctrl+C wordt ingedrukt om het proces te beëindigen en de container te stoppen.
docker run -it --rm --entrypoint "cmd.exe" counter-image
Microsoft Windows [Version 10.0.17763.379]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\>dir
Volume in drive C has no label.
Volume Serial Number is 3005-1E84
Directory of C:\
04/09/2019 08:46 AM <DIR> app
03/07/2019 10:25 AM 5,510 License.txt
04/02/2019 01:35 PM <DIR> Program Files
04/09/2019 01:06 PM <DIR> Users
04/02/2019 01:35 PM <DIR> Windows
1 File(s) 5,510 bytes
4 Dir(s) 21,246,517,248 bytes free
C:\>^C
Essentiële opdrachten
Docker heeft veel verschillende opdrachten die containers en installatiekopieën maken, beheren en gebruiken. Deze Docker-opdrachten zijn essentieel voor het beheren van uw containers:
Resources opschonen
Tijdens deze zelfstudie hebt u containers en installatiekopieën gemaakt. Verwijder deze resources desgewenst. Gebruik de volgende opdrachten om
Alle containers weergeven
docker ps -a
Stop containers die op hun naam worden uitgevoerd.
docker stop core-counter
De container verwijderen
docker rm core-counter
Verwijder vervolgens alle installatiekopieën die u niet meer op uw computer wilt gebruiken. Verwijder de installatiekopieën die zijn gemaakt door uw Dockerfile en verwijder vervolgens de .NET-installatiekopieën waarop het Dockerfile is gebaseerd. U kunt de afbeeldings-id of de tekenreeks REPOSITORY:TAG-indeling gebruiken.
docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:8.0
docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:7.0
Gebruik de docker images
opdracht om een lijst met geïnstalleerde installatiekopieën weer te geven.
Tip
Afbeeldingsbestanden kunnen groot zijn. Normaal gesproken verwijdert u tijdelijke containers die u hebt gemaakt tijdens het testen en ontwikkelen van uw app. Meestal houdt u de basisinstallatiekopieën bij de runtime geïnstalleerd als u van plan bent om andere installatiekopieën te bouwen op basis van die runtime.