|
@@ -4,7 +4,9 @@ import com.github.dockerjava.api.DockerClient;
|
|
|
import com.github.dockerjava.api.command.CreateContainerResponse;
|
|
import com.github.dockerjava.api.command.CreateContainerResponse;
|
|
|
import com.github.dockerjava.api.command.PullImageResultCallback;
|
|
import com.github.dockerjava.api.command.PullImageResultCallback;
|
|
|
import com.github.dockerjava.api.model.ExposedPort;
|
|
import com.github.dockerjava.api.model.ExposedPort;
|
|
|
|
|
+import com.github.dockerjava.api.model.Info;
|
|
|
import com.github.dockerjava.api.model.Ports;
|
|
import com.github.dockerjava.api.model.Ports;
|
|
|
|
|
+import com.github.dockerjava.api.model.Version;
|
|
|
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
|
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
|
|
import com.github.dockerjava.core.DockerClientBuilder;
|
|
import com.github.dockerjava.core.DockerClientBuilder;
|
|
|
import com.github.dockerjava.core.DockerClientConfig;
|
|
import com.github.dockerjava.core.DockerClientConfig;
|
|
@@ -19,6 +21,7 @@ import java.time.Duration;
|
|
|
/**
|
|
/**
|
|
|
* Docker Java SDK 快速入门示例
|
|
* Docker Java SDK 快速入门示例
|
|
|
* 演示 DockerClient 的创建、连接、拉取镜像、创建并启动容器等基本操作
|
|
* 演示 DockerClient 的创建、连接、拉取镜像、创建并启动容器等基本操作
|
|
|
|
|
+ * 每个操作旁标注了等价的 Docker CLI 命令,方便对照理解
|
|
|
*/
|
|
*/
|
|
|
public class QuickStart {
|
|
public class QuickStart {
|
|
|
private static final Logger log = LoggerFactory.getLogger(QuickStart.class);
|
|
private static final Logger log = LoggerFactory.getLogger(QuickStart.class);
|
|
@@ -43,8 +46,12 @@ public class QuickStart {
|
|
|
*/
|
|
*/
|
|
|
public void quickStart() {
|
|
public void quickStart() {
|
|
|
DockerClient defaultClient = DockerClientBuilder.getInstance().build();
|
|
DockerClient defaultClient = DockerClientBuilder.getInstance().build();
|
|
|
|
|
+
|
|
|
|
|
+ // 等价命令: docker version(连接自检,底层请求 HTTP GET /_ping)
|
|
|
defaultClient.pingCmd().exec();
|
|
defaultClient.pingCmd().exec();
|
|
|
log.info("Docker client ping 成功!");
|
|
log.info("Docker client ping 成功!");
|
|
|
|
|
+
|
|
|
|
|
+ // 等价命令: docker images
|
|
|
defaultClient.listImagesCmd().exec().forEach(image -> {
|
|
defaultClient.listImagesCmd().exec().forEach(image -> {
|
|
|
log.info("Docker 镜像信息: {}", image);
|
|
log.info("Docker 镜像信息: {}", image);
|
|
|
});
|
|
});
|
|
@@ -55,7 +62,7 @@ public class QuickStart {
|
|
|
* 可以自定义连接地址、TLS、超时时间等参数
|
|
* 可以自定义连接地址、TLS、超时时间等参数
|
|
|
*/
|
|
*/
|
|
|
public void customStart() {
|
|
public void customStart() {
|
|
|
- final String UNIX_HOST = "unix://var/run/docker.sock";
|
|
|
|
|
|
|
+ final String UNIX_HOST = "unix:///var/run/docker.sock";
|
|
|
final String TCP_HOST = "tcp://0.0.0.0:2375";
|
|
final String TCP_HOST = "tcp://0.0.0.0:2375";
|
|
|
// 构建 DockerClientConfig 配置对象
|
|
// 构建 DockerClientConfig 配置对象
|
|
|
DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
|
|
DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
|
|
@@ -79,12 +86,39 @@ public class QuickStart {
|
|
|
log.info("HTTP 客户端配置: {}", httpClient);
|
|
log.info("HTTP 客户端配置: {}", httpClient);
|
|
|
// 根据自定义配置创建 DockerClient
|
|
// 根据自定义配置创建 DockerClient
|
|
|
DockerClient customClient = DockerClientImpl.getInstance(dockerClientConfig, httpClient);
|
|
DockerClient customClient = DockerClientImpl.getInstance(dockerClientConfig, httpClient);
|
|
|
|
|
+
|
|
|
|
|
+ // 等价命令: docker version(连接自检)
|
|
|
customClient.pingCmd().exec();
|
|
customClient.pingCmd().exec();
|
|
|
|
|
+
|
|
|
|
|
+ // 等价命令: docker images
|
|
|
customClient.listImagesCmd().exec().forEach(image -> {
|
|
customClient.listImagesCmd().exec().forEach(image -> {
|
|
|
log.info("Docker 镜像信息: {}", image);
|
|
log.info("Docker 镜像信息: {}", image);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取 Docker 客户端与 daemon 的版本信息
|
|
|
|
|
+ * 等价命令: docker version
|
|
|
|
|
+ */
|
|
|
|
|
+ public void getDockerVersion() {
|
|
|
|
|
+ // 等价命令: docker version "Docker" 输出客户端与服务端版本
|
|
|
|
|
+ // 等价命令: docker version --format '{{.Server.Version}}' 只取服务端版本
|
|
|
|
|
+ Version version = dockerClient.versionCmd().exec();
|
|
|
|
|
+ log.info("Docker 服务端版本: {}, API 版本: {}, 架构: {}, 运行时间: {}",
|
|
|
|
|
+ version.getVersion(), version.getApiVersion(), version.getArch(), version.getBuildTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取 Docker daemon 的系统级信息(容器数、镜像数、存储驱动等)
|
|
|
|
|
+ * 等价命令: docker info
|
|
|
|
|
+ */
|
|
|
|
|
+ public void getDockerInfo() {
|
|
|
|
|
+ // 等价命令: docker info
|
|
|
|
|
+ Info info = dockerClient.infoCmd().exec();
|
|
|
|
|
+ log.info("Docker 系统信息: 容器数: {}, 镜像数: {}, 服务端版本: {}",
|
|
|
|
|
+ info.getContainers(), info.getImages(), info.getServerVersion());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 拉取指定名称的镜像
|
|
* 拉取指定名称的镜像
|
|
|
* 优化:如果本地已存在同名镜像则直接使用,无需访问网络
|
|
* 优化:如果本地已存在同名镜像则直接使用,无需访问网络
|
|
@@ -92,6 +126,7 @@ public class QuickStart {
|
|
|
*/
|
|
*/
|
|
|
public void pullImage(String imageName) {
|
|
public void pullImage(String imageName) {
|
|
|
// 先检查本地是否已存在该镜像,避免无谓的网络访问
|
|
// 先检查本地是否已存在该镜像,避免无谓的网络访问
|
|
|
|
|
+ // 等价命令: docker images 查看本地镜像列表
|
|
|
boolean exists = dockerClient.listImagesCmd().exec().stream()
|
|
boolean exists = dockerClient.listImagesCmd().exec().stream()
|
|
|
.anyMatch(img -> img.getRepoTags() != null &&
|
|
.anyMatch(img -> img.getRepoTags() != null &&
|
|
|
java.util.Arrays.asList(img.getRepoTags()).contains(imageName));
|
|
java.util.Arrays.asList(img.getRepoTags()).contains(imageName));
|
|
@@ -100,6 +135,7 @@ public class QuickStart {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
|
|
+ // 等价命令: docker pull nginx:latest
|
|
|
// exec() 执行命令,awaitCompletion() 阻塞等待镜像拉取完成
|
|
// exec() 执行命令,awaitCompletion() 阻塞等待镜像拉取完成
|
|
|
dockerClient.pullImageCmd(imageName)
|
|
dockerClient.pullImageCmd(imageName)
|
|
|
.exec(new PullImageResultCallback())
|
|
.exec(new PullImageResultCallback())
|
|
@@ -118,12 +154,15 @@ public class QuickStart {
|
|
|
*/
|
|
*/
|
|
|
public void createAndStartContainer(String imageName, String containerName) {
|
|
public void createAndStartContainer(String imageName, String containerName) {
|
|
|
// 步骤1:创建容器(只分配资源和配置,不真正运行)
|
|
// 步骤1:创建容器(只分配资源和配置,不真正运行)
|
|
|
|
|
+ // 等价命令: docker create --name demo-container hello-world
|
|
|
CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
|
|
CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
|
|
|
.withName(containerName)
|
|
.withName(containerName)
|
|
|
.exec();
|
|
.exec();
|
|
|
log.info("容器创建成功,ID: {}", container.getId());
|
|
log.info("容器创建成功,ID: {}", container.getId());
|
|
|
|
|
|
|
|
// 步骤2:启动容器
|
|
// 步骤2:启动容器
|
|
|
|
|
+ // 等价命令: docker start demo-container
|
|
|
|
|
+ // 上面两步合起来相当于: docker run --name demo-container hello-world
|
|
|
dockerClient.startContainerCmd(container.getId()).exec();
|
|
dockerClient.startContainerCmd(container.getId()).exec();
|
|
|
log.info("容器 {} 启动成功!", containerName);
|
|
log.info("容器 {} 启动成功!", containerName);
|
|
|
}
|
|
}
|
|
@@ -143,6 +182,8 @@ public class QuickStart {
|
|
|
Ports portBindings = new Ports();
|
|
Ports portBindings = new Ports();
|
|
|
portBindings.bind(exposedPort, Ports.Binding.bindPort(hostPort));
|
|
portBindings.bind(exposedPort, Ports.Binding.bindPort(hostPort));
|
|
|
|
|
|
|
|
|
|
+ // 等价命令: docker run -d --name demo-nginx -p 8080:80 nginx:latest
|
|
|
|
|
+ // 其中 -p 8080:80 表示"宿主机8080 -> 容器内80"
|
|
|
CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
|
|
CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
|
|
|
.withName(containerName)
|
|
.withName(containerName)
|
|
|
.withExposedPorts(exposedPort)
|
|
.withExposedPorts(exposedPort)
|
|
@@ -150,6 +191,7 @@ public class QuickStart {
|
|
|
.exec();
|
|
.exec();
|
|
|
log.info("容器创建成功,ID: {}, 端口映射: {} -> {}", container.getId(), hostPort, containerPort);
|
|
log.info("容器创建成功,ID: {}, 端口映射: {} -> {}", container.getId(), hostPort, containerPort);
|
|
|
|
|
|
|
|
|
|
+ // 等价命令: docker start demo-nginx
|
|
|
dockerClient.startContainerCmd(container.getId()).exec();
|
|
dockerClient.startContainerCmd(container.getId()).exec();
|
|
|
log.info("容器 {} 启动成功!", containerName);
|
|
log.info("容器 {} 启动成功!", containerName);
|
|
|
}
|
|
}
|
|
@@ -160,31 +202,36 @@ public class QuickStart {
|
|
|
*/
|
|
*/
|
|
|
public void runDemo() {
|
|
public void runDemo() {
|
|
|
// 1. 测试连接
|
|
// 1. 测试连接
|
|
|
|
|
+ // 等价命令: docker version
|
|
|
dockerClient.pingCmd().exec();
|
|
dockerClient.pingCmd().exec();
|
|
|
log.info("1. Docker 连接成功");
|
|
log.info("1. Docker 连接成功");
|
|
|
|
|
|
|
|
// 2. 检查本地是否已有可用的镜像
|
|
// 2. 检查本地是否已有可用的镜像
|
|
|
- String imageName = "alist666/alist:latest";
|
|
|
|
|
|
|
+ String imageName = "nginx:latest";
|
|
|
|
|
+ // 等价命令: docker images
|
|
|
boolean hasImage = dockerClient.listImagesCmd().exec().stream()
|
|
boolean hasImage = dockerClient.listImagesCmd().exec().stream()
|
|
|
.anyMatch(img -> img.getRepoTags() != null &&
|
|
.anyMatch(img -> img.getRepoTags() != null &&
|
|
|
java.util.Arrays.asList(img.getRepoTags()).contains(imageName));
|
|
java.util.Arrays.asList(img.getRepoTags()).contains(imageName));
|
|
|
if (!hasImage) {
|
|
if (!hasImage) {
|
|
|
- log.warn("本地不存在镜像 {},跳过容器演示", imageName);
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ log.warn("本地不存在镜像 {},尝试拉取", imageName);
|
|
|
|
|
+ pullImage(imageName);
|
|
|
}
|
|
}
|
|
|
log.info("2. 找到本地镜像: {}", imageName);
|
|
log.info("2. 找到本地镜像: {}", imageName);
|
|
|
|
|
|
|
|
// 3. 创建容器
|
|
// 3. 创建容器
|
|
|
|
|
+ // 等价命令: docker create --name demo-container nginx:latest
|
|
|
CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
|
|
CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
|
|
|
.withName("demo-container-" + System.currentTimeMillis())
|
|
.withName("demo-container-" + System.currentTimeMillis())
|
|
|
.exec();
|
|
.exec();
|
|
|
log.info("3. 容器创建成功,ID: {}", container.getId());
|
|
log.info("3. 容器创建成功,ID: {}", container.getId());
|
|
|
|
|
|
|
|
// 4. 启动容器
|
|
// 4. 启动容器
|
|
|
|
|
+ // 等价命令: docker start demo-container
|
|
|
dockerClient.startContainerCmd(container.getId()).exec();
|
|
dockerClient.startContainerCmd(container.getId()).exec();
|
|
|
log.info("4. 容器启动成功");
|
|
log.info("4. 容器启动成功");
|
|
|
|
|
|
|
|
// 5. 清理容器(避免污染环境)
|
|
// 5. 清理容器(避免污染环境)
|
|
|
|
|
+ // 等价命令: docker rm -f demo-container
|
|
|
dockerClient.removeContainerCmd(container.getId())
|
|
dockerClient.removeContainerCmd(container.getId())
|
|
|
.withForce(true)
|
|
.withForce(true)
|
|
|
.exec();
|
|
.exec();
|