前言:Docker直接开启2375端口是不安全的,别人只要连上之后就可以任意操作,下面是开启Docker的TLS和CA认证方法,并使用Jenkins和Portainer连接。

一、生成证书

查看服务器主机名

hostname

image-20210826174816658

安装生成证书软件

yum install -y openssl

image-20210827003357785

编写一键启动脚本

auto-generate-docker-tls-ca.sh

# !/bin/bash

# 一键生成TLS和CA证书

# Create : 2021-08-25
# Update : 2021-08-25
# @Autor : wuduoqiang

# 服务器主机名
SERVER="6c377ffb8e86"
# 密码
PASSWORD="2cx&BUjsV4u%3TW9"
# 国家
COUNTRY="CN"
# 省份
STATE="海南省"
# 城市
CITY="海口市"
# 机构名称
ORGANIZATION="小强崽公司"
# 机构单位
ORGANIZATIONAL_UNIT="小强崽单位"
# 邮箱
EMAIL="875667601@qq.com"

# 生成CA密钥
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-cert.pem -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$SERVER/emailAddress=$EMAIL"

# 生成服务端密钥
openssl genrsa -out server-key.pem 2048

# 生成服务端证书签名的请求文件
openssl req -subj "/CN=$SERVER" -new -key server-key.pem -out server-req.csr

# 生成服务端证书
openssl x509 -req -days 3650 -in server-req.csr -CA ca-cert.pem -CAkey ca-key.pem -passin "pass:$PASSWORD" -CAcreateserial -out server-cert.pem

# 生成客户端密钥
openssl genrsa -out client-key.pem 2048

# 生成客户端证书签名的请求文件
openssl req -subj '/CN=client' -new -key client-key.pem -out client-req.csr

# 生成客户端证书
sh -c 'echo "extendedKeyUsage=clientAuth" >> extfile.cnf'
openssl x509 -req -days 3650 -in client-req.csr -CA ca-cert.pem -CAkey ca-key.pem  -passin "pass:$PASSWORD" -CAcreateserial -out client-cert.pem -extfile extfile.cnf

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

image-20210826171824402

文件说明

ca.srl:CA签发证书的序列号记录文件
ca-cert.pem:CA证书
ca-key.pem:CA密钥
server-key.pem:服务端密钥
server-req.csr:服务端证书签名请求文件
server-cert.pem:服务端证书
client-key.pem:客户端密钥
extfile.cnf:客户端证书扩展配置文件
client-req.csr:客户端证书签名请求文件
client-cert.pem:客户端证书

命令解析

# -subj /C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$SERVER/emailAddress=$EMAIL
-subj 是 指定证书申请人的信息
C  是 Country Name
ST 是 State or Province Name
L  是 Locality Name
O  是 Organization Name
OU 是 Organizational Unit Name
CN 是 Common Name
emailAddress 是 Email Address

image-20210826175455378

二、开启远程

开启Docker的远程访问API

# 编辑文件
vim /etc/systemd/system/docker.service
# 修改内容,注意证书的指定位置
ExecStart=/usr/bin/dockerd \
--tlsverify \
--tlscacert=/etc/docker/ca-cert.pem \
--tlscert=/etc/docker/server-cert.pem \
--tlskey=/etc/docker/server-key.pem \
-H unix:///var/run/docker.sock \
-H tcp://0.0.0.0:2375
# 重启服务
systemctl daemon-reload && systemctl restart docker

image-20210826224926640

如果没有密钥和证书是连不上的

docker -H 192.168.8.248:2375 images

image-20210826170502465

使用主机名没有密钥和证书也是连不上的

docker -H 6c377ffb8e86:2375 images

image-20210826175645656

加上密钥和证书没有使用主机名也是连不上

curl https://192.168.8.248:2375/info --cert ./client-cert.pem --key ./client-key.pem --cacert ./ca-cert.pem

image-20210826175827579

加上密钥和证书并且使用主机名就能访问

curl https://6c377ffb8e86:2375/info --cert ./client-cert.pem --key ./client-key.pem --cacert ./ca-cert.pem

image-20210826175911595

三、远程连接

3.1 Jenkins连接

添加凭证

image-20210826005144524

填写信息

image-20210826005835157

测试连接,注意这里要使用主机名

image-20210826180407741

如果是docker安装的jenkins,则需要映射主机名

version: '3'
services:
  jenkins:
    restart: always
    image: 192.168.8.247/xiaoqiangzai/jenkins:latest
    container_name: jenkins
    ports:
      - '8888:8080'
      - '50000:50000'
    volumes:
      - ./data/jenkins_home:/var/jenkins_home
      - ./data/war/jenkins.war:/usr/share/jenkins/jenkins.war
    environment:
      JENKINS_OPTS: "--prefix=/jenkins"
    extra_hosts:
      - "6c377ffb8e86:192.168.8.248"

3.2 Portainer连接

选择客户端密钥和证书以及CA证书

image-20210826225329003

连接正常

image-20210826225451405

如果是docker安装的Portainer,则需要映射主机名

version: '3'
services:
  portainer:
    restart: always
    image: portainer/portainer-ce:latest
    container_name: portainer
    privileged: true
    ports:
      - '9000:9000'
    volumes:
      - ./data/data:/data
      - ./data/public:/public
    extra_hosts:
      - "6c377ffb8e86:192.168.8.248"

3.3 Java连接

导入依赖

<!-- java连接docker依赖 -->
<dependency>
    <groupId>com.github.docker-java</groupId>
    <artifactId>docker-java</artifactId>
    <version>3.2.12</version>
</dependency>
<!-- 域名解析依赖 -->
<dependency>
    <groupId>io.leopard</groupId>
    <artifactId>javahost</artifactId>
    <version>0.9.12</version>
</dependency>

域名映射

dns.properties

dockerd=192.168.1.54

image-20221202034011134

加载配置

DnsConfig

/**
 * @author: 小强崽
 * @create: 2022/12/2 3:27
 * @description: 加载域名解析配置
 **/
@Configuration
public class DnsConfig {

    /**
     * 加载域名解析配置
     *
     * @throws IOException IO异常
     */
    @Bean
    public void loadDns() throws IOException {
        Resource resource = new ClassPathResource("dns.properties");
        Properties props = PropertiesLoaderUtils.loadProperties(resource);
        JavaHost.updateVirtualDns(props);
    }
}

由于上面生成文件名在java连接docker依赖有点区别,这里需要修改下改一下文件名,并放到指定目录

ca-key.pem -> ca-key.pem

ca-cert.pem -> ca.pem

client-cert.pem -> cert.pem

client-key.pem -> key.pem

创建Docker客户端连接

/**
 * 创建docker连接
 *
 * @return DockerClient
 */
public static DockerClient dockerClient() {
    // 构建连接配置
    DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
            .withDockerHost(dockerHost)
            .withDockerTlsVerify(true)
            .withDockerCertPath("D:\\File\\IDEAProject\\GitHubProject\\docker-service\\src\\main\\resources\\cert")
            .build();
    // 获取docker连接方式
    return DockerClientBuilder.getInstance(dockerClientConfig).build();
}

image-20221202043213228

调用接口

image-20221202043451752

请求正常

image-20221202043525698

如果不配置证书则调用失败

image-20221202043754785