1. 概要

この記事では、もう1つの定評のあるプラットフォーム固有のAPIであるDocker用JavaAPIクライアントについて説明します。

この記事全体を通して、実行中のDockerデーモンに接続する方法と、APIがJava開発者に提供する重要な機能の種類を理解しています。

2. Mavenの依存関係

まず、主な依存関係をpom.xmlファイルに追加する必要があります。

<dependency>
    <groupId>com.github.docker-java</groupId>
    <artifactId>docker-java</artifactId>
    <version>3.0.14</version>
</dependency>

この記事を書いている時点では、APIの最新バージョンは3.0.14です。 各リリースは、GitHubリリースページまたはMavenリポジトリから表示できます。

3. Dockerクライアントの使用

DockerClient は、Dockerエンジン/デーモンとアプリケーション間の接続を確立できる場所です。

デフォルトでは、Dockerデーモンは unix:///var/run/docker.sockファイルでのみアクセスできます。 特に設定されていない限り、UnixソケットをリッスンしているDockerエンジンとローカルで通信できます

ここでは、 DockerClientBuilder クラスに適用して、デフォルト設定を受け入れて接続を作成します。

DockerClient dockerClient = DockerClientBuilder.getInstance().build();

同様に、2つのステップで接続を開くことができます。

DefaultDockerClientConfig.Builder config 
  = DefaultDockerClientConfig.createDefaultConfigBuilder();
DockerClient dockerClient = DockerClientBuilder
  .getInstance(config)
  .build();

エンジンは他の特性に依存する可能性があるため、クライアントはさまざまな条件で構成することもできます。

たとえば、ビルダーはサーバーURLを受け入れます。つまり、エンジンがポート2375 で使用可能な場合、接続値を更新できます。

DockerClient dockerClient
  = DockerClientBuilder.getInstance("tcp://docker.baeldung.com:2375").build();

接続タイプに応じて、接続文字列の前にunix://またはtcp://を付ける必要があることに注意してください。

さらに一歩進むと、DefaultDockerClientConfigクラスを使用してより高度な構成を行うことができます。

DefaultDockerClientConfig config
  = DefaultDockerClientConfig.createDefaultConfigBuilder()
    .withRegistryEmail("[email protected]")
    .withRegistryPassword("baeldung")
    .withRegistryUsername("baeldung")
    .withDockerCertPath("/home/baeldung/.docker/certs")
    .withDockerConfig("/home/baeldung/.docker/")
    .withDockerTlsVerify("1")
    .withDockerHost("tcp://docker.baeldung.com:2376").build();

DockerClient dockerClient = DockerClientBuilder.getInstance(config).build();

同様に、プロパティを使用して同じアプローチを実行できます。

Properties properties = new Properties();
properties.setProperty("registry.email", "[email protected]");
properties.setProperty("registry.password", "baeldung");
properties.setProperty("registry.username", "baaldung");
properties.setProperty("DOCKER_CERT_PATH", "/home/baeldung/.docker/certs");
properties.setProperty("DOCKER_CONFIG", "/home/baeldung/.docker/");
properties.setProperty("DOCKER_TLS_VERIFY", "1");
properties.setProperty("DOCKER_HOST", "tcp://docker.baeldung.com:2376");

DefaultDockerClientConfig config
  = DefaultDockerClientConfig.createDefaultConfigBuilder()
    .withProperties(properties).build();

DockerClient dockerClient = DockerClientBuilder.getInstance(config).build();

ソースコードでエンジンの設定を構成しない限り、別の選択肢は、プロジェクトで DockerClient のデフォルトのインスタンス化のみを考慮できるように、対応する環境変数を設定することです。

export DOCKER_CERT_PATH=/home/baeldung/.docker/certs
export DOCKER_CONFIG=/home/baeldung/.docker/
export DOCKER_TLS_VERIFY=1
export DOCKER_HOST=tcp://docker.baeldung.com:2376

4. コンテナ管理

APIを使用すると、コンテナ管理に関するさまざまな選択肢が得られます。 それぞれを見てみましょう。

4.1. コンテナのリスト

