ImageManageAPI.java 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package space.anyi.docker;
  2. import com.github.dockerjava.api.DockerClient;
  3. import com.github.dockerjava.api.command.InspectImageResponse;
  4. import com.github.dockerjava.api.command.PullImageResultCallback;
  5. import com.github.dockerjava.api.model.Image;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import java.util.Arrays;
  9. import java.util.List;
  10. /**
  11. * Docker 镜像管理 API 示例
  12. * 演示拉取、列出、查看详情、删除、标记、导入导出等镜像操作
  13. */
  14. public class ImageManageAPI {
  15. private static final Logger log = LoggerFactory.getLogger(ImageManageAPI.class);
  16. private final DockerClient dockerClient;
  17. public ImageManageAPI() {
  18. // 使用工厂类创建统一的 DockerClient 实例
  19. this.dockerClient = DockerClientFactory.createDockerClient();
  20. }
  21. /**
  22. * 列出自定义节点上所有存在的镜像
  23. * @return 镜像列表
  24. */
  25. public List<Image> listImages() {
  26. List<Image> images = dockerClient.listImagesCmd()
  27. .withShowAll(true) // 展示所有镜像(包括中间层)
  28. .exec();
  29. log.info("本机共有 {} 个镜像", images.size());
  30. return images;
  31. }
  32. /**
  33. * 获取镜像的详细信息
  34. * 包括镜像的 ID、仓库、标签、创建时间、大小、Layer 等
  35. * @param imageId 镜像 ID 或名称
  36. * @return 镜像详情
  37. */
  38. public InspectImageResponse inspectImage(String imageId) {
  39. InspectImageResponse response = dockerClient.inspectImageCmd(imageId).exec();
  40. log.info("镜像 {} 详情: {}", imageId, response);
  41. return response;
  42. }
  43. /**
  44. * 拉取指定名称的镜像
  45. * 优化:如果本地已存在同名镜像则直接使用,无需访问网络
  46. * @param imageName 镜像名称,如 "hello-world" 或 "nginx:latest"
  47. * @return 拉取是否成功
  48. */
  49. public boolean pullImage(String imageName) {
  50. // 先检查本地是否已存在该镜像,避免无谓的网络访问
  51. boolean exists = dockerClient.listImagesCmd().exec().stream()
  52. .anyMatch(img -> img.getRepoTags() != null &&
  53. Arrays.asList(img.getRepoTags()).contains(imageName));
  54. if (exists) {
  55. log.info("镜像 {} 已存在于本地,跳过拉取", imageName);
  56. return true;
  57. }
  58. try {
  59. // exec() 执行命令,awaitCompletion() 阻塞等待镜像拉取完成
  60. dockerClient.pullImageCmd(imageName)
  61. .exec(new PullImageResultCallback())
  62. .awaitCompletion();
  63. log.info("镜像 {} 拉取成功!", imageName);
  64. return true;
  65. } catch (InterruptedException e) {
  66. log.error("镜像拉取被中断: {}", e.getMessage());
  67. Thread.currentThread().interrupt();
  68. return false;
  69. }
  70. }
  71. /**
  72. * 删除本地镜像
  73. * @param imageId 镜像 ID 或名称
  74. * @param force 是否强制删除(即使镜像被容器使用)
  75. */
  76. public void removeImage(String imageId, boolean force) {
  77. dockerClient.removeImageCmd(imageId)
  78. .withForce(force) // 强制删除
  79. .exec();
  80. log.info("镜像 {} 已删除", imageId);
  81. }
  82. /**
  83. * 为镜像添加标签(相当于 docker tag)
  84. * @param imageId 源镜像 ID 或名称
  85. * @param repository 新的仓库名
  86. * @param tag 新的标签名
  87. */
  88. public void tagImage(String imageId, String repository, String tag) {
  89. dockerClient.tagImageCmd(imageId, repository, tag).exec();
  90. log.info("镜像 {} 已标记为 {}:{}", imageId, repository, tag);
  91. }
  92. /**
  93. * 检查本地是否存在指定镜像
  94. * @param imageName 镜像名称(仓库名:标签)
  95. * @return 是否存在
  96. */
  97. public boolean checkImageExists(String imageName) {
  98. boolean exists = dockerClient.listImagesCmd().exec().stream()
  99. .anyMatch(img -> img.getRepoTags() != null &&
  100. Arrays.asList(img.getRepoTags()).contains(imageName));
  101. log.info("镜像 {} 是否存在: {}", imageName, exists);
  102. return exists;
  103. }
  104. }