パッケージ | NuGet |
---|---|
FluentDocker | |
マイクロソフトテスト | |
XUnit テスト |
このライブラリにより、 Fluent APIを使用したdocker
およびdocker-compose
対話が可能になります。 Linux、Windows、Mac でサポートされています。また、従来のdocker-machine
の相互作用もサポートされています。
Fluent API の使用例
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 ( ) ) ;
}
これにより、postgres が起動され、準備が完了するまで待機します。 Compose を使用するには、次のようにします。
注: V2 の動作を使用するには、AssumeComposeVersion(ComposeVersion.V2) を使用します。デフォルトは引き続き V1 です (今年後半にデフォルトの V2 に変更される予定です)。
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 Linux ユーザー向けのメモ: Docker はデフォルトでsudo を必要とし、ライブラリはデフォルトで、実行ユーザーが docker デーモンと通信するためにsudo を実行する必要がないことを想定しています。詳細については、 「Docker デーモンとの対話」の章を参照してください。
Fluent API は1 つ以上のサービスを構築します。各サービスは複合的な場合もあれば、単一のサービスである場合もあります。したがって、たとえば、複数のdocker-composeベースのサービスを起動して、それぞれを 1 つのサービスとして管理したり、各docker-composeサービスの基盤となるすべてのサービスを掘り下げて使用したりすることが可能です。サービスを直接使用することも可能です。
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 ) ;
}
上記の例では、単一の構成ファイルからdocker-composeサービスを作成します。サービスが破棄されると、基盤となるすべてのサービスが自動的に停止されます。
このライブラリは、.NET フル 4.51 フレームワーク以降、.NET 標準 1.6、2.0 でサポートされています。 3 つの薄いレイヤーに分かれており、各レイヤーにアクセスできます。
サービス メソッドの大部分は拡張メソッドであり、サービス自体に組み込まれていないため、軽量でカスタマイズ可能です。すべてにアクセスできるため、たとえば、レイヤー 1 コマンドを使用して機能を提供するサービスの拡張メソッドを追加するのが簡単です。
貢献は歓迎しますが、現時点では貢献に関するガイドラインはありません。プル リクエストを行うときは.editorconfigを必ず遵守してください。そうしないと、ビルドが失敗します。今年の遅かれ早かれ、実際のガイドラインを更新する予定です。
すべてのコマンドを使用するにはDockerUri
必要です。これは、ローカルまたはリモートの Docker デーモンへの URI です。検出可能にすることも、ハードコーディングすることもできます。ローカルDockerUri
の検出は次のように行うことができます。
var hosts = new Hosts ( ) . Discover ( ) ;
var _docker = hosts . FirstOrDefault ( x => x . IsNative ) ?? hosts . FirstOrDefault ( x => x . Name == "default" ) ;
抜粋された例では、ネイティブまたは Docker ベータ版の「ネイティブ」ホストをチェックし、そうでない場合はホストとして docker-machine 「デフォルト」を選択します。 docker-machine を使用していて、マシンが存在しないか起動されていない場合は"test-machine".Create(1024,20000000,1)
などによって docker-machine を簡単に作成/起動できます。これにより、1 GB の RAM、20 GB のディスクを備え、1 つの CPU を使用する「test-machine」という名前の Docker マシンが作成されます。
Uri を使用してコマンドを使用して通信できるようになりました。たとえば、クライアントとサーバーの Docker バイナリのバージョンを取得するには、次のようにします。
var result = _docker . Host . Version ( _docker . Certificates ) ;
Debug . WriteLine ( result . Data ) ; // Will Print the Client and Server Version and API Versions respectively.
すべてのコマンドは CommandResponse を返すため、 response.Success
によって成功要因を確認できます。コマンドに関連するデータがある場合は、 response.Data
プロパティで返されます。
次に、コマンドを使用してコンテナの削除を含む開始と停止を以下のように簡単に実行します。以下ではコンテナを起動し、PS を実行してから削除します。
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 ) ;
Windows 上で実行する場合、Linux コンテナまたは Windows コンテナを実行することを選択できます。 LinuxDaemon
またはWindowsDaemon
使用して、どのデーモンと通信するかを制御します。
_docker . LinuxDaemon ( ) ; // ensures that it will talk to linux daemon, if windows daemon it will switch
一部のコマンドは、連続ストリームを使用してイベントやログなどが必要な場合にデータのストリームを返します。ストリームはバックグラウンド タスクで使用でき、 CancellationToken
サポートします。以下の例では、ログを追跡します。
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 ) ;
}
}
コマンドにはユーティリティ メソッドが存在します。ネットワークなどのさまざまな形式があります。たとえば、ログを最後まで読む場合:
using ( var logs = _docker . Host . Logs ( id , _docker . Certificates ) )
{
foreach ( var line in logs . ReadToEnd ( ) )
{
Debug . WriteLine ( line ) ;
}
}
このライブラリの最上位層は、マシン、イメージ、コンテナを定義および制御できる Fluent API です。たとえば、Redis サーバーから読み取る 2 つの Nodejs サーバーを使用してロード バランサーをセットアップするには、次のようになります (リポジトリで見つからない場合、ノード イメージはカスタム ビルドされます)。
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 ) ;
}
上記の例では、ノード イメージに対してDockerfile を定義し、構築します。次に、バニラ Redis と nginx を使用します。既存のDockerfile を使用したいだけの場合は、次のように実行できます。
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.
}
Fluent API は、Docker マシンの定義から一連の Docker インスタンスまでをサポートします。たとえば、 Build()
が完了する前にコンテナ内の特定のポートやプロセスを待機するためのサポートが組み込まれているため、using ステートメント内で安全に使用できます。待機タイムアウトなどを特別に管理する場合は、いつでもコンテナを構築して起動し、拡張メソッドを使用してコンテナ自体で待機を行うことができます。
コンテナを作成するには、開始部分を省略するだけです。例えば:
using (
var container =
new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( ) )
{
Assert . AreEqual ( ServiceRunningState . Stopped , container . State ) ;
}
この例では、postgres を使用してコンテナーを作成し、1 つの環境変数を構成します。 using ステートメント内でIContainerService
を開始できます。したがって、構築された各コンテナはIContainerService
でラップされます。 IHostService.GetContainers(...)
使用して、作成済み、実行中、および終了したコンテナーを取得することもできます。 IHostService
から、コンテナーを作成するローカル リポジトリ内のすべてのイメージを取得することもできます。
単一のコンテナーを実行する場合は、Fluent またはコンテナー サービスの開始メソッドを使用してください。例えば:
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" ) ) ;
}
デフォルトでは、Dispose メソッドの実行時にコンテナーが停止および削除されます。コンテナーをアーカイブに保持するには、Fluent API でKeepContainer()
を使用します。 Dispose()
が呼び出されると、停止されますが、削除されません。廃棄後も稼働し続けることも可能です。
ポートを明示的またはランダムに公開することが可能です。どちらの方法でも、コードで使用する IP (マシンの場合) とポート (ランダム ポートの場合) を解決できます。例えば:
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 ) ;
}
ここでは、コンテナ ポート 5432 をホスト ポート 40001 に明示的にマップします。 container.ToHostExposedEndpoint(...)
の使用に注意してください。これは、Docker コンテナと通信するために常に動作する IP とポートに解決されるようにするためです。ランダムなポートをマッピングすることも可能です。つまり、Docker に利用可能なポートを選択させます。例えば:
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 ) ;
}
ここでの唯一の違いは、 ExposePort(...)
使用してコンテナーを構成する場合、引数が 1 つだけ使用されることです。その他の場合も同じ使用法が適用されるため、コードに対して透過的です。
特定のサービスへの接続などを開始する前に、そのサービスがいつ稼働しているかを知るため。特定のポートが開くまで待つことができます。例えば:
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 ( ) ) ;
}
上の例では、コンテナ ポート 5432 が 30 秒以内に開かれるのを待ちます。失敗すると例外がスローされ、コンテナは破棄されて削除されます (コンテナを保持するなどの構成がないため)。
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 ( ) ) ;
}
場合によっては、ローカル IP とポートによってコンテナに直接アクセスできないことがあります。代わりに、たとえば、コンテナにはループバック インターフェイス ( 127.0.0.1 ) 上に公開ポートがあり、これがプログラムからコンテナにアクセスする唯一の方法です。上記の例では、アドレスが強制的に127.0.0.1になりますが、それでもホスト ポートは解決されます。デフォルトでは、 FluentDocker はコンテナーのネットワーク検査を使用してネットワーク構成を決定します。
ポートを待つだけでは不十分な場合があります。場合によっては、コンテナープロセスを待つことがはるかに重要である場合があります。したがって、コンテナ オブジェクトの拡張メソッドだけでなく、fluent API にも wait for process メソッドが存在します。例えば:
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 ( ) ) ;
}
上記の例では、プロセス「postgres」がコンテナ内で開始されると、 Build()
制御を返します。
コンテナを利用するには、コンテナ内のボリュームをホストにマウントしたり、コンテナとの間で単にコピーしたりする必要がある場合があります。マシンまたは Docker をネイティブに実行しているかどうかに応じて、ボリューム マッピングには仮想マシンからアクセス可能でなければならないという制約があります。
通常の使用例は、たとえば Web サーバーが Docker コンテナ上でコンテンツを提供し、ユーザーがホスト ファイル システム上のファイルを編集することです。このようなシナリオでは、Docker コンテナー ボリュームをホストにマウントする必要があります。例えば:
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 ) ;
}
上記の例では、nginx コンテナが起動され、「/usr/share/nginx/html」を (一時ディレクトリ内のランダムな) ホスト パスにマウントします。 HTML ファイルがホスト パスにコピーされ、nginx docker コンテナへの HTTP get が完了すると、同じファイルが提供されます。
場合によっては、コンテナーとの間でファイルをコピーする必要があります。たとえば、構成ファイルをコピーし、構成してからコピーし直します。より一般的なシナリオは、コンテナーを開始する直前に構成ファイルをコンテナーにコピーすることです。マルチコンテナーの例では、nginx 構成ファイルを開始直前にコピーします。したがって、このような単純なタスクのために Dockerfile とイメージを手動で作成することを回避できます。代わりに、たとえば公式またはカスタムイメージを使用し、設定をコピーして実行します。
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" ) ) ) ;
}
上記の例では、実行中のコンテナからホスト パス (fullPath) にディレクトリをコピーします。ここでは拡張メソッドを使用しているため、流暢な API を使用していないことに注意してください (CopyFrom が Start() の後にあるため)。開始直前にコンテナからファイルをコピーしたい場合は、代わりに Fluent API を使用してください。
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. CopyOnStart ( "/etc/conf.d" , fullPath )
. Build ( )
. Start ( ) )
{
}
以下の例は、ファイルがコンテナーにコピーされる、より一般的なシナリオを示しています。この例では、Fluent API バージョンの代わりに拡張メソッドを使用します。コピー前とコピー直後に差分スナップショットを取得します。後者には hello.html が存在します。
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" ) ) ;
}
IContainerService.Dispose()
内 (コンテナーが停止する直前) でファイルをコピーすると便利な場合があります。したがって、それを確実に実行するために、流暢な API が存在します。
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. CopyOnDispose ( "/etc/conf.d" , fullPath )
. Build ( )
. Start ( ) )
{
}
コンテナを分析するために、エクスポート拡張メソッドと Fluent API メソッドが存在します。最も注目すべき点は、 IContainerService
が破棄されるときにコンテナーをエクスポートできることです。
using ( new Builder ( ) . UseContainer ( )
. UseImage ( "kiasaki/alpine-postgres" )
. ExposePort ( 5432 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. ExportOnDispose ( fullPath )
. Build ( )
. Start ( ) )
{
}
これにより、ホスト (フルパス) 上にコンテナー エクスポート (tar ファイル) が生成されます。展開した (風袋引きを解除した) 場合は、代わりにExportExplodedOnDispose
メソッドを使用してください。もちろん、コンテナの拡張メソッドを使用していつでもコンテナをエクスポートできます。
単体テストに関して便利なトリックは、単体テストが何らかの理由で失敗したときにコンテナの状態をエクスポートすることです。そのため、特定の Lambda 条件が満たされたときにエクスポートする Fluent API が存在します。例えば:
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 ;
}
このスニペットは、failure 変数が true に設定されており、 ExportOnDispose
式で使用されているため、using ステートメントがコンテナーを破棄するときにコンテナーをエクスポートします。
すべてのサービスはフックを使用して拡張できます。 ExportOnDispose(path, lambda)
では、サービス状態がRemoving
のときにラムダを実行するように設定されている場合にフックをインストールします。フックの取り付けと取り外しがその場で可能です。複数のフックが同じServiceRunningState
を使用して同じサービス インスタンスに登録されている場合、それらはインストール順に実行されます。
フックは、 Starting
などのサービスで状態が設定されようとしている (または実行されている) ときに何かを実行したい場合に特に適しています。 Fluent API は、ファイルのコピー、エクスポートなどの状況でこれらを使用します。
FluentDocker はすべての docker network コマンドをサポートしています。 _docker.NetworkLs()
によってネットワークを検出できます。この場合、すべてのネットワークとNetworkRow
で定義されたいくつかの単純なパラメーターが検出されます。また_docker.NetworkInspect(network:"networkId")
によって、ネットワークに関するより詳細な情報 (ネットワーク内にあるコンテナーや Ipam 構成など) を取得するために検査することもできます。
新しいネットワークを作成するには、 _docker.NetworkCreate("name_of_network")
を使用します。また、オーバーレイネットワークの作成や Ipam 設定の変更など、すべてをカスタマイズできるNetworkCreateParams
を提供することもできます。ネットワークを削除するには、 _docker.NetworkRm(network:"networkId")
を使用するだけです。
ネットワークにコンテナが接続されている場合、ネットワークは削除されないことに注意してください。
ネットワークが作成されると、 _docker.NetworkConnect("containerId","networkId")
を使用してネットワークに 1 つ以上のコンテナーを配置できます。コンテナは同時に複数のネットワークに存在する可能性があるため、分離されたネットワーク間でリクエストをプロキシできることに注意してください。ネットワークからコンテナーを切断するには、 _docker.NetworkDisconnect("containerId","networkId")
を実行するだけです。
次のサンプルでは、コンテナーを実行し、新しいネットワークを作成し、実行中のコンテナーをネットワークに接続します。次に、コンテナを切断して削除し、ネットワークを削除します。
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 ) ;
Fluent Builder を使用して、新しい Docker ネットワークを構築したり、既存の Docker ネットワークを再利用したりすることもできます。これらは、コンテナーの構築中に参照できます。一度に複数の Docker ネットワークを構築し、コンテナを複数のネットワークに接続することができます。
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 ( ) ;
}
}
上記のコード スニペットは、 test-networkという新しいネットワークを作成し、 test-networkに接続されるコンテナーを作成します。 Dispose()
がnwで呼び出されると、ネットワークが削除されます。 UseIpV4
またはUseIpV6
を使用して、ネットワーク内で静的IPコンテナーの割り当てを行うこともできます。例えば:
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 ) ;
}
}
上記の例では、ip-range 10.18.0.0/16を使用して新しいネットワークUnit-test-nwを作成します。新品の容器に使用したものです。コンテナの IP は10.18.0.22に設定されており、 UseIpV4
コマンドにより静的です。
FluentDocker は、コマンドと Fluent API の両方からの Docker ボリューム管理をサポートします。したがって、コンテナを廃棄するか、再利用するか、どのドライバを使用するかなど、コンテナで使用される量を完全に制御することができます。
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" ) ;
上記のスニペットは、 test-volumeという名前の、 NFSタイプの新しいボリュームを作成します。次に、作成したばかりのボリュームを検査し、最後にボリュームを強制的に削除します。
Fluent API を使用してボリュームを作成または使用することもできます。これらは、コンテナーを構築するときに使用できます。これは、ボリュームの作成が特殊な場合、または存続期間を制御する必要がある場合に特に便利です。
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 ) ;
}
}
上記のサンプルでは、 test-volumeという新しいボリュームを作成し、 IVolumeService
でDispose()
が呼び出されたときに削除されるようにスケジュールされています。コンテナーが作成され、新しく作成されたボリュームが読み取り/書き込みアクセス モードで/var/lib/postgresql/dataにマウントされます。コンテナーはボリュームのusing
ステートメントのスコープ内にあるため、その有効期間はコンテナーの有効期間全体に及び、その後削除されます。
FluentDocker は、Docker イベント メカニズムに接続して、送信されるイベントをリッスンすることをサポートします。
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 ;
}
}
}
イベント リスナーはグローバルであり、多くのEventAction
タイプを処理できます。
例えば
EventAction.Kill
の場合はContainerKillEvent
など、アクションに応じてイベント タイプが異なる場合があります。すべてのイベントはFdEvent
から派生します。つまり、すべての共有プロパティは基本イベントにあり、明示的なプロパティは派生イベントにあります。
たとえば、「ContainerKillEvent」には次のプロパティが含まれています。
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 ; }
}
このイベント ループは、イベントを取得し、インスタンス化されたIService
インスタンスを駆動するために使用できます。または、ネットワークの追加または削除などに対応する必要がある場合。
完全なフレームワークでは、 System.Diagnostics.Debugger.Log
を使用した詳細ログが使用されます。 .net core の場合、標準のMicrosoft.Extensions.Logging.ILog
を使用してログを記録します。どちらもカテゴリDuctus.FluentDocker を使用しているため、ログに参加するかどうかを設定したり、異なるログ出力先を設定したりすることができます。
.net core では、アプリケーション構成ファイルにログ セグメントを指定できます。
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Ductus.FluentDocker": "None"
}
}
}
詳細については、https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1 を確認してください。完全なフレームワークについては、https://docs.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/cconfiguring-tracing で説明されている完全なフレームワークの appconfig で必要なXMLを確認してください。
( Ductus.FluentDocker.Services
) Logging.Enabled()
またはLogging.Disabled()
を介してログを無効または有効にする簡単な方法があります。これにより、ログ記録が強制的に有効または無効になります。
FluentDockerのデフォルトのメカニズムをオーバーライドして、 WaitForPort
などのクライアントの観点からコンテナ IP を解決することができます。これはContainerBuilder
ベースでオーバーライドできます。
以下のサンプルは、デフォルトの動作をオーバーライドします。 null
を返すと、デフォルトのリゾルバーが起動します。
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 ) ;
}
docker-machine を使用せずにFluentAPI を使用してリモート Docker デーモンと通信するためのサポートは限定的です。これは、 DockerHostService
のインスタンスを手動で作成するか、 HostBuilder
でFromUri
使用することによって行われます。
using ( var container = Fd . UseHost ( ) .
FromUri ( Settings . DockerUri , isWindowsHost : true ) .
UseContainer ( ) .
Build ( ) )
{
}
上記のサンプルは、設定からカスタムDockerUri
に接続しており、Windows コンテナーの Docker デーモンです。
DockerUri
使用してIHostService
を作成するFromUri
。このURI は任意です。他のプロパティもサポートしています (下記を参照)。 public HostBuilder FromUri (
DockerUri uri ,
string name = null ,
bool isNative = true ,
bool stopWhenDisposed = false ,
bool isWindowsHost = false ,
string certificatePath = null ) { /*...*/ }
すべてのパラメータに「適切な」デフォルトが使用されます。ほとんどの場合、 uriで十分です。たとえば、 certificatePath を提供しない場合は、環境DOCKER_CERT_PATHから取得しようとします。環境内で見つからない場合は、デフォルトで none になります。
IHostService
実装を受け取るUseHost
。 このライブラリは、既存の構成ファイルを使用してサービスをレンダリングし、その有効期間を管理するdocker-composeをサポートしています。
次のサンプルには、 MySqlとWordPress を起動する構成ファイルが含まれています。したがって、1 つの作成サービスの下に 2 つのコンテナサービスが存在します。デフォルトでは、 Dispose()
が呼び出されたときにサービスを停止し、クリーンアップします。これは、 Fluent構成のKeepContainers()
によってオーバーライドできます。
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 :
上記のファイルは、完全なサービスを結合するためのdocker-composeファイルです。
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 ) ;
}
上記のスニペットはdocker-composeサービスをスムーズに構成し、インストール ページを呼び出して WordPress が実際に動作していることを確認します。
コピー、エクスポート、待機操作など、単一のコンテナーがサポートするすべての操作を実行することもできます。例えば:
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 ) ;
}
上記のスニペットは、wordpress docker compose プロジェクトを起動し、 URL http://localhost:8000/wp-admin/install.php をチェックし、本文に特定の値 (この場合は「https://wordpress.org」) を返します。 /")。そうでない場合は500 を返し、 WaitForHttp
関数は再度呼び出すまで 500 ミリ秒待機します。これはカスタム ラムダでも同様に機能します。代わりにWaitFor
使用してください。したがって、たとえば、using スコープ内で続行する前にデータベースにクエリを実行することが可能です。
Linux および Mac ユーザーの場合、ソケットに対して認証する方法がいくつかあります。 FluentDocker は、 sudoなし、パスワードなしのsudo (/etc/sudoer に NOPASSWD として追加されたユーザー)、またはパスワードありのsudoをサポートします。デフォルトでは、FluentDocker はsudoなしで通信できることを期待しています。オプションはグローバルですが、実行時に変更できます。
SudoMechanism . None . SetSudo ( ) ; // This is the default
SudoMechanism . Password . SetSudo ( "<my-sudo-password>" ) ;
SudoMechanism . NoPassword . SetSudo ( ) ;
docker デーモンと通信するためにsudo をオフにしたい場合は、docker チュートリアルに従って、ユーザーを docker グループに追加する最後のステップを実行できます。
FluentDocker は、リモート Docker デーモンへの接続をサポートします。流暢な API は以下をサポートします。
new Builder ( ) . UseHost ( ) . UseMachine ( ) . WithName ( "remote-daemon" )
ここで、これには、 docker-machineレジストリに事前にセットアップされたエントリが必要です。 SSHベースのDocker マシンレジストリ全体を定義してリモート デーモンに接続することもできます。
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 ) ;
}
この例では、IP アドレス192.168.1.27とSSHユーザーSoloのSSHを使用する、 remote-daemonという名前の新しいdocker-machineレジストリ エントリを作成します。 Remote-daemonという名前のエントリがすでに見つかった場合は、このエントリのみが再利用されます。次に、リモート デーモンの正しい証明書とURL を含むIHostService を取得します。したがって、リモート デーモン上に Docker コンテナを作成することが可能です。この場合、それはpostgresイメージです。コンテナを破棄するときは、通常どおり、リモート Docker からコンテナを削除します。 IHostService は、接続を認証するために必要なすべての証明書を必ず取得します。
上記の例では、このdocker-machineレジストリ エントリが生成されます。
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
UseSsh(...)
を使用するには、パスワードなしのSSHトンネルを設定する必要があります。さらに、トンネルを使用するユーザーは docker デーモンへのアクセスを許可されている必要があります。
SSHトンネルを設定し、ユーザーが Docker デーモンにアクセスできることを確認する方法については、次のチュートリアルに従ってください。
基本的には、 ssh-keygen -t rsa
使用してSSHトンネルで使用する新しい rsa キーを作成し、それをssh-copy-id {username}@{host}
によってリモート ホストにコピーします。
2 番目のチュートリアルで指定されているように /etc/sudoers を編集します。
これが完了すると、上で指定した汎用ドライバーまたは Fluent API を使用してリモート Docker デーモンにアクセスできるようになります。例で指定されているのと同じことを手動で実行するには、次のようになります。
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
これでレジストリ エントリが作成されたので、ターミナル ドッカーの環境を設定できるようになります。
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
これを実行して、Docker クライアントがリモート Docker デーモンを使用できるようにします。
@FOR /f "tokens=*" %i IN ('docker-machine.exe env remote-daemon') DO @%i
docker
バイナリを使用するすべてのコマンドは、リモート docker デーモン上で実行されるようになります。
マシン経由で Hyper-V Docker マシンを作成およびクエリする場合、Hyper-V は標準ユーザー モードでは API 呼び出しに応答しないため、プロセスを昇格する必要があります。
Docker コンテナーのヘルスチェックを指定して、そのようなアクティビティに基づいてコンテナーの状態を報告することができます。次の例では、コンテナーが終了したかどうかのヘルスチェックを使用しています。ヘルスチェックでどのようなステータスが報告されているかを構成を確認することができます (必ず強制的に更新してください)。
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 ) ;
}
Fluent APIとContainerCreateParams
使用して、Docker コンテナに ulimit を指定して、開いているファイルの数などを制限することができます。たとえば、開いているファイルの数を 2048 (ソフトとハードの両方) に制限する場合、 Fluent API を使用すると次のようになります。 。
using (
var container =
Fd . UseContainer ( )
. UseImage ( "postgres:latest" , force : true )
. UseUlimit ( Ulimit . NoFile , 2048 , 2048 )
. WithEnvironment ( "POSTGRES_PASSWORD=mysecretpassword" )
. Build ( )
. Start ( ) )
{
// Do stuff
}
このリポジトリには 3 つの nuget パッケージが含まれています。1 つは Fluent アクセス用、1 つは ms-test 基本クラス用、もう 1 つはテスト中に使用される xunit 基本クラス用です。たとえば、単体テストでは、postgres コンテナを起動し、データベースが起動するまで待機することができます。
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 ( ) ;
}
また、抽象基本クラス (postgres テスト ベースなど) を再利用して、コンテナに対する単体テストを簡素化してクリーンにすることもできます。
[ TestClass ]
public class PostgresMsTests : PostgresTestBase
{
[ TestMethod ]
public void Test ( )
{
// We now have a running postgres
// and a valid connection string to use.
}
}
FluentDockerTestBase
使用すると、カスタムの Docker ベースのテストを簡単に実行するための単純なオーバーライドが可能になります。テスト クラスを作成し、 FluentDockerTestBase
から派生し、適切なメソッドをオーバーライドするだけです。例えば。
protected override DockerBuilder Build ( )
{
return new DockerBuilder ( )
. WithImage ( "kiasaki/alpine-postgres" )
. WithEnvironment ( $ "POSTGRES_PASSWORD= { PostgresPassword } " )
. ExposePorts ( "5432" )
. WaitForPort ( "5432/tcp" , 30000 /*30s*/ ) ;
}
これにより、docker イメージ postgres:latest を使用してビルダーが作成され、環境文字列が 1 つ設定されます。また、postgres DB ポート 5432 がホストに公開されるため、コンテナ内の DB に接続できるようになります。最後に、ポート 5432 を待ちます。これにより、データベースが実行中であり、適切に起動していることが保証されます。タイムアウトになると (この例では 30 秒に設定されています)、例外がスローされ、コンテナーは停止して削除されます。ホストポートが 5432 ではないことに注意してください。 Container.GetHostPort("5432/tcp")
を使用してホスト ポートを取得します。ホスト IP はContainer.Host
プロパティによって取得できるため、コンテナ内のアプリと通信するときに使用されます。
コンテナーが正常に取得、作成、開始されたときにコールバックが必要な場合。
protected override void OnContainerInitialized ( )
{
ConnectionString = string . Format ( PostgresConnectionString , Container . Host ,
Container . GetHostPort ( "5432/tcp" ) , PostgresUser ,
PostgresPassword , PostgresDb ) ;
}
この例では、新しく起動したコンテナ内の postgresql データベースに適切な接続文字列をレンダリングします。これは、Npgsql、EF7、NHibernate、Marten、またはその他の互換性のあるツールを使用して接続するために使用できます。 Docker リポジトリからイメージを取得する場合、またはコンテナーを作成/起動できなかった場合、このメソッドは呼び出されません。
シャットダウン前のコンテナフックをオーバーライドする必要がある場合。
protected virtual void OnContainerTearDown ( )
{
// Do stuff before container is shut down.
}
名前のないコンテナーが適切に破棄されていない場合、Docker コンテナーは引き続き実行されるため、手動で削除する必要があることに注意してください。テストでは複数のコンテナーを実行する必要がある場合があるため、これはバグではなく機能です。 DockerContainer
クラスはコンテナーのインスタンス ID を管理するため、そのコンテナーとのみ対話し、他のコンテナーとは対話しません。
新しいコンテナを作成/開始するとき、最初にローカル リポジトリをチェックして、コンテナ イメージがすでに存在するかどうかを確認し、見つからない場合はダウンロードします。これには時間がかかる場合があります。デバッグ ログが有効になっている場合は、ダウンロード プロセスを監視できるだけです。
未処理の例外が発生し、アプリケーションFailFastがすぐに終了すると、 finally
句は呼び出されません。したがって、 using
ステートメント内でWaitForPort
失敗しても、コンテナー サービスは破棄されません。したがって、コンテナはまだ実行中です。これを修正するには、グローバル try...catch を使用するか、ローカルに挿入します。
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 ; }
ただし、これはWaitForPort
でスローされたFluentDockerException
によってアプリケーションが終了した場合に限ります。それ以外の場合はコンテナが適切に破棄されるため、 try...catch
必要ありません。
これは、 Fd.Build
関数を使用して解決することもできます (詳細については、「ビルダー拡張機能の使用」を参照してください)。
クラスFd
は、単一の複合コンテナーを構築および実行するための便利なメソッドを提供する静的クラスです。コンテナを構築するには、以下を使用するだけです。
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 ) ) ;
これを使用して、例外がキャッチされなかった場合でも破棄されることが保証されている安全なusing
句内でコンテナを起動できます。
build . Container ( svc =>
{
var config = svc . GetConfiguration ( ) ;
// Do stuff...
} ) ;
Container
メソッドが実行された後、この場合コンテナは停止され、削除されます。これは以下と同等です
// This is equivalent of
try
{
using ( var svc = build . Build ( ) )
{
svc . Start ( ) ;
var config = svc . GetConfiguration ( ) ;
// Do stuff...
}
}
catch
{
Log ( .. . ) ;
throw ;
}
たとえば次のようにして、ビルダーと実行を組み合わせることも可能です。
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...
} ) ;
上記の例では、コンテナーを構築し、開始、停止し、最後にコンテナーを削除します。 Exception
がスローされた場合でも、それはDisposed
ます。もちろん、 container
と同様にcomposite
拡張メソッドを使用して compsed コンテナを使用することも可能です。