接続が確立されたので、Dockerホストにある実行中のすべてのコンテナーを一覧表示できます。

List<Container> containers = dockerClient.listContainersCmd().exec();

実行中のコンテナーを表示してもニーズに合わない場合は、提供されているオプションを使用してコンテナーを照会できます。

この場合、「終了」ステータスのコンテナを表示します。

List<Container> containers = dockerClient.listContainersCmd()
  .withShowSize(true)
  .withShowAll(true)
  .withStatusFilter("exited").exec()

これは次のものと同等です。

$ docker ps -a -s -f status=exited
# or 
$ docker container ls -a -s -f status=exited

4.2. コンテナを作成する

コンテナの作成は、createContainerCmdメソッドで提供されます。 より複雑な宣言を使用して「with」プレフィックスで始まる使用可能なメソッドを宣言できます。

ポート27017で内部的にリッスンするホスト依存のMongoDBコンテナーを定義するdocker createコマンドがあると仮定します。

$ docker create --name mongo \
  --hostname=baeldung \
  -e MONGO_LATEST_VERSION=3.6 \
  -p 9999:27017 \
  -v /Users/baeldung/mongo/data/db:/data/db \
  mongo:3.6 --bind_ip_all

プログラムで、同じコンテナとその構成をブートストラップすることができます。

CreateContainerResponse container
  = dockerClient.createContainerCmd("mongo:3.6")
    .withCmd("--bind_ip_all")
    .withName("mongo")
    .withHostName("baeldung")
    .withEnv("MONGO_LATEST_VERSION=3.6")
    .withPortBindings(PortBinding.parse("9999:27017"))
    .withBinds(Bind.parse("/Users/baeldung/mongo/data/db:/data/db")).exec();

4.3. コンテナの開始、停止、および強制終了

コンテナを作成したら、名前またはIDでそれぞれ開始、停止、および強制終了できます。

dockerClient.startContainerCmd(container.getId()).exec();

dockerClient.stopContainerCmd(container.getId()).exec();

dockerClient.killContainerCmd(container.getId()).exec();

4.4. コンテナを検査する

inspectContainerCmd メソッドは、コンテナーの名前またはIDを示すString引数を取ります。 このメソッドを使用すると、コンテナのメタデータを直接監視できます。

InspectContainerResponse container 
  = dockerClient.inspectContainerCmd(container.getId()).exec();

4.5. コンテナのスナップショット

docker commit コマンドと同様に、commitCmdメソッドを使用して新しいイメージを作成できます。

この例では、シナリオはです。以前は、IDが「3464bb547f88」のalpine:3.6コンテナーを実行し、その上にgitをインストールしました。

次に、コンテナから新しいイメージスナップショットを作成します。

String snapshotId = dockerClient.commitCmd("3464bb547f88")
  .withAuthor("Baeldung <[email protected]>")
  .withEnv("SNAPSHOT_YEAR=2018")
  .withMessage("add git support")
  .withCmd("git", "version")
  .withRepository("alpine")
  .withTag("3.6.git").exec();

git にバンドルされている新しいイメージはホストに残っているため、Dockerホストで検索できます。

$ docker image ls alpine --format "table {{.Repository}} {{.Tag}}"
REPOSITORY TAG
alpine     3.6.git

5. 画像管理

画像操作を管理するために与えられたいくつかの適用可能なコマンドがあります。

5.1. 画像の一覧表示

Dockerホストでぶら下がっている画像を含むすべての利用可能な画像を一覧表示するには、listImagesCmdメソッドに適用する必要があります。

List<Image> images = dockerClient.listImagesCmd().exec();

Dockerホストに2つのイメージがある場合、実行時にそれらのイメージオブジェクトを取得する必要があります。 私たちが探している画像は次のとおりです。

$ docker image ls --format "table {{.Repository}} {{.Tag}}"
REPOSITORY TAG
alpine     3.6
mongo      3.6

次に、中間画像を表示するには、明示的にリクエストする必要があります。

List<Image> images = dockerClient.listImagesCmd()
  .withShowAll(true).exec();

