Aplikasi Core ASP.NET benar-benar lintas platform dan dapat berjalan di nixes dan, karenanya, di Docker. Mari kita lihat bagaimana mereka dapat dikemas untuk digunakan di Linux dan digunakan bersama dengan Nginx. Detail di bawah potongan!

Catatan: kami melanjutkan serangkaian publikasi artikel versi lengkap dari majalah Hacker. Ejaan dan tanda baca penulis disimpan.
Tentang Docker
Hampir setiap orang pernah mendengar tentang arsitektur layanan mikro. Konsep memecah aplikasi menjadi beberapa bagian bukan untuk mengatakan bahwa itu baru. Namun, yang baru adalah yang lama terlupakan dan didaur ulang.
Jika Anda mencoba berbicara tentang arsitektur dalam beberapa kata, maka aplikasi web dibagi menjadi beberapa bagian kesatuan - layanan. Layanan tidak berinteraksi langsung satu sama lain dan tidak memiliki database umum. Ini dilakukan untuk dapat mengubah setiap layanan tanpa konsekuensi bagi yang lain. Layanan dikemas dalam wadah. Di antara kontainer, Docker menguasai bola.
Untuk menggambarkan apa Docker sangat sering disederhanakan menggunakan istilah "mesin virtual". Jelas ada kesamaan, tetapi salah untuk mengatakannya. Cara termudah untuk memahami perbedaan ini adalah dengan melihat gambar-gambar berikut dari dokumentasi buruh pelabuhan resmi:


