使用 docker-client 对docker Engine 进行调用

使用 docker-client 对docker Engine 进行调用

前提:一段时间以来,使用程序操作docker都是通过shell脚本进行操作,这种方法有很大的弊端(个人理解分为以下几点:)

1、对并发处理不友好

1.1、如果生成shell脚本,脚本前面路径加上UUID,只要脚本中的变量(例如路径)都是唯一的,这种做法是行的通的。(Linux 多用户,多任务)

举例Java程序执行Java代码调用脚本:

    public synchronized static String execCommand(String[] command){
        log.info("将要执行命令{}", JSONObject.toJSONString(command));
        StringBuilder result = new StringBuilder();
        try {
//            String image = "nginx-xi1:latest";
//            String[] command = new String[]{"docker","build","-t",image,"/root/xiqingsong/docker/642B426072C773F3BFCB6B408932594E"};
            Process ps = Runtime.getRuntime().exec(command);
            ps.waitFor();
            BufferedReader bufrIn = new BufferedReader(new InputStreamReader(ps.getInputStream(), "UTF-8"));
            BufferedReader bufrError = new BufferedReader(new InputStreamReader(ps.getErrorStream(), "UTF-8"));
            // 读取输出 result是shell中的输出
//            StringBuilder result = new StringBuilder();
            String line = null;
            while ((line = bufrIn.readLine()) != null || (line = bufrError.readLine()) != null) {
                result.append(line).append('\n');
            }
            log.info(result.toString());
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

通过上面代码示例发现一个方法 Process.waitFor() 先看看方法的说明:

Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
导致当前线程在必要时等待,直到该进程对象所表示的进程终止。如果子进程已经终止,则该方法立即返回。如果子进程尚未终止,则调用线程将被阻塞,直到子进程退出。

没错,当程序执行Linux命令的时候,该线程必须要等待完成,而且通过执行结果也很难判断出是否成功。当然shell脚本的话可能通过是不是 “exit 1” 进行判断。
同时 还需要判断执行时间,为程序设置等待超时时间。(不到实在没有解决方案的时候,慎用)

1.2 、对事务管理不友好

1.3、异常处理比较复杂

**没有调查没有发言权,1.2 1.3 这个我没有验证,公司大佬告诉我这个问题,我先写上

2、选择合适的SDK

官方地址:https://docs.docker.com/engine/api/sdk/examples/

2.1 、官方只给出了两种语言操作docker Engine的示例(go 、 Python)

在这里插入图片描述

当然除了这两种语言之外,官方下面推荐以下SDK

在这里插入图片描述

在这里插入图片描述

3、正文 目前Java用于操作docker 常用的工具有两种:

在这里插入图片描述

3.1、操作docker 需要配置开放远程调用的端口,和证书的配置

有兴趣的同学可以去看官网上的介绍和操作步骤:https://docs.docker.com/engine/security/https/

下面是我借鉴其他博客实测过后生成证书的脚本:

#创建 Docker TLS 证书
#!/bin/bash

#相关配置信息
SERVER="192.168.80.136"
PASSWORD="123123"
COUNTRY="CN"
STATE="北京市"
CITY="北京市"
ORGANIZATION="本地测试"
ORGANIZATIONAL_UNIT="Dev"
EMAIL="119@qq.com"

###开始生成文件###
echo "开始生成文件"

#切换到生产密钥的目录
cd /etc/docker   
#生成ca私钥(使用aes256加密)
openssl genrsa -aes256 -passout pass:$PASSWORD  -out ca-key.pem 2048
#生成ca证书,填写配置信息
openssl req -new -x509 -passin "pass:$PASSWORD" -days 3650 -key ca-key.pem -sha256 -out ca.pem -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$SERVER/emailAddress=$EMAIL"

#生成server证书私钥文件
openssl genrsa -out server-key.pem 2048
#生成server证书请求文件
openssl req -subj "/CN=$SERVER" -new -key server-key.pem -out server.csr
#使用CA证书及CA密钥以及上面的server证书请求文件进行签发,生成server自签证书
openssl x509 -req -days 3650 -in server.csr -CA ca.pem -CAkey ca-key.pem -passin "pass:$PASSWORD" -CAcreateserial  -out server-cert.pem

#生成client证书RSA私钥文件
openssl genrsa -out key.pem 2048
#生成client证书请求文件
openssl req -subj '/CN=client' -new -key key.pem -out client.csr

sh -c 'echo "extendedKeyUsage=clientAuth" > extfile.cnf'
#生成client自签证书(根据上面的client私钥文件、client证书请求文件生成)
openssl x509 -req -days 3650 -in client.csr -CA ca.pem -CAkey ca-key.pem  -passin "pass:$PASSWORD" -CAcreateserial -out cert.pem  -extfile extfile.cnf

#更改密钥权限
chmod 0400 ca-key.pem key.pem server-key.pem
#更改密钥权限
chmod 0444 ca.pem server-cert.pem cert.pem
#删除无用文件
rm client.csr server.csr

echo "生成文件完成"
###生成结束###

脚本来源:https://blog.csdn.net/qq_21187515/article/details/90268345

3.2 、 配置docker 添加证书

1> 获取docker 启动的时候加载的配置文件(由于环境安装的都不一定一样,所以这个路径可能会变)

在这里插入图片描述

2> 编辑文件 添加证书

--tlsverify \
--tlscacert=/etc/docker/ca.pem \ 
--tlscert=/etc/docker/server-cert.pem \          
--tlskey=/etc/docker/server-key.pem \     
-H tcp://0.0.0.0:2376 \    
-H unix:///var/run/docker.sock 

3.3 、重启docker

在这里插入图片描述

可以看到端口已经监听了

3.4 、验证配置是否成功

在这里插入图片描述

3.5 、问题解决

Get http://192.168.80.136:2376/v1.26/images/json: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02".
* Are you trying to connect to a TLS-enabled daemon without TLS? 

在这里插入图片描述

如果你出现这个问题,不要着急,下面是解决方案

在这里插入图片描述

原因分析:解决方法来源:http://tinylab.org/use-docker-without-sudo/

  • - 因为 /var/run/docker.sock 所属 docker 组具有 setuid 权限
    - 1. $ sudo ls -l /var/run/docker.sock
      2. srw-rw---- 1 root docker 0 May  1 21:35 /var/run/docker.sock
    

4、程序调用

maven添加:

<dependency>
    <groupId>com.spotify</groupId>
    <artifactId>docker-client</artifactId>
    <version>8.16.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.27</version>
</dependency>

代码实现:

package com.qyos.docker.utils;

import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerCertificates;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.exceptions.DockerCertificateException;
import com.spotify.docker.client.exceptions.DockerException;
import com.spotify.docker.client.messages.Image;
import com.spotify.docker.client.messages.RegistryAuth;
import lombok.extern.slf4j.Slf4j;

import java.net.URI;
import java.nio.file.Paths;
import java.util.List;

/**
 * @Author xiqingsong
 * @CreateTime 2020/4/28 15:46
 * docker 客户端统一处理docker操作
 **/
@Slf4j
public class DockerUtils {
    static DockerClient docker;

    static {
        try {
            docker = DefaultDockerClient.builder()
                    .uri(URI.create("https://192.168.80.136:2376"))
                    .dockerCertificates(new DockerCertificates(Paths.get("/etc/docker/")))  //jar 部署位置所需docker服务端的证书
                    .build();
        } catch (DockerCertificateException e) {
            e.printStackTrace();
        }
    }


    public static boolean getImageList(){
        try {
            List<Image> quxImages = docker.listImages();
            log.info(quxImages.toString());
            return true;
        } catch (DockerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }

}

5 、docker-client 操作手册

官方文档: https://github.com/spotify/docker-client/blob/master/docs/user_manual.md

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值