ぶら下がっている画像のみを表示する場合は、withDanglingFilterメソッドを検討する必要があります。

List<Image> images = dockerClient.listImagesCmd()
  .withDanglingFilter(true).exec();

5.2. イメージを作成する

APIを使用してイメージを構築する方法に焦点を当てましょう。 buildImageCmdメソッドは、DockerfileからDockerイメージをビルドします。 私たちのプロジェクトには、gitがインストールされたAlpineイメージを提供するDockerfileがすでに1つあります。

FROM alpine:3.6

RUN apk --update add git openssh && \
  rm -rf /var/lib/apt/lists/* && \
  rm /var/cache/apk/*

ENTRYPOINT ["git"]
CMD ["--help"]

新しいイメージはキャッシュを使用せずにビルドされ、ビルドプロセスを開始する前に、いずれの場合も、Dockerエンジンは新しいバージョンの alpine:3.6をプルしようとします。 すべてがうまくいけば、最終的には alpine:git:という名前の画像が表示されるはずです。

String imageId = dockerClient.buildImageCmd()
  .withDockerfile(new File("path/to/Dockerfile"))
  .withPull(true)
  .withNoCache(true)
  .withTag("alpine:git")
  .exec(new BuildImageResultCallback())
  .awaitImageId();

5.3. 画像を検査する

inspectImageCmd メソッドのおかげで、画像に関する低レベルの情報を検査できます。

InspectImageResponse image 
  = dockerClient.inspectImageCmd("161714540c41").exec();

5.4. 画像にタグを付ける

docker tag コマンドを使用すると、画像にタグを追加するのは非常に簡単なので、APIも例外ではありません。 tagImageCmdメソッドでも同じ意図を実行できます。 ID 161714540c41のDockerイメージをgit:を使用してbaeldung/alpineリポジトリにタグ付けするには

String imageId = "161714540c41";
String repository = "baeldung/alpine";
String tag = "git";

dockerClient.tagImageCmd(imageId, repository, tag).exec();

新しく作成された画像を一覧表示します。次のようになります。

$ docker image ls --format "table {{.Repository}} {{.Tag}}"
REPOSITORY      TAG
baeldung/alpine git

5.5. 画像をプッシュ

レジストリサービスにイメージを送信する前に、レジストリの操作を事前に認証する必要があるため、Dockerクライアントはサービスと連携するように構成する必要があります。

クライアントがDockerHubで構成されていると想定しているため、 baeldung /alpineイメージをbaeldungDockerHubアカウントにプッシュできます。

dockerClient.pushImageCmd("baeldung/alpine")
  .withTag("git")
  .exec(new PushImageResultCallback())
  .awaitCompletion(90, TimeUnit.SECONDS);

プロセスの期間を遵守する必要があります。 例では、90秒待機しています

5.6. 画像をプルする

レジストリサービスから画像をダウンロードするには、pullImageCmdメソッドを使用します。 さらに、イメージがプライベートレジストリからプルされている場合、クライアントはクレデンシャルを知っている必要があります。そうでない場合、プロセスは失敗します。 画像をプルするのと同じように、画像をプルするための固定期間とともにコールバックを指定します:

dockerClient.pullImageCmd("baeldung/alpine")
  .withTag("git")
  .exec(new PullImageResultCallback())
  .awaitCompletion(30, TimeUnit.SECONDS);

上記のイメージをプルした後、Dockerホストに存在するかどうかを確認するには:

$ docker images baeldung/alpine --format "table {{.Repository}} {{.Tag}}"
REPOSITORY      TAG
baeldung/alpine git

5.7. 画像を削除する

残りの中でもう1つの単純な関数は、removeImageCmdメソッドです。 短いIDまたは長いIDの画像を削除できます。

dockerClient.removeImageCmd("beaccc8687ae").exec();

5.8. レジストリで検索

Docker Hubから画像を検索するために、クライアントには、用語を示す文字列値を取得するsearchImagesCmdメソッドが付属しています。 ここでは、DockerHubで「Java」を含む名前に関連する画像を調べます。

List<SearchItem> items = dockerClient.searchImagesCmd("Java").exec();

出力は、SearchItemオブジェクトのリストの最初の25個の関連画像を返します。

6. ボリューム管理

Javaプロジェクトがボリュームに対してDockerと対話する必要がある場合は、このセクションも考慮する必要があります。 簡単に説明します。DockerJavaAPIによって提供されるボリュームの基本的な手法を見ていきます。

6.1. ボリュームのリスト

名前付きおよび名前なしを含むすべての使用可能なボリュームは、次のようにリストされます。

ListVolumesResponse volumesResponse = dockerClient.listVolumesCmd().exec();
List<InspectVolumeResponse> volumes = volumesResponse.getVolumes();

6.2. ボリュームを検査する

inspectVolumeCmd メソッドは、ボリュームの詳細情報を表示するためのフォームです。 短いIDを指定してボリュームを検査します。

InspectVolumeResponse volume 
  = dockerClient.inspectVolumeCmd("0220b87330af5").exec();

6.3. ボリュームを作成する

APIは、ボリュームを作成するための2つの異なるオプションを提供します。 非引数createVolumeCmdメソッドは、名前がDockerによって指定されたボリュームを作成します。

CreateVolumeResponse unnamedVolume = dockerClient.createVolumeCmd().exec();

デフォルトの動作を使用するのではなく、 withName というヘルパーメソッドを使用すると、ボリュームに名前を設定できます。

CreateVolumeResponse namedVolume 
  = dockerClient.createVolumeCmd().withName("myNamedVolume").exec();

6.4. ボリュームを削除する

removeVolumeCmd メソッドを使用して、Dockerホストからボリュームを直感的に削除できます。 コンテナから使用中のボリュームを削除できないことに注意してください。ボリュームリストからボリュームmyNamedVolumeを削除します。

dockerClient.removeVolumeCmd("myNamedVolume").exec();

7. ネットワーク管理

最後のセクションでは、APIを使用したネットワークタスクの管理について説明します。

7.1. ネットワークの一覧表示

list で始まる従来のAPIメソッドの1つを使用して、ネットワークユニットのリストを表示できます。

List<Network> networks = dockerClient.listNetworksCmd().exec();

7.2. ネットワークを作成する

docker network create コマンドに相当するものは、createNetworkCmdメソッドを使用して実行されます。 30パーティまたはカスタムネットワークドライバーがある場合、 withDriver メソッドは、組み込みドライバー以外にそれらを受け入れることができます。 この例では、baeldungという名前のブリッジネットワークを作成しましょう。

CreateNetworkResponse networkResponse 
  = dockerClient.createNetworkCmd()
    .withName("baeldung")
    .withDriver("bridge").exec();

さらに、デフォルト設定でネットワークユニットを作成しても問題は解決しません。他のヘルパーメソッドを適用して、高度なネットワークを構築できます。 したがって、デフォルトのサブネットワークをカスタム値でオーバーライドするには:

CreateNetworkResponse networkResponse = dockerClient.createNetworkCmd()
  .withName("baeldung")
  .withIpam(new Ipam()
    .withConfig(new Config()
    .withSubnet("172.36.0.0/16")
    .withIpRange("172.36.5.0/24")))
  .withDriver("bridge").exec();

dockerコマンドで実行できるのと同じコマンドは次のとおりです。

$ docker network create \
  --subnet=172.36.0.0/16 \
  --ip-range=172.36.5.0/24 \
  baeldung

7.3. ネットワークを検査する

ネットワークの低レベルの詳細の表示もAPIでカバーされています。

Network network 
  = dockerClient.inspectNetworkCmd().withNetworkId("baeldung").exec();

7.4. ネットワークを削除する

removeNetworkCmd メソッドを使用して、名前またはIDを持つネットワークユニットを安全に削除できます。

dockerClient.removeNetworkCmd("baeldung").exec();

8. 結論

この広範なチュートリアルでは、 Java Docker APIクライアントのさまざまな機能と、デプロイメントおよび管理シナリオのいくつかの実装アプローチについて説明しました。

この記事で説明されているすべての例は、GitHubにあります。