天天看点

使用Docker-java API对容器化操作Docker-java 简介

使用Docker-java API对容器化操作

  • Docker-java 简介
    • 入门案例介绍
    • Docker Remote API
    • Docker Remote API 打开后可能存在的隐患(重要)
    • Docker客户端与服务端TLS认证(Docker Remote API认证)
    • 使用TLS认证案例

Docker-java 简介

Docker-java是一个开源的项目,目前托管在github上,拥有一套完整的API,用以操作docker服务.

github地址:docker-java,

基本入手文档:docker-java入门文档

测试demo需要将代码下载后,在docker-java/docker-java/src/test目录下,可以用于学习

入门案例介绍

``使用Docker-java上传镜像到私有化镜像仓库

Docker Remote API

Docker Remote API 介绍

Docker Remote API 打开后可能存在的隐患(重要)

Docker Remote API 开启后可能导致机器被控制

Docker客户端与服务端TLS认证(Docker Remote API认证)

使用合理的方式开启Docker Remote API,参考此文章讲了部分步骤,但是生成理念是错误的

Docker Remote API,开启TLS认证官方CA证书生成文档

推荐

使用脚本,一键生成CA证书信息,包含服务端,客户端

使用TLS认证案例

导入docker-java 相关maven依赖

<dependency>
            <groupId>com.github.docker-java</groupId>
            <artifactId>docker-java-core</artifactId>
            <version>3.2.7</version>
        </dependency>
        <dependency>
            <groupId>com.github.docker-java</groupId>
            <artifactId>docker-java-transport-httpclient5</artifactId>
            <version>3.2.7</version>
        </dependency>

           

配置文件

#docker访问路径
docker.url=tcp://${IP}2376
#私服仓库配置
harbor.login_address=${IP}:5000
#私有仓库用户名,如果无,值可以不填写
harbor.username=xxx
#私有仓库密码,如果无,值可以不填写
harbor.password=xxx
#docker client证书地址,如果使用TLS必填
docker.cert.path="/Users/test/.docker"
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold =0
           

创建docker-java 工具类

package com.persion.docker.utils;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.model.AuthConfig;
import com.github.dockerjava.api.model.Image;

import com.github.dockerjava.core.DefaultDockerClientConfig;

import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.core.LocalDirectorySSLConfig;

import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.github.dockerjava.transport.DockerHttpClient;
import com.github.dockerjava.transport.SSLConfig;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;


import java.io.InputStream;

import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * docker工具类
 */
@Component
public class DockerUtils {

    //docker服务器
    @Value("${docker.url}")
    private String DOCKER_URL;

    //私有仓库登录用户名
    @Value("${harbor.username}")
    private String HARBOR_USERNAME;

    //私有仓库登录密码
    @Value("${harbor.password}")
    private String HARBOR_PASSWORD;

    //私有仓库的登录地址
    @Value("${harbor.login_address}")
    private String HARBOR_LOGIN_ADDRESS;
    
    // CA证书存放位置
    @Value("${docker.cert.path}")
    private String DOCKER_CERT_PATH;

    /**
     * 获取docker链接
     *
     * @return
     */
    public DockerClient getDockerClient() {
        DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(DOCKER_URL)
                .withRegistryUsername(HARBOR_USERNAME)
                .withRegistryPassword(HARBOR_PASSWORD)
                .withRegistryUrl(HARBOR_LOGIN_ADDRESS)
                .withDockerTlsVerify(true)
                .withDockerCertPath(DOCKER_CERT_PATH)
                .build();
        
        // 配置docker客户端连接及证书信息
        SSLConfig sslConfig = new LocalDirectorySSLConfig(DOCKER_CERT_PATH);
        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
                .dockerHost(dockerClientConfig.getDockerHost())
                .sslConfig(sslConfig)
                .build();

        // 目前getInstance方法中,只有此方法被推荐
        return DockerClientImpl.getInstance(dockerClientConfig, httpClient);
    }

    /**
     * 参考之前文章《docker---镜像的加载》,镜像如何保存到本地
     * 上传镜像
     *
     * @param file      镜像文件
     * @param imageName
     * @throws Exception
     */
    public void uploadImage(MultipartFile file, String imageName) throws Exception {
        DockerClient dockerClient = getDockerClient();
        InputStream inputStream = file.getInputStream();
        //Harbor登录信息
        AuthConfig autoConfig =
                new AuthConfig().withRegistryAddress(HARBOR_LOGIN_ADDRESS).
                        withUsername(HARBOR_USERNAME).withPassword(HARBOR_PASSWORD);
        //加载镜像
        dockerClient.loadImageCmd(inputStream).exec();
        //获取加载镜像的名称
        String uploadImageName = "";
        String imageFile = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));
        String imageId = imageFile.substring(imageFile.lastIndexOf("_") + 1);
        List<Image> list = dockerClient.listImagesCmd().exec();
        for (Image image : list) {
            // 压缩包可能包含多个对象,只导入指定镜像
            if (image.getId().contains(imageId)) {
                uploadImageName = image.getRepoTags()[0];
            }
        }

        // 判断是否有这个需求
        //镜像打tag
        dockerClient.tagImageCmd(uploadImageName, imageName, imageName.split(":")[2]).exec();
       
        //push至镜像仓库
        dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion(30, TimeUnit.SECONDS);
        
        //push成功后,删除本地加载的镜像
        // 以下这个应该饭在finally中
        dockerClient.removeImageCmd(imageName).exec();
        dockerClient.removeImageCmd(uploadImageName).exec();
        //关闭文件流,这个应该使用try-catch 的try中
        if (inputStream != null) {
            inputStream.close();
        }
    }

    /**
     * 查询镜像信息
     */

    public List<Image> listImages() {
        return getDockerClient().listImagesCmd().withShowAll(true).exec();
    }

}


           

创建Controller

/*
 * Copyright (C) 2021 Baidu, Inc. All Rights Reserved.
 */
package com.persion.docker.web;

import java.io.File;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.github.dockerjava.api.model.Image;
import com.persion.docker.utils.DockerUtils;

@RestController
public class HarborController {

    // 私有仓库地址
    @Value("${harbor.login_address}")
    private String HOST_HOST;

    @Autowired
    private DockerUtils dockerUtils;
    
    @PostMapping("/uploadImages")
    public String uploadImages(String projectName, String imageName, String tag, MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            return "FILE can't be null!";
        }
        String imageNames = HOST_HOST + "/" + projectName + "/" + imageName + ":" + tag;
        dockerUtils.uploadImage(file, imageNames);
        return "SUCCESS";
    }

    @GetMapping("/list/image")
    public List<Image>  listImages() throws Exception {
      return  dockerUtils.listImages();
    }

}