前言

为了方便学习和实践,我曾在阿里云以 99 元的价格购买了一台配置为 2 核 2G 的 ECS 服务器,并在其上部署了 Docker。然而,由于平时使用 Docker 的频率较低,我经常会忘记相关命令。同时,在本地开发环境中,我更习惯通过 Docker Desktop 提供的可视化界面进行操作。这让我开始思考,是否可以在本地实现对云服务器上 Docker 的可视化管理。 尽管可以选择在云服务器上部署诸如 Portainer 这样的可视化管理工具,但鉴于这台 99 元服务器的硬件资源相对有限,我决定将可视化部分的职责交给本地机器去承担,而云服务器只负责运行 Docker 并支持远程访问。接下来的文档将记录整个实现过程及相关技术细节,希望能为有类似需求的朋友提供一些参考。

具体流程

允许云服务器的docker支持远程访问

修改docker.service文件

由于我的docker利用了systemd生成服务,所以我们可以看一下我们的Systemd单元文件。

我的系统是Ubuntu,默认位置在/usr/lib/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service containerd.service time-set.target
Wants=network-online.target containerd.service
Requires=docker.socket

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd  -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2380
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutStartSec=0
RestartSec=2
Restart=always

# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3

# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s

# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity

# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity

# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes

# kill only the docker process, not all processes in the cgroup
KillMode=process
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
涉及到此次改动的地方是ExecStart 启动参数的设置,我们需要修改内容,在后面增加参数 

-H tcp://0.0.0.0:2380 代表支持tcp连接,端口号是2380端口(端口号可以自定义)

# 原内容
ExecStart=/usr/bin/dockerd  -H fd:// --containerd=/run/containerd/containerd.sock 

# 新增参数后的内容
ExecStart=/usr/bin/dockerd  -H fd:// --containerd=/run/containerd/containerd.sock  -H tcp://0.0.0.0:2380 

重新加载文件并且重启docker

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
开放端口号

设置完端口后需要将防火墙的对应端口进行开放,ubuntu目前使用的是ufw,Centos可以查看firewall使用说明

# 要不先打开ufw吧
$ sudo ufw enable
# 允许开放端口2380
$ sudo ufw allow 2380/tcp 
# 别忘了把22端口也打开,不然我怕你ssh连的时候突然中断了
$ sudo ufw allow 22

# reload一下
$ sudo ufw reload

当然,如果你使用了云服务器,请记得进入云服务器—> 打开控制台 —> 查看安全组 —> 开放端口范围。

使用Docker desktop可视化远程docker

下载插件Portainer

实在对不起,我研究了一下发现Docker Desktop并没办法直接可视化远程的docker,所以我们需要利用插件Portainer。

在这里插入图片描述

添加远程的环境

选择environment

在这里插入图片描述

选择Standalone

在这里插入图片描述

输入自定义的名字和ip,点击连接

在这里插入图片描述

成功后会出现新增的环境

在这里插入图片描述

进入环境会看到我远程的镜像信息

在这里插入图片描述

安全的访问远端的docker

由于是http://ip:port的形式连接,所以我们是明文传输的,对于暴露在公网上的服务器来说是很不安全的,所以我们目前希望采用TLS加密的方式对我们的连接进行加密处理。

官方文档如下:docker加密通信

登录服务器创建存储证书和加密信息的文件夹
$ mkdir -p /etc/docker/certs
$ cd /etc/docker/certs
生成CA私钥
$ openssl genrsa -aes256 -out ca-key.pem 4096

先别急着执行,我们先看一下这几个参数是干嘛的

  1. -aes256 : 使用AES-256 来加密生成的RSA私钥。AES-256是一种对称加密算法,是私钥的一种保护
    1. 如果生成的私钥文件被未经授权的用户获取到,由于它被加密了,只有知道这个密码的人才能解密这个私钥。所以把私钥进行一次对称加密还是很重要的
  2. -out ca-key.pem : 指定生成的私钥的文件的保存路径和文件名字
  3. 4096 : 指定RSA密钥的长度是 4096位。这玩意越长越安全一般都是2048。
$ openssl genrsa -aes256 -out ca-key.pem 4096
Enter PEM pass phrase: # 需要输入对称加密的密码
Verifying - Enter PEM pass phrase: # 需要再次确认对称加密的密码

看到已经生成私钥了: ca-key.pem

生成CA证书
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

