Tutorial: Mengontainerisasi aplikasi .NET
Dalam tutorial ini, Anda mempelajari cara membuat kontainer aplikasi .NET dengan Docker. Kontainer memiliki banyak fitur dan manfaat, seperti menjadi infrastruktur yang tidak dapat diubah, menyediakan arsitektur portabel, dan memungkinkan skalabilitas. Gambar dapat digunakan untuk membuat kontainer untuk lingkungan pengembangan lokal, cloud privat, atau cloud publik Anda.
Dalam tutorial ini, Anda:
- Membuat dan menerbitkan aplikasi .NET sederhana
- Membuat dan mengonfigurasi Dockerfile untuk .NET
- Membangun gambar Docker
- Membuat dan menjalankan kontainer Docker
Anda menjelajahi build kontainer Docker dan menyebarkan tugas untuk aplikasi .NET. Platform Docker
Saran
Jika Anda tertarik untuk menerbitkan aplikasi .NET anda sebagai kontainer tanpa perlu Docker atau Podman, lihat Containerize aplikasi .NET dengan dotnet publish.
Nota
Tutorial ini tidak untuk aplikasi ASP.NET Core. Jika Anda menggunakan ASP.NET Core, lihat tutorial Pelajari cara membuat kontainer aplikasi ASP.NET Core.
Prasyarat
Instal prasyarat berikut:
-
.NET 8+ SDK.
Jika Anda telah menginstal .NET, gunakan perintahdotnet --info
untuk menentukan SDK mana yang Anda gunakan. - Docker Community Edition.
- Folder kerja sementara untuk Dockerfile dan aplikasi contoh .NET. Dalam tutorial ini, nama yang berfungsi dengan docker digunakan sebagai folder kerja.
Membuat aplikasi .NET
Anda memerlukan aplikasi .NET yang dijalankan kontainer Docker. Buka terminal Anda, buat folder yang berfungsi jika Anda belum melakukannya, dan masukkan. Di folder kerja, jalankan perintah berikut untuk membuat proyek baru di subdirektori bernama App:
dotnet new console -o App -n DotNet.Docker
Pohon folder Anda terlihat mirip dengan struktur direktori berikut:
π 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
Perintah dotnet new
membuat folder baru bernama App dan menghasilkan aplikasi konsol "Halo Dunia". Sekarang, Anda mengubah direktori dan menavigasi ke folder Aplikasi dotnet run
untuk memulai aplikasi. Aplikasi dijalankan, dan mencetak Hello World!
di bawah perintah:
cd App
dotnet run
Hello World!
Templat default membuat aplikasi yang mencetak ke terminal dan kemudian segera berakhir. Untuk tutorial ini, Anda menggunakan aplikasi yang mengulang tanpa batas waktu. Buka file Program.cs di editor teks.
Ujung
Jika Anda menggunakan Visual Studio Code, dari sesi terminal sebelumnya ketik perintah berikut:
code .
Perintah ini membuka folder Aplikasi
Program.cs akan terlihat seperti kode C# berikut:
Console.WriteLine("Hello World!");
Ganti file dengan kode berikut yang menghitung angka setiap detik:
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));
}
Simpan file dan uji program lagi dengan dotnet run
. Ingatlah bahwa aplikasi ini berjalan tanpa batas waktu. Gunakan perintah batalkan Ctrl+C untuk menghentikannya. Pertimbangkan contoh output berikut:
dotnet run
Counter: 1
Counter: 2
Counter: 3
Counter: 4
^C
Jika Anda memasukkan angka pada baris perintah ke dalam aplikasi, aplikasi tersebut akan membatasi jumlahnya hingga angka tersebut dan kemudian keluar. Cobalah dengan dotnet run -- 5
untuk menghitung hingga lima.
Penting
Parameter apa pun setelah --
tidak diteruskan ke perintah dotnet run
dan sebaliknya diteruskan ke aplikasi Anda.
Menerbitkan aplikasi .NET
Agar aplikasi cocok untuk pembuatan gambar, aplikasi harus dikompilasi. Perintah dotnet publish
paling sesuai untuk ini, karena membangun dan menerbitkan aplikasi. Untuk referensi mendalam, lihat dokumentasi perintah dotnet build dan dotnet publish.
dotnet publish -c Release
Tips
Jika Anda tertarik untuk menerbitkan aplikasi .NET Anda sebagai kontainer tanpa perlu Docker, silakan lihat Memberikan Kontainer pada aplikasi .NET dengan dotnet publish.
Perintah
- Windows
- Linux
Dari folder Aplikasi, peroleh daftar direktori folder publikasi untuk memverifikasi bahwa file DotNet.Docker.dll telah dibuat.
dir .\bin\Release\net9.0\publish\
Directory: C:\Users\default\docker-working\App\bin\Release\net9.0\publish
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/6/2025 10:11 AM 431 DotNet.Docker.deps.json
-a---- 1/6/2025 10:11 AM 6144 DotNet.Docker.dll
-a---- 1/6/2025 10:11 AM 145408 DotNet.Docker.exe
-a---- 1/6/2025 10:11 AM 11716 DotNet.Docker.pdb
-a---- 1/6/2025 10:11 AM 340 DotNet.Docker.runtimeconfig.json
dir .\bin\Release\net8.0\publish\
Directory: C:\Users\default\docker-working\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
Membuat Dockerfile
File Dockerfile
Buat file bernama Dockerfile di direktori yang berisi .csproj dan buka di editor teks. Tutorial ini menggunakan gambar runtime ASP.NET Core (yang berisi gambar runtime .NET) dan sesuai dengan aplikasi konsol .NET.
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"]
Nota
Gambar runtime ASP.NET Core sengaja digunakan di sini, meskipun gambar mcr.microsoft.com/dotnet/runtime:9.0
dapat digunakan sebagai gantinya.
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"]
Nota
Gambar runtime ASP.NET Core sengaja digunakan di sini, meskipun gambar mcr.microsoft.com/dotnet/runtime:8.0
dapat digunakan sebagai gantinya.
Penting
Termasuk algoritma hash yang aman (SHA) setelah tag gambar dalam Dockerfile adalah praktik terbaik. Ini memastikan bahwa gambar tidak dirusak dan gambarnya sama dengan yang Anda harapkan. SHA adalah pengidentifikasi unik untuk gambar. Untuk informasi selengkapnya, lihat Docker Docs: Mengambil citra berdasarkan digest.
Tips
Dockerfile
Kata kunci FROM
memerlukan nama gambar kontainer Docker yang sepenuhnya memenuhi syarat. Microsoft Container Registry (MCR, mcr.microsoft.com) adalah sindikat Docker Hub, yang menghosting kontainer yang dapat diakses publik. Segmen dotnet
adalah repositori kontainer, sedangkan segmen sdk
atau aspnet
adalah nama gambar kontainer. Gambar ditandai dengan 9.0
, yang digunakan untuk pengelolaan versi. Dengan demikian, mcr.microsoft.com/dotnet/aspnet:9.0
adalah runtime .NET 9.0. Pastikan Anda menarik versi runtime yang cocok dengan runtime yang ditentukan oleh SDK Anda. Misalnya, aplikasi yang dibuat di bagian sebelumnya menggunakan .NET 9.0 SDK, dan gambar dasar yang dimaksud dalam Dockerfile
Penting
Saat menggunakan gambar kontainer berbasis Windows, Anda perlu menentukan tag gambar di luar hanya 9.0
, misalnya, mcr.microsoft.com/dotnet/aspnet:9.0-nanoserver-1809
alih-alih mcr.microsoft.com/dotnet/aspnet:9.0
. Pilih nama gambar berdasarkan apakah Anda menggunakan Nano Server atau Windows Server Core dan versi OS tersebut. Anda dapat menemukan daftar lengkap semua tag yang didukung di halaman Docker Hub .NET .
Simpan file Dockerfile. Struktur direktori folder kerja akan terlihat seperti berikut ini. Beberapa file dan folder tingkat yang lebih dalam dihilangkan untuk menghemat ruang dalam artikel:
π 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
βββ...
Kata kunci FROM
memerlukan nama gambar kontainer Docker yang sepenuhnya memenuhi syarat. Microsoft Container Registry (MCR, mcr.microsoft.com) adalah sindikat Docker Hub, yang menghosting kontainer yang dapat diakses publik. Segmen dotnet
adalah repositori kontainer, sedangkan segmen sdk
atau aspnet
adalah nama gambar kontainer. Gambar ditandai dengan 8.0
, yang digunakan untuk penandaan versi. Dengan demikian, mcr.microsoft.com/dotnet/aspnet:8.0
adalah runtime .NET 8.0. Pastikan Anda mengambil versi runtime yang cocok dengan runtime yang ditargetkan oleh SDK Anda. Misalnya, aplikasi yang dibuat di bagian sebelumnya menggunakan .NET 8.0 SDK, dan gambar dasar yang dimaksud dalam Dockerfile ditandai dengan 8.0.
Penting
Saat menggunakan gambar kontainer berbasis Windows, Anda perlu menentukan tag gambar di luar hanya 8.0
, misalnya, mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-1809
alih-alih mcr.microsoft.com/dotnet/aspnet:8.0
. Pilih nama gambar berdasarkan apakah Anda menggunakan Nano Server atau Windows Server Core dan versi OS tersebut. Anda dapat menemukan daftar lengkap semua tag yang didukung di halaman Docker Hub .NET
Simpan file Dockerfile. Struktur direktori folder kerja akan terlihat seperti berikut ini. Beberapa file dan folder tingkat yang lebih dalam dihilangkan untuk menghemat ruang dalam 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
βββ...
Instruksi ENTRYPOINT
menetapkan dotnet
sebagai host untuk DotNet.Docker.dll
. Namun, dimungkinkan untuk mendefinisikan ENTRYPOINT
sebagai aplikasi yang dapat dieksekusi itu sendiri, mengandalkan OS sebagai host aplikasi:
ENTRYPOINT ["./DotNet.Docker"]
Ini menyebabkan aplikasi dijalankan secara langsung, tanpa dotnet
, dan sebaliknya bergantung pada host aplikasi dan OS yang mendasar. Untuk informasi selengkapnya tentang menyebarkan biner lintas platform, lihat Menghasilkan biner lintas platform.
Untuk membangun kontainer, dari terminal Anda, jalankan perintah berikut:
docker build -t counter-image -f Dockerfile .
Docker memproses setiap baris diDockerfile .
dalam perintah docker build
mengatur konteks build gambar. Sakelar -f
adalah jalur ke Dockerfile. Perintah ini membangun gambar dan membuat repositori lokal bernama counter-image yang menunjuk ke gambar tersebut. Setelah perintah ini selesai, jalankan docker images
untuk melihat daftar gambar yang diinstal:
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
Repositori counter-image
adalah nama dari gambar tersebut. Selain itu, tag gambar, pengidentifikasi gambar, ukuran, dan kapan dibuat semuanya adalah bagian dari output. Langkah terakhir Dockerfile
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"]
Perintah FROM
menentukan gambar dasar dan tag yang akan digunakan. Perintah WORKDIR
mengubah direktori saat ini di dalam kontainer menjadi App.
Perintah COPY
memberi tahu Docker untuk menyalin direktori sumber yang ditentukan ke folder tujuan. Dalam contoh ini, konten yang diterbitkan oleh
Perintah berikutnya, ENTRYPOINT
, memberi tahu Docker untuk mengonfigurasi kontainer agar berjalan sebagai executable. Saat kontainer dimulai, perintah ENTRYPOINT
berjalan. Ketika perintah ini berakhir, kontainer secara otomatis berhenti.
Tips
Sebelum .NET 8, kontainer yang dikonfigurasi untuk berjalan sebagai baca-saja mungkin gagal dengan Failed to create CoreCLR, HRESULT: 0x8007000E
. Untuk mengatasi masalah ini, tentukan variabel lingkungan DOTNET_EnableDiagnostics
sebagai 0
(tepat sebelum langkah ENTRYPOINT
):
ENV DOTNET_EnableDiagnostics=0
Untuk informasi selengkapnya tentang berbagai variabel lingkungan .NET, lihat variabel lingkungan .NET.
Nota
.NET 6 menstandarkan pada awalan DOTNET_
alih-alih COMPlus_
untuk variabel lingkungan yang mengonfigurasi perilaku run-time .NET. Namun, awalan COMPlus_
akan terus berfungsi. Jika Anda menggunakan versi runtime .NET sebelumnya, Anda masih harus menggunakan awalan COMPlus_
untuk variabel lingkungan.
Membuat kontainer
Setelah memiliki gambar yang berisi aplikasi, Anda dapat membuat kontainer. Anda dapat membuat kontainer dengan dua cara. Pertama, buat kontainer baru yang dihentikan.
docker create --name core-counter counter-image
Perintah docker create
ini membuat kontainer berdasarkan gambar counter-image. Hasil perintah docker create
menunjukkan ID KONTAINER dari kontainer (pengidentifikasi Anda mungkin berbeda):
d0be06126f7db6dd1cee369d911262a353c9b7fb4829a0c11b4b2eb7b2d429cf
Untuk melihat daftar semua kontainer, gunakan perintah 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
Mengelola kontainer
Kontainer dibuat dengan nama tertentu core-counter
. Nama ini digunakan untuk mengelola kontainer. Contoh berikut menggunakan perintah docker start
untuk memulai kontainer, lalu menggunakan perintah docker ps
untuk hanya menampilkan kontainer yang sedang berjalan:
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
Demikian pula, perintah docker stop
menghentikan kontainer. Contoh berikut menggunakan perintah docker stop
untuk menghentikan kontainer, lalu menggunakan perintah docker ps
untuk menunjukkan bahwa tidak ada kontainer yang berjalan:
docker stop core-counter
core-counter
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Menyambungkan ke kontainer
Setelah kontainer berjalan, Anda dapat menyambungkannya untuk melihat output. Gunakan perintah docker start
dan docker attach
untuk memulai kontainer dan mengintip aliran output. Dalam contoh ini, kombinasi tombol Ctrl+C digunakan untuk melepaskan dari kontainer aktif. Penekanan tombol ini mengakhiri proses dalam kontainer kecuali ditentukan sebaliknya, yang akan menghentikan kontainernya. Parameter --sig-proxy=false
memastikan bahwa Ctrl+C tidak menghentikan proses dalam kontainer.
Setelah Anda melepaskan diri dari kontainer, hubungkan kembali untuk memverifikasi bahwa kontainer masih berjalan dan menghitung.
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
Menghapus kontainer
Untuk artikel ini, Anda tidak ingin kontainer berkeliaran di sekitar yang tidak melakukan apa pun. Hapus kontainer yang sebelumnya Anda buat. Jika kontainer berjalan, hentikan.
docker stop core-counter
Contoh berikut mencantumkan semua kontainer. Kemudian menggunakan perintah docker rm
untuk menghapus kontainer lalu memeriksa untuk kedua kalinya untuk setiap kontainer yang sedang berjalan.
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
Putaran tunggal
Docker menyediakan perintah docker run
untuk membuat dan menjalankan kontainer sebagai satu perintah. Perintah ini menghilangkan kebutuhan untuk menjalankan docker create
lalu docker start
. Anda juga dapat mengatur perintah ini untuk menghapus kontainer secara otomatis saat kontainer berhenti. Misalnya, gunakan docker run -it --rm
untuk melakukan dua hal, pertama, secara otomatis menggunakan terminal saat ini untuk terhubung ke kontainer, lalu ketika kontainer selesai, hapus:
docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
^C
Kontainer juga meneruskan parameter ke dalam eksekusi aplikasi .NET. Untuk menginstruksikan aplikasi .NET untuk menghitung hanya hingga tiga, masukkan nilai 3.
docker run -it --rm counter-image 3
Counter: 1
Counter: 2
Counter: 3
Dengan docker run -it
, perintah Ctrl+C menghentikan proses yang berjalan dalam kontainer, yang kemudian menghentikan kontainer. Karena parameter --rm
disediakan, kontainer secara otomatis dihapus ketika proses dihentikan. Verifikasi bahwa itu tidak ada:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Mengubah Titik Masuk
Perintah bash
atau cmd.exe
. Edit perintah seperlunya.
Dalam contoh ini, ENTRYPOINT
diubah menjadi cmd.exe
.
Ctrl+C ditekan untuk mengakhiri proses dan menghentikan kontainer.
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
Nota
Contoh ini hanya berfungsi pada kontainer Windows. Kontainer Linux tidak memiliki cmd.exe
.
Perintah penting
Docker memiliki banyak perintah berbeda yang membuat, mengelola, dan berinteraksi dengan kontainer dan gambar. Perintah Docker ini sangat penting untuk mengelola kontainer Anda:
Membersihkan sumber daya
Selama tutorial ini, Anda membuat kontainer dan gambar. Jika mau, hapus sumber daya ini. Gunakan perintah berikut untuk
Mencantumkan semua kontainer
docker ps -a
Hentikan kontainer yang sedang berjalan berdasarkan namanya.
docker stop core-counter
Menghapus kontainer
docker rm core-counter
Selanjutnya, hapus gambar apa pun yang tidak lagi Anda inginkan di komputer Anda. Hapus gambar yang dibuat oleh Dockerfile
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
Gunakan perintah docker images
untuk melihat daftar gambar yang terinstal.
Tips
File gambar bisa besar. Biasanya, Anda akan menghapus kontainer sementara yang Anda buat saat menguji dan mengembangkan aplikasi Anda. Anda biasanya menyimpan gambar dasar dengan runtime yang diinstal jika Anda berencana membangun gambar lain berdasarkan runtime tersebut.