| Kemasan | NuGet |
|---|---|
| Docker Lancar | |
| Tes Microsoft | |
| Tes XUnit |
Pustaka ini memungkinkan interaksi docker dan docker-compose menggunakan API Lancar . Ini didukung di Linux, Windows dan Mac. Ia juga memiliki dukungan untuk interaksi docker-machine pelabuhan yang lama.
Contoh penggunaan API Lancar
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( true ) ;
Assert . AreEqual ( ServiceRunningState . Running , config . State . ToServiceState ( ) ) ;
}Ini menjalankan postgres dan menunggu sampai siap. Untuk menggunakan composer, lakukan saja seperti ini:
CATATAN: Gunakan AssumeComposeVersion(ComposeVersion.V2) untuk menggunakan perilaku V2, defaultnya tetap V1 (akan diubah ke default ke V2 akhir tahun ini)
var file = Path . Combine ( Directory . GetCurrentDirectory ( ) ,
( TemplateString ) "Resources/ComposeTests/WordPress/docker-compose.yml" ) ;
// @formatter:off
using ( var svc = new Builder ( )
. UseContainer ( )
. UseCompose ( )
. FromFile ( file )
. RemoveOrphans ( )
. WaitForHttp ( "wordpress" , "http://localhost:8000/wp-admin/install.php" )
. Build ( ) . Start ( ) )
// @formatter:on
{
// We now have a running WordPress with a MySql database
var installPage = await "http://localhost:8000/wp-admin/install.php" . Wget ( ) ;
Assert . IsTrue ( installPage . IndexOf ( "https://wordpress.org/" , StringComparison . Ordinal ) != - 1 ) ;
Assert . AreEqual ( 1 , svc . Hosts . Count ) ; // The host used by compose
Assert . AreEqual ( 2 , svc . Containers . Count ) ; // We can access each individual container
Assert . AreEqual ( 2 , svc . Images . Count ) ; // And the images used.
}:bulb Catatan untuk Pengguna Linux: Docker memerlukan sudo secara default dan perpustakaan secara default mengharapkan pengguna yang menjalankan tidak perlu melakukan sudo untuk berbicara dengan daemon buruh pelabuhan. Penjelasan lebih lanjut dapat ditemukan di bab Berbicara dengan Docker Daemon .
API yang lancar membangun satu atau lebih layanan. Setiap layanan mungkin gabungan atau tunggal. Oleh karena itu, dimungkinkan untuk menjalankan beberapa layanan berbasis pembuatan buruh pelabuhan dan mengelola masing-masing layanan tersebut sebagai satu layanan atau menggali dan menggunakan semua layanan yang mendasari pada setiap layanan pembuatan buruh pelabuhan . Dimungkinkan juga untuk menggunakan layanan secara langsung misalnya
var file = Path . Combine ( Directory . GetCurrentDirectory ( ) ,
( TemplateString ) "Resources/ComposeTests/WordPress/docker-compose.yml" ) ;
using ( var svc = new DockerComposeCompositeService ( DockerHost , new DockerComposeConfig
{
ComposeFilePath = new List < string > { file } , ForceRecreate = true , RemoveOrphans = true ,
StopOnDispose = true
} ) )
{
svc . Start ( ) ;
// We now have a running WordPress with a MySql database
var installPage = await $ "http://localhost:8000/wp-admin/install.php" . Wget ( ) ;
Assert . IsTrue ( installPage . IndexOf ( "https://wordpress.org/" , StringComparison . Ordinal ) != - 1 ) ;
}Contoh di atas membuat layanan penulisan buruh pelabuhan dari satu file penulisan. Ketika layanan dihentikan, semua layanan yang mendasarinya secara otomatis dihentikan.
Pustaka ini didukung oleh kerangka .NET full 4.51 dan lebih tinggi, .NET standar 1.6, 2.0. Ini dibagi menjadi tiga lapisan tipis, setiap lapisan dapat diakses:
Mayoritas metode layanan adalah metode ekstensi dan tidak tertanam dalam layanan itu sendiri, menjadikannya ringan dan dapat disesuaikan. Karena semuanya dapat diakses, misalnya mudah untuk menambahkan metode ekstensi untuk layanan yang menggunakan perintah lapisan 1 untuk menyediakan fungsionalitas.
Saya menyambut baik kontribusi, meskipun belum ada pedoman kontribusi, pastikan untuk mematuhi .editorconfig saat melakukan Permintaan Tarik. Kalau tidak, pembangunannya akan gagal. Saya akan memperbarui dengan pedoman nyata cepat atau lambat tahun ini.
Semua perintah memerlukan DockerUri untuk digunakan. Ini adalah Uri ke daemon buruh pelabuhan, baik secara lokal atau jarak jauh. Itu dapat ditemukan atau di-hardcode. Penemuan DockerUri lokal dapat dilakukan dengan cara
var hosts = new Hosts ( ) . Discover ( ) ;
var _docker = hosts . FirstOrDefault ( x => x . IsNative ) ?? hosts . FirstOrDefault ( x => x . Name == "default" ) ; Contoh yang diambil akan memeriksa host asli, atau host docker beta "asli", jika tidak memilih mesin docker "default" sebagai host. Jika Anda menggunakan mesin buruh pelabuhan dan tidak ada mesin atau tidak dimulai, mudah untuk membuat/memulai mesin buruh pelabuhan dengan misalnya "test-machine".Create(1024,20000000,1) . Ini akan membuat mesin buruh pelabuhan bernama "mesin uji" dengan RAM 1 GB, Disk 20 GB, dan menggunakan satu CPU.
Sekarang Uri dapat digunakan untuk berkomunikasi menggunakan perintah. Misalnya untuk mendapatkan versi biner buruh pelabuhan klien dan server:
var result = _docker . Host . Version ( _docker . Certificates ) ;
Debug . WriteLine ( result . Data ) ; // Will Print the Client and Server Version and API Versions respectively. Semua perintah mengembalikan CommandResponse sedemikian rupa sehingga memungkinkan untuk memeriksa faktor keberhasilan dengan response.Success . Jika ada data yang terkait dengan perintah, data tersebut dikembalikan di properti response.Data .
Maka sesederhana di bawah ini untuk memulai dan menghentikan termasuk menghapus wadah menggunakan perintah. Di bawah ini memulai sebuah wadah dan melakukan PS di atasnya lalu menghapusnya.
var id = _docker . Host . Run ( "nginx:latest" , null , _docker . Certificates ) . Data ;
var ps = _docker . Host . Ps ( null , _docker . Certificates ) . Data ;
_docker . Host . RemoveContainer ( id , true , true , null , _docker . Certificates ) ; Saat berjalan di windows, seseorang dapat memilih untuk menjalankan linux atau windows container. Gunakan LinuxDaemon atau WindowsDaemon untuk mengontrol daemon mana yang akan diajak bicara.
_docker . LinuxDaemon ( ) ; // ensures that it will talk to linux daemon, if windows daemon it will switch Beberapa perintah mengembalikan aliran data ketika misalnya peristiwa atau log diinginkan menggunakan aliran berkelanjutan. Aliran dapat digunakan dalam tugas latar belakang dan mendukung CancellationToken . Contoh di bawah ini mengikuti log.
using ( var logs = _docker . Host . Logs ( id , _docker . Certificates ) )
{
while ( ! logs . IsFinished )
{
var line = logs . TryRead ( 5000 ) ; // Do a read with timeout
if ( null == line )
{
break ;
}
Debug . WriteLine ( line ) ;
}
}Metode utilitas ada untuk perintah. Mereka datang dalam berbagai bentuk seperti jaringan dll. Misalnya ketika membaca log sampai akhir:
using ( var logs = _docker . Host . Logs ( id , _docker . Certificates ) )
{
foreach ( var line in logs . ReadToEnd ( ) )
{
Debug . WriteLine ( line ) ;
}
} Lapisan tertinggi perpustakaan ini adalah API lancar tempat Anda dapat menentukan dan mengontrol mesin, gambar, dan kontainer. Misalnya untuk menyiapkan penyeimbang beban dengan dua server nodejs yang membaca dari server redis dapat terlihat seperti ini (gambar node dibuat khusus jika tidak ditemukan di repositori).
var fullPath = ( TemplateString ) @"${TEMP}/fluentdockertest/${RND}" ;
var nginx = Path . Combine ( fullPath , "nginx.conf" ) ;
Directory . CreateDirectory ( fullPath ) ;
typeof ( NsResolver ) . ResourceExtract ( fullPath , "index.js" ) ;
using ( var services = new Builder ( )
// Define custom node image to be used
. DefineImage ( "mariotoffia/nodetest" ) . ReuseIfAlreadyExists ( )
. From ( "ubuntu" )
. Maintainer ( "Mario Toffia <[email protected]>" )
. Run ( "apt-get update &&" ,
"apt-get -y install curl &&" ,
"curl -sL https://deb.nodesource.com/setup | sudo bash - &&" ,
"apt-get -y install python build-essential nodejs" )
. Run ( "npm install -g nodemon" )
. Add ( "emb:Ductus.FluentDockerTest/Ductus.FluentDockerTest.MultiContainerTestFiles/package.txt" ,
"/tmp/package.json" )
. Run ( "cd /tmp && npm install" )
. Run ( "mkdir -p /src && cp -a /tmp/node_modules /src/" )
. UseWorkDir ( "/src" )
. Add ( "index.js" , "/src" )
. ExposePorts ( 8080 )
. Command ( "nodemon" , "/src/index.js" ) . Builder ( )
// Redis Db Backend
. UseContainer ( ) . WithName ( "redis" ) . UseImage ( "redis" ) . Builder ( )
// Node server 1 & 2
. UseContainer ( ) . WithName ( "node1" ) . UseImage ( "mariotoffia/nodetest" ) . Link ( "redis" ) . Builder ( )
. UseContainer ( ) . WithName ( "node2" ) . UseImage ( "mariotoffia/nodetest" ) . Link ( "redis" ) . Builder ( )
// Nginx as load balancer
. UseContainer ( ) . WithName ( "nginx" ) . UseImage ( "nginx" ) . Link ( "node1" , "node2" )
. CopyOnStart ( nginx , "/etc/nginx/nginx.conf" )
. ExposePort ( 80 ) . Builder ( )
. Build ( ) . Start ( ) )
{
Assert . AreEqual ( 4 , services . Containers . Count ) ;
var ep = services . Containers . First ( x => x . Name == "nginx" ) . ToHostExposedEndpoint ( "80/tcp" ) ;
Assert . IsNotNull ( ep ) ;
var round1 = $ "http:// { ep . Address } : { ep . Port } " . Wget ( ) ;
Assert . AreEqual ( "This page has been viewed 1 times!" , round1 ) ;
var round2 = $ "http:// { ep . Address } : { ep . Port } " . Wget ( ) ;
Assert . AreEqual ( "This page has been viewed 2 times!" , round2 ) ;
}Contoh di atas mendefinisikan Dockerfile , membangunnya, untuk gambar node. Kemudian menggunakan vanilla redis dan nginx. Jika Anda hanya ingin menggunakan Dockerfile yang sudah ada, caranya bisa seperti ini.
using ( var services = new Builder ( )
. DefineImage ( "mariotoffia/nodetest" ) . ReuseIfAlreadyExists ( )
. FromFile ( "/tmp/Dockerfile" )
. Build ( ) . Start ( ) )
{
// Container either build to reused if found in registry and started here.
} API yang lancar mendukung mulai dari mendefinisikan mesin buruh pelabuhan hingga sekumpulan instance buruh pelabuhan. Ia memiliki dukungan bawaan untuk misalnya menunggu port tertentu atau proses dalam wadah sebelum Build() selesai dan dengan demikian dapat digunakan dengan aman dalam pernyataan penggunaan. Jika manajemen khusus tentang waktu tunggu habis, dll. Anda selalu dapat membangun dan memulai penampung dan menggunakan metode ekstensi untuk melakukan penantian pada penampung itu sendiri.
Untuk membuat wadah, hilangkan saja bagian awal. Misalnya:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( ) )
{
Assert . AreEqual ( ServiceRunningState . Stopped , container . State ) ;
} Contoh ini membuat wadah dengan postgres, konfigurasikan satu variabel lingkungan. Dalam pernyataan penggunaan dimungkinkan untuk memulai IContainerService . Jadi, setiap kontainer yang dibangun dibungkus dengan IContainerService . Dimungkinkan juga untuk menggunakan IHostService.GetContainers(...) untuk mendapatkan kontainer yang dibuat, dijalankan, dan keluar. Dari IHostService juga dimungkinkan untuk mendapatkan semua gambar di repositori lokal untuk membuat kontainer.
Jika Anda ingin menjalankan satu container, gunakan metode mulai layanan fasih atau container. Misalnya:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( ) ;
Assert . AreEqual ( ServiceRunningState . Running , container . State ) ;
Assert . IsTrue ( config . Config . Env . Any ( x => x == "POSTGRES_PASSWORD=mysecretpassword" ) ) ;
} Secara default, kontainer dihentikan dan dihapus ketika metode Buang dijalankan, untuk menjaga kontainer tetap dalam arsip, gunakan KeepContainer() pada API yang lancar. Ketika Dispose() dipanggil maka akan dihentikan tetapi tidak dihapus. Dimungkinkan juga untuk tetap menjalankannya setelah dibuang.
Port dapat diekspos secara eksplisit atau acak. Apa pun yang terjadi, dimungkinkan untuk menyelesaikan IP (jika mesin) dan port (jika port acak) untuk digunakan dalam kode. Misalnya:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 40001 , 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( ) )
{
var endpoint = container . ToHostExposedEndpoint ( "5432/tcp" ) ;
Assert . AreEqual ( 40001 , endpoint . Port ) ;
} Di sini kami memetakan port kontainer 5432 ke port host 40001 secara eksplisit. Perhatikan penggunaan container.ToHostExposedEndpoint(...) . Ini untuk selalu menentukan ip dan port yang berfungsi untuk berkomunikasi dengan kontainer buruh pelabuhan. Dimungkinkan juga untuk memetakan port acak, yaitu membiarkan Docker memilih port yang tersedia. Misalnya:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( ) )
{
var endpoint = container . ToHostExposedEndpoint ( "5432/tcp" ) ;
Assert . AreNotEqual ( 0 , endpoint . Port ) ;
} Satu-satunya perbedaan di sini adalah hanya satu argumen yang digunakan ketika ExposePort(...) digunakan untuk mengonfigurasi kontainer. Penggunaan yang sama berlaku sebaliknya dan dengan demikian transparan untuk kodenya.
Untuk mengetahui kapan layanan tertentu aktif dan berjalan sebelum mulai, misalnya menyambungkannya. Dimungkinkan untuk menunggu port tertentu terbuka. Misalnya:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( true ) ;
Assert . AreEqual ( ServiceRunningState . Running , config . State . ToServiceState ( ) ) ;
}Pada contoh di atas kita menunggu port container 5432 dibuka dalam waktu 30 detik. Jika gagal, ia akan mengeluarkan pengecualian dan dengan demikian kontainer akan dibuang dan dihapus (karena kita tidak memiliki konfigurasi simpan kontainer dll.).
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ , "127.0.0.1" )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( true ) ;
Assert . AreEqual ( ServiceRunningState . Running , config . State . ToServiceState ( ) ) ;
}Kadang-kadang tidak mungkin untuk mencapai kontainer secara langsung, dengan ip dan port lokal, misalnya kontainer memiliki port yang terbuka pada antarmuka loopback ( 127.0.0.1 ) dan itulah satu-satunya cara untuk mencapai kontainer dari program. Contoh di atas memaksa alamatnya menjadi 127.0.0.1 tetapi masih menyelesaikan port host. Secara default, FluentDocker menggunakan pemeriksaan jaringan pada kontainer untuk menentukan konfigurasi jaringan.
Terkadang tidak cukup hanya menunggu port. Terkadang proses container jauh lebih penting untuk ditunggu. Oleh karena itu, metode menunggu proses ada di API lancar serta metode ekstensi pada objek kontainer. Misalnya:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForProcess ( "postgres" , 30000 /*30s*/ )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( true ) ;
Assert . AreEqual ( ServiceRunningState . Running , config . State . ToServiceState ( ) ) ;
} Dalam contoh di atas, Build() akan mengembalikan kontrol ketika proses "postgres" telah dimulai di dalam container.
Untuk memanfaatkan container, terkadang perlu memasang volume di container ke host atau cukup menyalin dari atau ke container. Bergantung pada apakah Anda menjalankan mesin atau buruh pelabuhan, pemetaan volume secara asli memiliki batasan bahwa pemetaan tersebut harus dapat dijangkau dari mesin virtual.
Kasus penggunaan normal adalah misalnya server web menyajikan konten pada wadah buruh pelabuhan dan pengguna mengedit file pada sistem file host. Dalam skenario seperti itu, perlu untuk memasang volume kontainer buruh pelabuhan ke host. Misalnya:
const string html = "<html><head>Hello World</head><body><h1>Hello world</h1></body></html>" ;
var hostPath = ( TemplateString ) @"${TEMP}/fluentdockertest/${RND}" ;
Directory . CreateDirectory ( hostPath ) ;
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "nginx:latest" )
. ExposePort ( 80 )
. Mount ( hostPath , "/usr/share/nginx/html" , MountType . ReadOnly )
. Build ( )
. Start ( )
. WaitForPort ( "80/tcp" , 30000 /*30s*/ ) )
{
File . WriteAllText ( Path . Combine ( hostPath , "hello.html" ) , html ) ;
var response = $ "http:// { container . ToHostExposedEndpoint ( "80/tcp" ) } /hello.html" . Wget ( ) ;
Assert . AreEqual ( html , response ) ;
}Dalam contoh di atas, container nginx dimulai dan dipasang '/usr/share/nginx/html' ke jalur host (acak, dalam direktori sementara). File HTML disalin ke jalur host dan ketika proses HTTP menuju wadah buruh pelabuhan nginx selesai, file yang sama akan disajikan.
Terkadang perlu menyalin file ke dan dari sebuah wadah. Misalnya menyalin file konfigurasi, mengkonfigurasinya dan menyalinnya kembali. Skenario yang lebih umum adalah menyalin file konfigurasi ke kontainer, tepat sebelum dimulai. Contoh multi container menyalin file konfigurasi nginx sebelum dimulai. Dengan demikian, dimungkinkan untuk menghindari pembuatan Dockerfile dan image secara manual untuk tugas sederhana seperti itu. Alih-alih gunakan saja misalnya gambar resmi atau khusus, salin konfigurasi dan jalankan.
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( )
. CopyFrom ( "/etc/conf.d" , fullPath ) )
{
var files = Directory . EnumerateFiles ( Path . Combine ( fullPath , "conf.d" ) ) . ToArray ( ) ;
Assert . IsTrue ( files . Any ( x => x . EndsWith ( "pg-restore" ) ) ) ;
Assert . IsTrue ( files . Any ( x => x . EndsWith ( "postgresql" ) ) ) ;
}Contoh di atas menyalin direktori ke jalur host (fullPath) dari container yang sedang berjalan. Perhatikan penggunaan metode ekstensi di sini, sehingga tidak menggunakan API yang lancar (karena CopyFrom setelah Start()). Jika Anda ingin menyalin file dari container sebelum memulai, gunakan Fluent API sebagai gantinya.
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. CopyOnStart ( "/etc/conf.d" , fullPath )
. Build ( )
. Start ( ) )
{
}Contoh di bawah mengilustrasikan skenario yang lebih umum ketika file disalin ke kontainer. Contoh ini menggunakan metode ekstensi alih-alih versi API yang lancar. Dibutuhkan snapshot Diff sebelum penyalinan dan kemudian setelah penyalinan. Yang terakhir hello.html hadir.
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( )
. WaitForProcess ( "postgres" , 30000 /*30s*/ )
. Diff ( out before )
. CopyTo ( "/bin" , fullPath ) )
{
var after = container . Diff ( ) ;
Assert . IsFalse ( before . Any ( x => x . Item == "/bin/hello.html" ) ) ;
Assert . IsTrue ( after . Any ( x => x . Item == "/bin/hello.html" ) ) ;
} Terkadang berguna untuk menyalin file di IContainerService.Dispose() (tepat sebelum container berhenti). Oleh karena itu, ada API yang lancar untuk memastikan bahwa ia dapat melakukan hal tersebut.
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. CopyOnDispose ( "/etc/conf.d" , fullPath )
. Build ( )
. Start ( ) )
{
} Untuk menganalisis suatu wadah, ada metode ekstensi ekspor dan metode API yang lancar. Yang paling menonjol adalah kemungkinan untuk mengekspor kontainer ketika IContainerService dibuang.
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExportOnDispose ( fullPath )
. Build ( )
. Start ( ) )
{
} Ini akan menghasilkan ekspor kontainer (file tar) di host (fullPath). Jika Anda lebih suka meledakkannya (tidak ditar) gunakan metode ExportExplodedOnDispose sebagai gantinya. Tentu saja Anda dapat mengekspor container kapan saja menggunakan metode ekstensi pada container tersebut.
Trik yang berguna dalam pengujian unit adalah dengan mengekspor status kontainer ketika pengujian unit gagal karena alasan tertentu, oleh karena itu terdapat API Lancar yang akan mengekspor ketika kondisi Lambda tertentu terpenuhi. Misalnya:
var failure = false ;
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExportOnDispose ( fullPath , svc => failure )
. Build ( )
. Start ( ) )
{
failure = true ;
} Cuplikan ini akan mengekspor kontainer ketika pernyataan penggunaan membuang kontainer karena variabel kegagalan disetel ke true dan digunakan dalam ekspresi ExportOnDispose .
Semua layanan dapat diperluas dengan pengait. Di ExportOnDispose(path, lambda) memasang Hook ketika status layanan diatur untuk mengeksekusi lambda ketika statusnya adalah Removing . Anda dapat memasang dan melepas kait dengan cepat. Jika beberapa hook didaftarkan pada instance layanan yang sama, dengan ServiceRunningState yang sama, hook tersebut akan dieksekusi sesuai urutan instalasi.
Kaitnya sangat bagus jika Anda ingin sesuatu dieksekusi ketika suatu keadaan akan ditetapkan (atau dieksekusi) pada layanan seperti Starting . Fluent API memanfaatkannya dalam beberapa situasi seperti Menyalin file, mengekspor, dll.
FluentDocker mendukung semua perintah jaringan buruh pelabuhan. Ia dapat menemukan jaringan dengan _docker.NetworkLs() di mana ia menemukan semua jaringan dan beberapa parameter sederhana yang ditentukan dalam NetworkRow . Itu juga dapat memeriksa untuk mendapatkan informasi lebih dalam tentang jaringan (seperti kontainer mana yang ada di jaringan dan konfigurasi Ipam) dengan _docker.NetworkInspect(network:"networkId") .
Untuk membuat jaringan baru, gunakan _docker.NetworkCreate("name_of_network") . Dimungkinkan juga untuk menyediakan NetworkCreateParams di mana semuanya dapat disesuaikan seperti membuat jaringan overlay dan mengubah konfigurasi Ipam. Untuk menghapus jaringan, cukup gunakan _docker.NetworkRm(network:"networkId") .
Perhatikan bahwa jaringan tidak dihapus jika ada wadah yang melekat padanya!
Saat jaringan dibuat, dimungkinkan untuk memasukkan satu atau lebih container ke dalamnya menggunakan _docker.NetworkConnect("containerId","networkId") . Perhatikan bahwa kontainer mungkin berada di beberapa jaringan sekaligus, sehingga dapat melakukan permintaan proksi antar jaringan yang terisolasi. Untuk memutuskan sambungan kontainer dari jaringan, cukup lakukan _docker.NetworkDisconnect("containerId","networkId") .
Contoh berikut menjalankan container, membuat jaringan baru, dan menghubungkan container yang sedang berjalan ke dalam jaringan. Kemudian putuskan sambungan wadah, hapus, dan hapus jaringan.
var cmd = _docker . Run ( "postgres:9.6-alpine" , new ContainerCreateParams
{
PortMappings = new [ ] { "40001:5432" } ,
Environment = new [ ] { "POSTGRES_PASSWORD=mysecretpassword" }
} , _certificates ) ;
var container = cmd . Data ;
var network = string . Empty ;
var created = _docker . NetworkCreate ( "test-network" ) ;
if ( created . Success )
network = created . Data [ 0 ] ;
_docker . NetworkConnect ( container , network ) ;
// Container is now running and has address in the newly created 'test-network'
_docker . NetworkDisconnect ( container , id , true /*force*/ ) ;
_docker . RemoveContainer ( container , true , true ) ;
// Now it is possible to delete the network since it has been disconnected from the network
_docker . NetworkRm ( network : network ) ;Dimungkinkan juga untuk menggunakan pembuat yang fasih untuk membangun jaringan buruh pelabuhan baru atau menggunakan kembali yang sudah ada. Hal tersebut kemudian dapat direferensikan saat membuat container . Dimungkinkan untuk membangun lebih dari satu jaringan buruh pelabuhan dan melampirkan sebuah container ke lebih dari satu jaringan secara bersamaan.
using ( var nw = new Builder ( ) . UseNetwork ( "test-network" ) )
{
using (
var container =
new DockerBuilder ( )
. WithImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExposePorts ( "5432" )
. UseNetwork ( nw )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( ) )
{
container . Create ( ) . Start ( ) ;
}
} Cuplikan kode di atas membuat jaringan baru bernama test-network dan kemudian membuat container yang dilampirkan ke test-network . Saat Dispose() dipanggil di nw, jaringan akan dihapus. Dimungkinkan juga untuk melakukan penetapan kontainer IP statis dalam jaringan dengan UseIpV4 atau UseIpV6 . Misalnya:
using ( var nw = Fd . UseNetwork ( "unit-test-nw" )
. UseSubnet ( "10.18.0.0/16" ) . Build ( ) )
{
using (
var container =
Fd . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExposePort ( 5432 )
. UseNetwork ( nw )
. UseIpV4 ( "10.18.0.22" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( )
. Start ( ) )
{
var ip = container . GetConfiguration ( ) . NetworkSettings . Networks [ "unit-test-nw" ] . IPAddress ;
Assert . AreEqual ( "10.18.0.22" , ip ) ;
}
} Contoh di atas membuat jaringan baru unit-test-nw dengan ip-range 10.18.0.0/16 . Itu digunakan dalam wadah baru. IP untuk kontainer diatur ke 10.18.0.22 dan bersifat statis karena perintah UseIpV4 .
FluentDocker mendukung manajemen volume buruh pelabuhan baik dari perintah maupun dari API yang lancar. Oleh karena itu dimungkinkan untuk memiliki kendali penuh atas volume yang digunakan dalam wadah seperti apakah wadah tersebut harus dibuang, digunakan kembali, bahan apa yang digunakan, dll.
var volume = _docker . VolumeCreate ( "test-volume" , "local" , opts : {
{ "type" , "nfs" } ,
{ "o=addr" , "192.168.1.1,rw" } ,
{ "device" , ":/path/to/dir" }
} ) ;
var cfg = _docker . VolumeInspect ( _certificates , "test-volume" ) ;
_docker . VolumeRm ( force : true , id : "test-volume" ) ;Cuplikan di atas membuat volume baru dengan nama test-volume dan bertipe NFS . Ia kemudian memeriksa volume yang baru saja dibuat dan terakhir menghapus paksa volume tersebut.
Dimungkinkan juga untuk menggunakan API yang lancar untuk membuat atau menggunakan volume. Mereka kemudian dapat digunakan saat membuat wadah. Hal ini sangat berguna ketika pembuatan volume bersifat khusus atau kebutuhan seumur hidup harus dikontrol.
using ( var vol = new Builder ( ) . UseVolume ( "test-volume" ) . RemoveOnDispose ( ) . Build ( ) )
{
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. MountVolume ( vol , "/var/lib/postgresql/data" , MountType . ReadWrite )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( ) ;
Assert . AreEqual ( 1 , config . Mounts . Length ) ;
Assert . AreEqual ( "test-volume" , config . Mounts [ 0 ] . Name ) ;
}
} Contoh di atas membuat volume baru yang disebut test-volume dan dijadwalkan untuk dihapus ketika Dispose() dipanggil pada IVolumeService . Kontainer dibuat dan memasang volume yang baru dibuat ke /var/lib/postgresql/data sebagai mode akses baca/tulis . Karena kontainer berada dalam cakupan pernyataan using volume, masa pakainya mencakup seluruh masa pakai kontainer dan kemudian dihapus.
FluentDocker mendukung, menghubungkan ke mekanisme peristiwa buruh pelabuhan untuk mendengarkan peristiwa yang dikirimkannya.
using ( var events = Fd . Native ( ) . Events ( ) )
{
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( )
. Start ( ) )
{
FdEvent e ;
while ( ( e = events . TryRead ( 3000 ) ) != null )
{
if ( e . Type == EventType . Container && e . Action == EventAction . Start )
break ;
}
}
} Pendengar peristiwa bersifat global dan dapat menangani banyak jenis EventAction .
Misalnya
Bergantung pada tindakan, jenis peristiwa mungkin berbeda seperti ContainerKillEvent untuk EventAction.Kill . Semua acara berasal dari FdEvent . Itu berarti semua properti bersama ada di acara dasar dan properti eksplisit ada di acara turunan.
Misalnya, ´ContainerKillEvent` berisi properti berikut:
public sealed class ContainerKillActor : EventActor
{
/// <summary>
/// The image name and label such as "alpine:latest".
/// </summary>
public string Image { get ; set ; }
/// <summary>
/// Name of the container.
/// </summary>
public string Name { get ; set ; }
/// <summary>
/// The signal that the container has been signalled.
/// </summary>
public string Signal { get ; set ; }
} Perulangan peristiwa ini dapat digunakan untuk mengambil peristiwa dan menggerakkan instans IService yang Anda buat. Atau jika Anda perlu bereaksi misalnya jaringan ditambahkan atau dihapus.
Dalam kerangka lengkapnya menggunakan logging verbose menggunakan System.Diagnostics.Debugger.Log . Untuk .net core menggunakan standar Microsoft.Extensions.Logging.ILog untuk mencatat. Keduanya menggunakan kategori Ductus.FluentDocker dan oleh karena itu dapat dikonfigurasi untuk berpartisipasi dalam logging atau tidak dan mengkonfigurasi tujuan logging yang berbeda.
Di .net core Anda dapat menyediakan segmen logging di file konfigurasi aplikasi.
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Ductus.FluentDocker": "None"
}
}
}
Silakan periksa https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1 untuk informasi lebih lanjut. Untuk kerangka lengkap, silakan periksa XML yang diperlukan di appconfig untuk kerangka lengkap yang dijelaskan di https://docs.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/configuring-tracing.
Ada cara cepat untuk menonaktifkan/mengaktifkan logging melalui ( Ductus.FluentDocker.Services ) Logging.Enabled() atau Logging.Disabled() . Ini akan mengaktifkan/menonaktifkan logging secara paksa.
Dimungkinkan untuk mengganti mekanisme default FluentDocker yang menyelesaikan IP kontainer dari perspektif klien misalnya WaitForPort . Ini dapat diganti berdasarkan ContainerBuilder .
Contoh di bawah ini, menggantikan perilaku default . Ketika ia mengembalikan null penyelesai default akan aktif.
using (
var container =
Fd . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExposePort ( 5432 )
. UseCustomResolver ( (
ports , portAndProto , dockerUri ) =>
{
if ( null == ports || string . IsNullOrEmpty ( portAndProto ) )
return null ;
if ( ! ports . TryGetValue ( portAndProto , out var endpoints ) )
return null ;
if ( null == endpoints || endpoints . Length == 0 )
return null ;
if ( CommandExtensions . IsNative ( ) )
return endpoints [ 0 ] ;
if ( CommandExtensions . IsEmulatedNative ( ) )
return CommandExtensions . IsDockerDnsAvailable ( )
? new IPEndPoint ( CommandExtensions . EmulatedNativeAddress ( ) , endpoints [ 0 ] . Port )
: new IPEndPoint ( IPAddress . Loopback , endpoints [ 0 ] . Port ) ;
if ( Equals ( endpoints [ 0 ] . Address , IPAddress . Any ) && null != dockerUri )
return new IPEndPoint ( IPAddress . Parse ( dockerUri . Host ) , endpoints [ 0 ] . Port ) ;
return endpoints [ 0 ] ;
} )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( )
. Start ( ) )
{
var state = container . GetConfiguration ( true /*force*/ ) . State . ToServiceState ( ) ;
Assert . AreEqual ( ServiceRunningState . Running , state ) ;
} Ada dukungan terbatas untuk menggunakan FluentAPI untuk berkomunikasi dengan daemon buruh pelabuhan jarak jauh tanpa menggunakan mesin buruh pelabuhan. Hal ini dilakukan dengan membuat instance DockerHostService secara manual atau menggunakan FromUri di HostBuilder .
using ( var container = Fd . UseHost ( ) .
FromUri ( Settings . DockerUri , isWindowsHost : true ) .
UseContainer ( ) .
Build ( ) )
{
} Contoh di atas terhubung ke DockerUri kustom dari pengaturan dan merupakan daemon docker container windows.
FromUri yang menggunakan DockerUri untuk membuat IHostService . Uri ini sewenang-wenang. Ini juga mendukung properti lainnya ( lihat di bawah ). public HostBuilder FromUri (
DockerUri uri ,
string name = null ,
bool isNative = true ,
bool stopWhenDisposed = false ,
bool isWindowsHost = false ,
string certificatePath = null ) { /*...*/ }Ini akan menggunakan default "masuk akal" pada semua parameter. Dalam kebanyakan kasus, uri sudah mencukupi. Misalnya jika tidak menyediakan CertificatePath, ia akan mencoba mendapatkannya dari lingkungan DOCKER_CERT_PATH . Jika tidak ditemukan di lingkungan, defaultnya adalah tidak ada.
UseHost yang menggunakan implementasi IHostService yang dipakai. Pustaka mendukung penulisan buruh pelabuhan untuk menggunakan file penulisan yang ada guna merender layanan dan mengelola masa pakainya.
Contoh berikut akan memiliki file penulisan yang menjalankan MySql dan WordPress . Oleh karena itu, layanan penulisan tunggal akan memiliki dua layanan kontainer di bawahnya. Secara default, ini akan menghentikan layanan dan membersihkan ketika Dispose() dipanggil. Ini dapat ditimpa oleh KeepContainers() dalam konfigurasi yang lancar .
version : ' 3.3 '
services :
db :
image : mysql:5.7
volumes :
- db_data:/var/lib/mysql
restart : always
environment :
MYSQL_ROOT_PASSWORD : somewordpress
MYSQL_DATABASE : wordpress
MYSQL_USER : wordpress
MYSQL_PASSWORD : wordpress
wordpress :
depends_on :
- db
image : wordpress:latest
ports :
- " 8000:80 "
restart : always
environment :
WORDPRESS_DB_HOST : db:3306
WORDPRESS_DB_USER : wordpress
WORDPRESS_DB_PASSWORD : wordpress
volumes :
db_data :File di atas adalah file pembuatan buruh pelabuhan untuk menggabungkan layanan lengkap.
var file = Path . Combine ( Directory . GetCurrentDirectory ( ) ,
( TemplateString ) "Resources/ComposeTests/WordPress/docker-compose.yml" ) ;
using ( var svc = new Builder ( )
. UseContainer ( )
. UseCompose ( )
. FromFile ( file )
. RemoveOrphans ( )
. Build ( ) . Start ( ) )
{
var installPage = await "http://localhost:8000/wp-admin/install.php" . Wget ( ) ;
Assert . IsTrue ( installPage . IndexOf ( "https://wordpress.org/" , StringComparison . Ordinal ) != - 1 ) ;
Assert . AreEqual ( 1 , svc . Hosts . Count ) ;
Assert . AreEqual ( 2 , svc . Containers . Count ) ;
Assert . AreEqual ( 2 , svc . Images . Count ) ;
Assert . AreEqual ( 5 , svc . Services . Count ) ;
}Cuplikan di atas dengan lancar mengonfigurasi layanan penulisan buruh pelabuhan dan memanggil halaman instalasi untuk memverifikasi bahwa WordPress memang berfungsi.
Dimungkinkan juga untuk melakukan semua operasi yang didukung oleh satu kontainer seperti operasi salin, ekspor, tunggu. Misalnya:
var file = Path . Combine ( Directory . GetCurrentDirectory ( ) ,
( TemplateString ) "Resources/ComposeTests/WordPress/docker-compose.yml" ) ;
// @formatter:off
using ( new Builder ( )
. UseContainer ( )
. UseCompose ( )
. FromFile ( file )
. RemoveOrphans ( )
. WaitForHttp ( "wordpress" , "http://localhost:8000/wp-admin/install.php" , continuation : ( resp , cnt ) =>
resp . Body . IndexOf ( "https://wordpress.org/" , StringComparison . Ordinal ) != - 1 ? 0 : 500 )
. Build ( ) . Start ( ) )
// @formatter:on
{
// Since we have waited - this shall now always work.
var installPage = await "http://localhost:8000/wp-admin/install.php" . Wget ( ) ;
Assert . IsTrue ( installPage . IndexOf ( "https://wordpress.org/" , StringComparison . Ordinal ) != - 1 ) ;
} Cuplikan di atas menjalankan proyek pembuatan buruh pelabuhan wordpress dan memeriksa URL http://localhost:8000/wp-admin/install.php dan mengembalikan nilai tertentu di badan (dalam hal ini "https://wordpress.org /"). Jika tidak, ia akan mengembalikan 500 dan fungsi WaitForHttp akan menunggu 500 milidetik sebelum dipanggil lagi. Ini juga berfungsi untuk lambda khusus apa pun, cukup gunakan WaitFor saja. Jadi, misalnya saja dimungkinkan untuk menanyakan database sebelum melanjutkan ke dalam lingkup penggunaan.
Untuk pengguna Linux dan Mac ada beberapa opsi cara mengautentikasi ke soket. FluentDocker tidak mendukung sudo , sudo tanpa kata sandi apa pun (pengguna ditambahkan sebagai NOPASSWD di /etc/sudoer), atau sudo dengan kata sandi. Standarnya adalah FluentDocker mengharapkan dapat berbicara tanpa sudo apa pun. Opsinya bersifat global tetapi dapat diubah saat runtime.
SudoMechanism . None . SetSudo ( ) ; // This is the default
SudoMechanism . Password . SetSudo ( "<my-sudo-password>" ) ;
SudoMechanism . NoPassword . SetSudo ( ) ;Jika Anda ingin mematikan sudo untuk berkomunikasi dengan daemon buruh pelabuhan, Anda dapat mengikuti tutorial buruh pelabuhan dan melakukan langkah terakhir dengan menambahkan pengguna Anda ke grup buruh pelabuhan.
FluentDocker mendukung koneksi ke daemon buruh pelabuhan jarak jauh. Dukungan API yang lancar, misalnya
new Builder ( ) . UseHost ( ) . UseMachine ( ) . WithName ( "remote-daemon" )di mana ini memerlukan entri yang sudah disiapkan sebelumnya di registri mesin buruh pelabuhan . Dimungkinkan juga untuk menentukan keseluruhan registri mesin buruh pelabuhan berbasis SSH untuk terhubung ke daemon jarak jauh.
using (
var container =
new Builder ( ) . UseHost ( )
. UseSsh ( "192.168.1.27" ) . WithName ( "remote-daemon" )
. WithSshUser ( "solo" ) . WithSshKeyPath ( "${E_LOCALAPPDATA}/lxss/home/martoffi/.ssh/id_rsa" )
. UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( ) )
{
Assert . AreEqual ( ServiceRunningState . Stopped , container . State ) ;
}Contoh ini akan membuat entri registri mesin buruh pelabuhan baru bernama daemon jarak jauh yang menggunakan SSH dengan alamat ip 192.168.1.27 dan pengguna SSH solo . Jika entri bernama daemon jarak jauh sudah ditemukan, entri ini hanya akan digunakan kembali. Kemudian ia mendapat IHostService dengan sertifikat dan URL yang benar untuk daemon jarak jauh. Dengan demikian, dimungkinkan untuk membuat wadah buruh pelabuhan pada daemon jarak jauh, dalam hal ini adalah gambar postgres . Saat ia membuang containernya, seperti biasa ia menghapusnya dari buruh pelabuhan jarak jauh. IHostService pastikan untuk mengambil semua sertifikat yang diperlukan untuk mengautentikasi koneksi.
Contoh di atas menghasilkan entri registri mesin buruh pelabuhan ini.
C:Usersmartoffi>docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
remote-daemon * generic Running tcp://192.168.1.27:2376 v18.06.1-ce
Untuk menggunakan UseSsh(...) terowongan SSH tanpa kata sandi harus disiapkan. Selain itu pengguna yang menggunakan terowongan harus diizinkan mengakses daemon buruh pelabuhan.
Ikuti tutorial berikut cara menyiapkan terowongan SSH dan pastikan pengguna dapat mengakses daemon buruh pelabuhan.
Pada dasarnya buat kunci rsa baru untuk digunakan dengan terowongan SSH menggunakan ssh-keygen -t rsa dan kemudian salin ke host jarak jauh dengan ssh-copy-id {username}@{host} .
Edit /etc/sudoers seperti yang ditentukan dalam tutorial kedua.
Ketika ini selesai, Anda sekarang dapat mengakses daemon buruh pelabuhan jarak jauh dengan driver generik atau API lancar yang ditentukan di atas. Untuk melakukan hal yang sama secara manual seperti yang ditentukan dalam contoh, tampilannya akan seperti ini.
C:Usersmartoffi>docker-machine.exe create --driver generic --generic-ip-address=192.168.1.27 --generic-ssh-key="%localappdata%/lxss/home/martoffi/.ssh/id_rsa" --generic-ssh-user=solo remote-daemon
Running pre-create checks...
Creating machine...
(remote-daemon) Importing SSH key...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine.exe env remote-daemon
Sekarang entri registri dibuat, dimungkinkan untuk mengatur lingkungan untuk buruh pelabuhan terminal.
C:Usersmartoffi>docker-machine.exe env remote-daemon
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.1.24:2376
SET DOCKER_CERT_PATH=C:Usersmartoffi.dockermachinemachinesremote-daemon
SET DOCKER_MACHINE_NAME=remote-daemon
SET COMPOSE_CONVERT_WINDOWS_PATHS=true
REM Run this command to configure your shell:
REM @FOR /f "tokens=*" %i IN ('docker-machine.exe env remote-daemon') DO @%i
Jalankan ini untuk membuat klien buruh pelabuhan menggunakan daemon buruh pelabuhan jarak jauh.
@FOR /f "tokens=*" %i IN ('docker-machine.exe env remote-daemon') DO @%i
Semua perintah yang menggunakan biner docker sekarang akan dijalankan pada daemon buruh pelabuhan jarak jauh.
Saat membuat dan membuat kueri, melalui mesin, mesin buruh pelabuhan hyper-v, prosesnya perlu ditingkatkan karena Hyper-V tidak akan merespons panggilan API dalam mode pengguna standar.
Dimungkinkan untuk menentukan pemeriksaan kesehatan bagi kontainer buruh pelabuhan untuk melaporkan status kontainer berdasarkan aktivitas tersebut. Contoh berikut menggunakan health check apakah container sudah keluar atau belum. Dimungkinkan untuk memeriksa konfigurasi (pastikan untuk memaksa penyegaran) status apa yang dilaporkan oleh pemeriksaan kesehatan.
using (
var container =
Fd . UseContainer ( )
. UseImage ( "postgres:latest" , force : true )
. HealthCheck ( "exit" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( ) )
{
var config = container . GetConfiguration ( true ) ;
AreEqual ( HealthState . Starting , config . State . Health . Status ) ;
} Hal ini dimungkinkan melalui Fluent API dan ContainerCreateParams menentukan ulimit ke wadah buruh pelabuhan untuk misalnya membatasi jumlah file yang terbuka, dll. Misalnya menggunakan Fluent API akan terlihat seperti ini ketika membatasi jumlah file yang terbuka hingga 2048 (baik lunak maupun keras) .
using (
var container =
Fd . UseContainer ( )
. UseImage ( "postgres:latest" , force : true )
. UseUlimit ( Ulimit . NoFile , 2048 , 2048 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( ) )
{
// Do stuff
} Repo ini berisi tiga paket nuget, satu untuk akses lancar, satu untuk kelas dasar ms-test dan satu lagi untuk kelas dasar xunit yang akan digunakan saat pengujian. Misalnya dalam pengujian unit dimungkinkan untuk menjalankan wadah postgres dan menunggu ketika db telah boot.
public class PostgresXUnitTests : IClassFixture < PostgresTestBase >
{
[ Fact ]
public void Test ( )
{
// We now have a running postgres
// and a valid connection string to use.
}
} using (
var container =
new DockerBuilder ( )
. WithImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExposePorts ( "5432" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ )
. Build ( ) )
{
container . Create ( ) . Start ( ) ;
}Dimungkinkan juga untuk menggunakan kembali kelas dasar abstrak, misalnya basis pengujian postgres untuk menyederhanakan dan membuat pengujian unit bersih terhadap suatu wadah.
[ TestClass ]
public class PostgresMsTests : PostgresTestBase
{
[ TestMethod ]
public void Test ( )
{
// We now have a running postgres
// and a valid connection string to use.
}
} FluentDockerTestBase memungkinkan penggantian sederhana untuk melakukan pengujian apa pun yang didukung buruh pelabuhan khusus dengan mudah. Cukup buat kelas pengujian dan ambil dari FluentDockerTestBase dan ganti metode yang sesuai. Misalnya.
protected override DockerBuilder Build ( )
{
return new DockerBuilder ( )
. WithImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( $ "POSTGRES_PASSWORD= { PostgresPassword } " )
. ExposePorts ( "5432" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ ) ;
} Ini akan membuat pembangun dengan gambar buruh pelabuhan postgres:latest dan menetapkan satu string lingkungan, itu juga akan mengekspos port db postgres 5432 ke host sehingga seseorang dapat terhubung ke db di dalam wadah. Terakhir ia akan menunggu port 5432. Ini memastikan bahwa db berjalan dan melakukan booting dengan benar. Jika batas waktu, dalam contoh ini disetel ke 30 detik, pengecualian akan muncul dan container dihentikan dan dihapus. Perhatikan bahwa port host bukan 5432! Gunakan Container.GetHostPort("5432/tcp") untuk mendapatkan port host. Ip host dapat diambil oleh properti Container.Host dan karenanya harus digunakan saat berkomunikasi dengan aplikasi di dalam container.
Jika panggilan balik diperlukan ketika kontainer berhasil ditarik, dibuat, dan dimulai.
protected override void OnContainerInitialized ( )
{
ConnectionString = string . Format ( PostgresConnectionString , Container . Host ,
Container . GetHostPort ( "5432/tcp" ) , PostgresUser ,
PostgresPassword , PostgresDb ) ;
}Contoh ini merender string koneksi yang tepat ke db postgresql dalam wadah yang baru diputar. Ini dapat digunakan untuk terhubung menggunakan Npgsql, EF7, NHibernate, Marten atau alat lain yang kompatibel. Metode ini tidak akan dipanggil jika menarik image dari repositori buruh pelabuhan atau tidak dapat membuat/memulai container.
Jika kait kontainer sebelum dimatikan ingin diganti.
protected virtual void OnContainerTearDown ( )
{
// Do stuff before container is shut down.
} Perhatikan bahwa jika container tidak diberi nama, jika tidak dibuang dengan benar, container buruh pelabuhan akan tetap berjalan dan harus dihapus secara manual. Ini adalah fitur, bukan bug karena Anda mungkin ingin beberapa container berjalan dalam pengujian Anda. Kelas DockerContainer mengelola id instans kontainer dan dengan demikian hanya berinteraksi dengannya dan tidak ada kontainer lain.
Saat membuat/memulai container baru, ia akan memeriksa repositori lokal terlebih dahulu jika image container sudah ada dan akan mendownloadnya jika tidak ditemukan. Ini mungkin memakan waktu beberapa saat dan hanya ada Log Debug jika diaktifkan memungkinkan untuk memantau proses pengunduhan.
Ketika pengecualian yang tidak tertangani terjadi dan aplikasi FailFast yaitu berakhir dengan cepat, klausa finally tidak akan dipanggil. Jadi WaitForPort yang gagal di dalam pernyataan using tidak akan membuang layanan kontainer. Oleh karena itu kontainer masih berjalan. Untuk memperbaikinya, lakukan try...catch global atau masukkan secara lokal misalnya
try
{
using ( var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=postgres" )
. WaitForPort ( "5777/tcp" , 10000 ) // Fail here since 5777 is not valid port
. Build ( ) )
{
container . Start ( ) ; // FluentDockerException is thrown here since WaitForPort is executed
}
} catch { throw ; } Namun hal ini hanya terjadi ketika penghentian aplikasi dilakukan karena FluentDockerException dilemparkan ke dalam WaitForPort , jika tidak maka container akan dibuang dengan benar sehingga try...catch tidak diperlukan.
Hal ini juga dapat diselesaikan dengan menggunakan fungsi Fd.Build ( lihat Menggunakan Ekstensi Builder untuk informasi lebih lanjut).
Kelas Fd adalah kelas statis yang menyediakan metode kemudahan untuk membangun dan menjalankan kontainer tunggal dan tersusun. Untuk membuat wadah cukup gunakan:
var build = Fd . Build ( c => c . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , TimeSpan . FromSeconds ( 30 ) ) ) ;
// This is the equivalent of
var build = new Builder ( ) . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , TimeSpan . FromSeconds ( 30 ) ) ; Hal ini kemudian dapat digunakan untuk memulai kontainer dalam klausul using yang aman yang dijamin akan dibuang bahkan jika tidak ada pengecualian.
build . Container ( svc =>
{
var config = svc . GetConfiguration ( ) ;
// Do stuff...
} ) ; Setelah metode Container dijalankan, kontainer dalam hal ini dihentikan dan dihapus. Ini setara dengan
// This is equivalent of
try
{
using ( var svc = build . Build ( ) )
{
svc . Start ( ) ;
var config = svc . GetConfiguration ( ) ;
// Do stuff...
}
}
catch
{
Log ( .. . ) ;
throw ;
}Dimungkinkan juga untuk menggabungkan pembangun dan menjalankan misalnya melalui:
Fd . Container ( c => c . UseContainer ( )
. UseImage ( "postgres:9.6-alpine" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. WaitForPort ( "5432/tcp" , TimeSpan . FromSeconds ( 30 ) ) ,
svc =>
{
var config = svc . GetConfiguration ( ) ;
// Do stuff...
} ) ; Contoh di atas akan membangun container, memulai, menghentikan, dan terakhir menghapus container. Bahkan jika dan Exception dilempar maka akan Disposed . Tentu saja dimungkinkan untuk menggunakan wadah terkomposisi menggunakan metode ekstensi composite seperti halnya container .