还是不着急执行,我们看一下这几个参数是干嘛的

  1. req : 表示需要处理一个证书请求(Certificate request)
  2. -new -x509 : 表示生成一个新的证书,生成一个X.509格式的证书,这是一种标准的数字证书格式
  3. -days 365 : 表示证书的有效期为365天
  4. -key ca-key.pem : 指定使用的私钥文件
    1. 用这个私钥对新的证书进行签名
    2. ca-key.pem 就是刚才用AES对称加密出来的私钥,所以我们需要先试用刚才对称加密的密码解密出来私钥的内容
  5. -sha256 : 表示使用SHA-256 哈希算法 来对证书的内容进行hash处理,然后用私钥签名
    1. 很明显HASH代表不可逆,安全性很高的一种加密算法了。
  6. -out ca.pem : 指定生成的证书文件的保存路径和文件名。ca.pem就是这个证书的公钥部分。
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
Enter pass phrase for ca-key.pem:  # 输入你刚才对称加密的密码
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]: # 会要求输入一些个人信息,我没输入,我全回车了
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
$ # 生成了
$ ls	# 看到有了证书和原来的私钥
ca-key.pem  ca.pem 
生成客户端/服务器的私钥
$ openssl genrsa -out server-key.pem 4096
$ ls
ca-key.pem  ca.pem  server-key.pem
$ openssl req -subj "/CN=我的ip就不展示了" -sha256 -new -key server-key.pem -out server.csr
$ ls
ca-key.pem  ca.pem  server.csr  server-key.pem

我解释一下上面的命令

  1. CN: 主机名或者ip或者域名,我这里是我的ip
  2. -key server-key.pem : 指定与证书签名请求关联的私钥文件。在这里是 <font style="color:rgb(16, 24, 40);">server-key.pem</font>,它是用户/服务器私钥。私钥为 CSR 提供:
    1. 公钥部分:CSR 包含这个私钥对应的公钥。
    2. 数字签名部分:用私钥对 CSR 内容进行签名,保证请求的完整性和真实性
指定ip

由于 TLS 连接可以通过 IP 地址和 DNS 名称进行,因此在创建证书时需要指定 IP 地址。

将 Docker 守护程序密钥的 extended usage 属性设置为仅用于服务器身份验证。

$ echo subjectAltName = IP:我的ip,IP:127.0.0.1 >> extfile.cnf
$ echo extendedKeyUsage = serverAuth >> extfile.cnf
$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem -extfile extfile.cnf
Certificate request self-signature ok
subject=CN = 我的ip
Enter pass phrase for ca-key.pem: # 记得在这里输入之前AES加密的密码
$ ls # 出现了server-cert.pem
ca-key.pem  ca.pem  ca.srl  extfile.cnf  server-cert.pem  server.csr  server-key.pem
生成客户端的密钥

正常的rsa密钥

$ openssl genrsa -out key.pem 4096

设置客户端的csr凭证

$ openssl req -subj '/CN=client' -new -key key.pem -out client.csr
$ echo extendedKeyUsage = clientAuth > extfile-client.cnf
生成客户端的证书
$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out cert.pem -extfile extfile-client.cnf
保证密钥只有读的权限
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
mode of 'ca-key.pem' changed from 0600 (rw-------) to 0400 (r--------)
mode of 'key.pem' changed from 0600 (rw-------) to 0400 (r--------)
mode of 'server-key.pem' changed from 0600 (rw-------) to 0400 (r--------)


$ chmod -v 0444 ca.pem server-cert.pem cert.pem
mode of 'ca.pem' changed from 0644 (rw-r--r--) to 0444 (r--r--r--)
mode of 'server-cert.pem' changed from 0644 (rw-r--r--) to 0444 (r--r--r--)
mode of 'cert.pem' changed from 0644 (rw-r--r--) to 0444 (r--r--r--)
查看docker的启动参数

下面展示一下启动参数,但是我们不这么做,我们还是选择修改docker.service内容

dockerd \
    --tlsverify \
    --tlscacert=ca.pem \
    --tlscert=server-cert.pem \
    --tlskey=server-key.pem \
    -H=0.0.0.0:2376
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/certs/ca.pem --tlscert=/etc/docker/certs/server-cert.pem --tlskey=/etc/docker/certs/server-key.pem  -H fd:// --containerd=/run/containerd/containerd.sock  -H tcp://0.0.0.0:2380 
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
回到本地机器新建一个文件夹用来存储客户端的密钥
docker --tlsverify \
    --tlscacert=ca.pem \
    --tlscert=cert.pem \
    --tlskey=key.pem \
    -H=$HOST:2376 version
  1. 我创建了一个文件夹在这里插入图片描述

  2. 把服务器的证书下载到本地在这里插入图片描述

  3. 我们要的是ca.pem、cert.pem、key.pem

  4. 下载完毕后是这样在这里插入图片描述

回到本地发现刚才连上的docker已经断开了

在这里插入图片描述

因为我们需要新增一些https的配置了

勾选上我们刚才下载过来的证书信息

在这里插入图片描述

更新后发现活过来了

在这里插入图片描述

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