Kontainer menggunakan inti dari sistem operasi saat ini dan membaginya di antara mereka sendiri. Sedangkan mesin virtual menggunakan hypervisor menggunakan sumber daya perangkat keras.
Gambar Docker adalah objek hanya baca yang pada dasarnya menyimpan templat untuk membuat wadah. Wadah adalah lingkungan di mana kode dieksekusi. Gambar disimpan dalam repositori. Sebagai contoh, repositori Docker Hub resmi memungkinkan Anda untuk menyimpan hanya satu gambar secara pribadi. Namun, gratis, jadi untuk ini Anda perlu berterima kasih kepada mereka.
INFO
Docker bukan satu-satunya perwakilan dari containerisasi. Selain itu, ada teknologi lainnya. Sebagai contoh:
rkt (diucapkan 'roket') oleh CoreOS
LXD (diucapkan 'lexdi') oleh Ubuntu
Wadah Windows - Anda tidak akan pernah menebak dari siapa pun.
Sekarang kita telah membiasakan diri dengan teori, mari kita lanjutkan ke praktik.
Tidak ada gunanya membongkar instalasi buruh pelabuhan, karena dapat diinstal pada banyak sistem operasi. Saya hanya akan menunjukkan bahwa Anda dapat mengunduhnya untuk platform Anda dari Docker Store . Jika Anda menginstal Docker di Windows, maka virtualisasi harus diaktifkan di BIOS dan OS. Anda dapat membaca tentang cara mengaktifkannya dalam 10-ke dalam artikel berikut: Menginstal Hyper-V di Windows10
Membuat proyek yang didukung buruh pelabuhan
Docker, tentu saja, adalah produk Linux, tetapi jika perlu, Anda dapat menggunakannya saat mengembangkan untuk Mac atau untuk Windows. Saat membuat proyek di Visual Studio, untuk menambahkan dukungan buruh pelabuhan, cukup pilih kotak centang Aktifkan Dukungan Docker.
Dukungan Docker dapat ditambahkan ke proyek yang ada. Itu ditambahkan ke proyek dengan cara yang sama seperti berbagai komponen baru ditambahkan. Menu konteks Tambah - Dukungan Docker.
Jika docker diinstal dan dijalankan pada mesin Anda, konsol akan dibuka secara otomatis dan perintah akan dieksekusi
docker pull microsoft/aspnetcore:2.0
yang memulai proses mengunduh gambar. Gambar ini sebenarnya kosong berdasarkan gambar yang akan Anda buat. ASP.NET Core 2.1 menggunakan gambar yang berbeda - microsoft / dotnet: sdk
File-file berikut akan secara otomatis dibuat di direktori dengan solusi untuk Anda:
.dockerignore (tidak termasuk file dan direktori dari gambar docker), docker-compose.yml (menggunakan file ini Anda dapat mengonfigurasi pelaksanaan beberapa layanan), docker-compose.override.yml (susunan tambahan docker-compose), docker-compose.dcproj ( file proyek untuk Visual Studio).
File Dockerfile akan dibuat di direktori proyek. Sebenarnya, dengan bantuan file ini kami membuat gambar kami. Secara default (jika proyek ini disebut DockerServiceDemo) mungkin terlihat seperti ini:
FROM microsoft/aspnetcore:2.0 AS base WORKDIR /app EXPOSE 80 FROM microsoft/aspnetcore-build:2.0 AS build WORKDIR /src COPY DockerServiceDemo/DockerServiceDemo.csproj DockerServiceDemo/ RUN dotnet restore DockerServiceDemo/DockerServiceDemo.csproj COPY . . WORKDIR /src/DockerServiceDemo RUN dotnet build DockerServiceDemo.csproj -c Release -o /app FROM build AS publish RUN dotnet publish DockerServiceDemo.csproj -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "DockerServiceDemo.dll"]
Konfigurasi awal untuk .NET Core 2.0 tidak akan memungkinkan Anda untuk segera membangun gambar menggunakan perintah build docker. Ini dikonfigurasi untuk meluncurkan file docker-compose dari direktori satu tingkat ke atas. Agar konstruksi dapat berjalan dengan sukses, Dockerfile dapat dibawa ke tampilan yang sama:
FROM microsoft/aspnetcore:2.0 AS base WORKDIR /app EXPOSE 80 FROM microsoft/aspnetcore-build:2.0 AS build WORKDIR /src COPY DockerServiceDemo.csproj DockerServiceDemo.csproj RUN dotnet restore DockerServiceDemo.csproj COPY . . WORKDIR /src RUN dotnet build DockerServiceDemo.csproj -c Release -o /app FROM build AS publish RUN dotnet publish DockerServiceDemo.csproj -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "DockerServiceDemo.dll"]
Yang saya lakukan adalah menghapus direktori DockerServiceDemo tambahan.
Jika Anda menggunakan Visual Studio Code, maka Anda harus membuat file secara manual. Meskipun VS Code memiliki fungsionalitas tambahan dalam bentuk ekstensi Docker , saya akan menambahkan tautan ke manual tentang cara bekerja dengan buruh pelabuhan dari VS Code - Bekerja dengan Docker . Ya, artikel ini dalam bahasa Inggris, tetapi dengan gambar
Three Chords Docker
Untuk pekerjaan sehari-hari dengan buruh pelabuhan, hanya beberapa perintah yang cukup untuk diingat.
Tim yang paling penting tentu saja adalah membangun citra. Untuk melakukan ini, Anda perlu menggunakan bash / CMD / PowerShell untuk pergi ke direktori tempat Dockerfile berada dan jalankan perintah:
docker build -t your_image_name .
Di sini, setelah opsi -t, nama gambar Anda diatur. Perhatian - di akhir perintah, spasi setelah spasi. Titik ini berarti bahwa direktori saat ini sedang digunakan. Gambar dapat ditandai dengan tag (nomor atau nama). Untuk melakukan ini, beri tanda titik dua di belakang nama dan tentukan tag. Jika tag tidak ditentukan, maka secara default akan ditetapkan dengan nama terbaru. Untuk mengirim gambar ke repositori, perlu bahwa nama gambar menyertakan nama repositori. Sesuatu seperti ini:
docker build -t docker_account_name/image_name:your_tag .
Di sini your_docker_account_name adalah nama akun hub docker Anda.
Jika Anda membuat gambar hanya dengan nama lokal yang tidak termasuk repositori, maka Anda dapat menandai gambar dengan nama yang berbeda setelah konstruksi menggunakan perintah berikut:
docker tag image_name docker_account_name/image_name:your_tag
Untuk mengirim perubahan ke hub, Anda sekarang harus menjalankan perintah berikut:
docker push docker_account_name/image_name:your_tag
Sebelum ini, Anda harus masuk ke akun buruh pelabuhan. Pada Windows, ini dilakukan dari UI aplikasi, tetapi pada * nix ini dilakukan oleh perintah:
docker login
Padahal, tiga tim tidak cukup. Anda juga harus dapat memeriksa pengoperasian wadah. Perintah yang digunakan untuk memulai wadah terlihat seperti ini:
docker run -it -p 5000:80 image_name
Opsi -itu akan membuat pseudo-TTY dan wadah Anda akan menanggapi permintaan. Setelah menjalankan perintah, layanan akan tersedia di http: // localhost: 5000 /
-p 5000: 80 mengaitkan port 5000 dari wadah dengan port 80 dari host.
Selain itu, ada perintah seperti itu:
docker ps βa
Tunjukkan daftar kontainer. Karena sakelar -a telah ditambahkan, semua wadah akan ditampilkan, bukan hanya yang sedang berjalan.
docker rm container_name
Perintah ini akan menghapus wadah bernama container_name. rm - kependekan untuk menghapus
docker logs container_name
Tampilkan log kontainer
docker rmi image_name
Menghapus gambar bernama image_name
Meluncurkan wadah melalui server proxy terbalik
Faktanya adalah bahwa aplikasi .NET Core sendiri menggunakan server web Kestrel mereka. Server ini tidak direkomendasikan untuk produksi. Mengapa Ada beberapa penjelasan.
Jika ada beberapa aplikasi yang berbagi IP dan port, maka Kestrel tidak akan dapat mendistribusikan lalu lintas. Selain itu, server proxy terbalik memberikan lapisan keamanan tambahan, menyederhanakan penyeimbangan muatan dan pengaturan SSL, dan juga mengintegrasikan lebih baik ke dalam infrastruktur yang ada. Bagi sebagian besar pengembang, alasan paling penting untuk kebutuhan proxy terbalik adalah keamanan tambahan.
Pertama, kembalikan konfigurasi Dockerfile asli. Setelah itu, kita akan berurusan dengan file docker-compose.yml dan mencoba menjalankan layanan kita sendiri. Format file yml dibaca sebagai "yaml" dan merupakan singkatan dari "Yet Another Markup Language" atau dari "YAML Ain't Markup Language". Entah bahasa markup lain, atau bukan bahasa markup sama sekali. Entah bagaimana, semuanya tidak pasti.
File komposisi buruh pelabuhan default saya terlihat seperti ini:
version: '3.4' services: dockerservicedemo: image: ${DOCKER_REGISTRY}dockerservicedemo build: context: . dockerfile: DockerServiceDemo/Dockerfile
File docker-compose.override.yml menambahkan beberapa pengaturan ke konfigurasi:
versi: '3.4'
services: dockerservicedemo: environment: - ASPNETCORE_ENVIRONMENT=Development ports: - "80"
Kita dapat membangun solusi yang dibuat dengan menggunakan docker-compose build, dengan memanggil perintah docker-compose up, kita akan meluncurkan kontainer kita. Apakah semuanya berfungsi? Lalu lanjutkan ke langkah berikutnya. Buat file nginx.info. Konfigurasi akan kira-kira sebagai berikut:
worker_processes 4; events { worker_connections 1024; } http { sendfile on; upstream app_servers { server dockerservicedemo:80; } server { listen 80; location / { proxy_pass http://app_servers; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } }
Di sini kami menunjukkan bahwa nginx akan mendengarkan pada port 80 (dengarkan 80;). Dan permintaan yang diterima akan dialihkan ke port ke-80 dari host di wadah dockerservicedemo. Selain itu, kami memberi tahu nginx header mana yang harus diteruskan.
Kita dapat menggunakan http di nginx, dan mengakses situs web melalui https. Ketika permintaan https melewati proxy http, banyak informasi dari https tidak diteruskan ke http. Selain itu, saat menggunakan proxy, alamat IP eksternal hilang. Agar informasi ini dapat dikirimkan dalam header, Anda perlu mengubah kode proyek ASP.NET kami dan menambahkan kode berikut ke awal metode Konfigurasi file Startup.cs:
app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto });
Sebagian besar server proxy menggunakan header X-Forwarded-For dan X-Forwarded-Proto. Header inilah yang ditentukan sekarang dalam konfigurasi nginx.
Sekarang termasuk gambar nginx dan file nginx.conf dalam konfigurasi doker-compose. Perhatian dalam masalah spasi YAML:
version: '3.4' services: dockerservicedemo: image: ${DOCKER_REGISTRY}dockerservicedemo build: context: . dockerfile: DockerServiceDemo/Dockerfile ports: - 5000:80 proxy: image: nginx:latest volumes: - ./DockerServiceDemo/nginx.conf:/etc/nginx/nginx.conf ports: - 80:80
Di sini kita menambahkan proksi ke konfigurasi kita sebagai gambar nginx. Kami melampirkan gambar ini file pengaturan eksternal. Kami semacam memasangnya ke sistem file wadah menggunakan mekanisme yang disebut volume. Jika Anda menambahkan di akhir: ro maka objek akan dipasang hanya-baca.
Proxy mendengarkan port 80 eksternal dari mesin di mana wadah berjalan dan mengirimkan permintaan ke port 80 internal kontainer.
Dengan menjalankan perintah doker-compose up, kita akan mengisi, yaitu, mengekstrak gambar nginx dari repositori dan mulai wadah kami bersama dengan wadah proxy. Sekarang di http: // localhost: 80 / itu akan dapat diakses melalui nginx. Pada port 5000, aplikasi "spin" juga di bawah Kestrel.
Kami dapat memverifikasi bahwa permintaan ke aplikasi web melewati proksi terbalik. Buka alat pengembang di browser Chrome dan buka tab Network. Klik localhost di sini dan pilih tab Headers.

Kami meluncurkan wadah melalui proxy dan HTTPS
ASP.NET Core 2.1 membawa serta peningkatan dalam dukungan HTTPS.
Katakanlah middleware berikut memungkinkan Anda mengalihkan dari koneksi yang tidak aman ke koneksi yang aman:
app.UseHttpsRedirection();
Dan yang berikutnya memungkinkan Anda menggunakan Protokol Keamanan Transportasi Ketat HTTP - HSTS.
app.UseHsts();
HSTS adalah fitur dari protokol HTTP / 2, spesifikasi yang dirilis pada 2015. Fungsionalitas ini didukung oleh browser modern dan menginformasikan bahwa situs web hanya menggunakan https. Dengan demikian, perlindungan terhadap serangan downgrade terjadi selama penyerang dapat mengambil keuntungan dari situasi dengan menggunakan transisi ke protokol http tidak aman. Misalnya, menurunkan TLS atau bahkan mengganti sertifikat.
Biasanya, tipe serangan ini digunakan bersamaan dengan serangan man-in-the-middle. Anda harus tahu dan ingat bahwa HSTS tidak menyelamatkan Anda dari situasi ketika pengguna mengunjungi situs menggunakan protokol http dan kemudian mengalihkan ke https. Ada daftar preload Chrome yang disebut, yang berisi tautan ke situs yang mendukung https. Peramban lain (Firefox, Opera, Safari, Edge) juga mendukung daftar situs https yang dibuat berdasarkan daftar Chrome. Tetapi semua daftar ini jauh dari semua situs.
Pertama kali Anda menjalankan aplikasi Core pada Windows, Anda akan menerima pesan yang menyatakan bahwa sertifikat pengembang telah dibuat dan diinstal. Dengan mengklik tombol dan menginstal sertifikat, Anda akan membuatnya dipercaya. Dari baris perintah di macOS, Anda dapat menambahkan kepercayaan ke sertifikat menggunakan perintah:
dotnet dev-certs https βtrust
Jika utilitas dev-certs tidak diinstal, Anda dapat menginstalnya dengan perintah:
dotnet tool install --global dotnet-dev-certs
Cara menambahkan sertifikat ke tepercaya di Linux tergantung pada distribusinya.
Untuk tujuan pengujian, kami menggunakan sertifikat pengembang. Tindakan dengan sertifikat yang ditandatangani oleh CA serupa. Jika diinginkan, Anda dapat menggunakan sertifikat LetsEncrypt gratis
Anda dapat mengekspor sertifikat pengembang ke file menggunakan perintah
dotnet dev-certs https -ep ___.pfx
File harus disalin ke direktori% APPDATA% / ASP.NET / Https / di bawah Windows atau ke /root/.aspnet/https/ di bawah macOS / Linux.
Agar wadah untuk mengambil jalur ke sertifikat dan kata sandinya, buat rahasia Pengguna dengan konten berikut:
{ "Kestrel":{ "Certificates":{ "Default":{ "Path": "/root/.aspnet/https/__.pfx", "Password": "___" } } } }
File ini menyimpan data yang tidak terenkripsi dan karena itu digunakan hanya selama pengembangan. File dibuat di Visual Studio dengan memanggil menu konteks pada ikon proyek atau menggunakan utilitas rahasia pengguna di Linux.
Pada Windows, file tersebut akan disimpan dalam direktori% APPDATA% \ Microsoft \ UserSecrets \ <user_secrets_id> \ secrets.json, dan pada MacOS dan Linux file itu akan disimpan di ~ / .microsoft / usersecrets / <user_secrets_id> /secrets.json
Untuk menyimpan pengaturan untuk produksi, beberapa distribusi Linux dapat menggunakan systemd. Pengaturan disimpan di bawah atribut Layanan. Misalnya, seperti ini:
[Service] Environment="Kestrel _ Certificates _ Default _Path=/root/.aspnet/https/__.pfx" Environment="Kestrel _ Certificates _ Default _Password=___"
Selanjutnya, saya akan segera memberikan dan menganalisis versi konfigurasi buruh pelabuhan untuk proksi dan wadah melalui https.
File penyusun Docker:
version: '3.4' services: dockerservicedemo21: image: ${DOCKER_REGISTRY}dockerservicedemo build: context: . dockerfile: DockerServiceDemo/Dockerfile override: version: '3.4' services: dockerservicedemo: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=https://+:44392;http://+:80 - ASPNETCORE_HTTPS_PORT=44392 ports: - "59404:80" - "44392:44392" volumes: - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro proxy: image: nginx:latest volumes: - ./DockerServiceDemo/nginx.conf:/etc/nginx/nginx.conf - ./DockerServiceDemo/cert.crt:/etc/nginx/cert.crt - ./DockerServiceDemo/cert.rsa:/etc/nginx/cert.rsa ports: - "5001:44392"
Sekarang saya akan menggambarkan momen yang tidak bisa dipahami. ASPNETCORE_URLS memungkinkan kita untuk tidak menunjukkan dalam kode aplikasi menggunakan aplikasi. Gunakan port yang sedang didengarkan aplikasi.
ASPNETCORE_HTTPS_PORT melakukan pengalihan serupa dengan apa yang akan dilakukan oleh kode berikut:
services.AddHttpsRedirection (options => options.HttpsPort = 44392)
Artinya, lalu lintas dari permintaan http akan dialihkan ke port permintaan https tertentu.
Menggunakan port ditunjukkan bahwa permintaan dari port eksternal 59404 akan dialihkan ke wadah ke-80, dan dari port eksternal 44392 ke 44392. Secara teoritis, karena kami telah mengonfigurasi server proxy terbalik, kami dapat menghapus port dengan pengalihan ini.
Menggunakan volume, direktori dengan sertifikat pfx dan aplikasi UserSecrets dipasang dengan kata sandi dan tautan ke sertifikat.
Bagian proxy menunjukkan bahwa permintaan dari port eksternal 5001 akan dialihkan ke port nginx ke-44392. Selain itu, file konfigurasi nginx dipasang, serta sertifikat dan kunci sertifikat.
Agar mereka dapat membuat sertifikat pfx tunggal (yang sudah kita miliki) untuk membuat file crt dan rsa, Anda dapat menggunakan OpenSSL. Pertama, Anda perlu mengekstrak sertifikat:
openssl pkcs12 -in ./_.pfx -clcerts -nokeys -out domain.crt
Dan kemudian kunci pribadi:
openssl pkcs12 -in ./_.pfx -nocerts -nodes -out domain.rsa
Konfigurasi nginx adalah sebagai berikut:
worker_processes 4; events { worker_connections 1024; } http { sendfile on; upstream app_servers { server dockerservicedemo:44392; } server { listen 44392 ssl; ssl_certificate /etc/nginx/cert.crt; ssl_certificate_key /etc/nginx/cert.rsa; location / { proxy_pass https://app_servers; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } }
Server proxy sedang mendengarkan pada port 44392. Port ini menerima permintaan dari port host 5001. Selanjutnya, proksi mengalihkan permintaan ke port 44392 dari wadah dockerdemoservice.
Setelah memahami contoh-contoh ini, Anda akan mendapatkan latar belakang yang baik untuk bekerja dengan buruh pelabuhan, layanan microser dan nginx.
Kami mengingatkan Anda bahwa ini adalah versi lengkap dari artikel dari majalah Hacker . Penulisnya adalah Alexey Sommer .