idea 连接远程docker 防止docker 镜像和容器占用本地太多空间

远程连接Docker有如下三种方式

方式一:开启 TCP(不带 TLS,仅用于内网调试)

  • 在docker服务端编辑 /etc/docker/daemon.json,加上:

{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
 
  • 此时通过sudo systemctl restart docker重启 Docker会启动失败,原因是systemd会在docker启动命令中添加 -H fd://,其含义是从 systemd 传递进来的 socket 文件描述符监听 API 请求,当 Docker 被 systemd 启动并启用 socket activation(套接字激活)时,systemd 会预先创建 socket(比如 /var/run/docker.sock),然后再启动 dockerd,并通过文件描述符(fd)把这个 socket 传递给 dockerd。此时你在 dockerd 中看到的 -H fd:// 意思是:“不用自己打开 socket,去 systemd 那里拿吧。”

# 通过该命令可以获取 docker 的启动命令文件是 /usr/lib/systemd/system/docker.service
sudo systemctl status docker
# 查看 /usr/lib/systemd/system/docker.service,可以看到 docker的启动命令如下,可以看到 -H fd://
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# 另外可以在与 docker.service 同目录下找到 docker.socket 文件,可以看到如下内容
ListenStream=/run/docker.sock # /run 目录是被软连接到 /var/run/

# 总结:通过systemd 启动 docker时,如果配置了 -H fd://,则 docker 会监听 /run/docker.sock 文件,实际上也就是 /var/run/docker.sock
# 而我们在/etc/docker/daemon.json中加上的"unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"实际上就是改写docker的启动参数,这就与 systemd 启动 docker 的 `-H fd://` 参数冲突了
# 此时我们可以不使用systemd 启动 docker,而是使用 docker daemon 启动 docker
sudo dockerd --containerd=/run/containerd/containerd.sock
# 但这样不利于 docker 的管理,因此最好的方式是禁用 `-H fd://`
 
  • 禁用 -H fd://(systemd 与 daemon.json 冲突的根源)

# 方式一: 去掉 `-H fd://` 参数
sudo vi /usr/lib/systemd/system/docker.service

# 方式二(推荐): 创建 override.conf 文件,其作用是 覆盖 systemd 默认配置文件,只会覆盖指定的参数
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vi /etc/systemd/system/docker.service.d/override.conf
# 填入
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
# 这里顺便说一下,`--containerd=/run/containerd/containerd.sock` 是 docker 默认参数,
# 告诉 Docker 守护进程去连接已有的 containerd 实例,而不是自己启动一个新的。
# Docker 默认内部使用 containerd 来管理容器运行时,所以这条参数是明确指定要使用哪个 containerd 服务。
 
  • 重启 docker daemon

sudo systemctl daemon-reload
sudo systemctl restart docker
 
  • 在客户端测试连接

docker -H tcp://远程IP:2375 ps
 
  • 在客户端加入环境变量后就不需要每次都加上 -H 参数了

# zsh 就换成 ~/.zshrc
echo "export DOCKER_HOST=tcp://远程IP:2375" >> ~/.bashrc
source ~/.bashrc
# 测试
docker ps
 
  • ❗不要开启无认证的 tcp://0.0.0.0:2375 在公网,这是裸奔的安全风险,任何人都能控制你的 Docker。

  • ✅ 推荐方式是:

    • 使用 tcp://0.0.0.0:2376 + --tlsverify
    • 或通过 ssh:// 隧道 访问 Docker

小贴士

  • 通过上面的介绍你应该搞明白一件事,就是我们可以不用在 /etc/docker/daemon.json 中配置远程连接,而是通过 systemd 来配置,即在 /usr/lib/systemd/system/docker.service 或者 /etc/systemd/system/docker.service.d/override.conf中配置。
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
 
  • 那么问题来了:既然 systemd 就能搞定一切,那还要 /etc/docker/daemon.json 有什么用?答案是:可读性、可维护性、工具兼容性更强。
项目daemon.jsonsystemd ExecStart
语法 JSON Shell 命令行
适合设置 Hosts、日志、registry、镜像驱动等 启动命令、资源限制等
可读性 👍 结构化 👎 较长、容易出错
自动化支持 👍 工具友好 👎 需要 patch systemd

方式二:开启 TCP + TLS 安全访问(推荐用于公网)

  • 创建 TLS 证书,通过一个脚本实现,脚本名称 generate-docker-certs.sh

#!/bin/bash

set -e

SERVER_IP=166.189.9.114 # 🚨 修改为你的 Docker 服务器 IP 或域名

echo "[+] 创建 CA..."
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 365 \
-key ca-key.pem -subj "/CN=docker-ca" -out ca.pem

echo "[+] 创建服务器私钥..."
openssl genrsa -out server-key.pem 4096

echo "[+] 创建 OpenSSL 配置文件..."
cat > extfile.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = ${SERVER_IP}

[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
IP.1 = ${SERVER_IP}
EOF

echo "[+] 创建服务器证书签名请求 (CSR)..."
openssl req -new -key server-key.pem \
-out server.csr -config extfile.cnf

echo "[+] 签发服务器证书..."
openssl x509 -req -days 365 -in server.csr \
-CA ca.pem -CAkey ca-key.pem -CAcreateserial \
-out server-cert.pem -extensions v3_req -extfile extfile.cnf

echo "[+] 创建客户端私钥..."
openssl genrsa -out key.pem 4096

echo "[+] 创建客户端 CSR..."
openssl req -new -key key.pem -subj "/CN=client" -out client.csr

echo "[+] 签发客户端证书..."
cat > client-ext.cnf <<EOF
extendedKeyUsage = clientAuth
EOF

openssl x509 -req -days 365 -in client.csr \
-CA ca.pem -CAkey ca-key.pem -CAcreateserial \
-out cert.pem -extfile client-ext.cnf

echo "[✓] 所有证书生成完成!"
echo
echo " 服务器证书: server-cert.pem, server-key.pem"
echo " 客户端证书: cert.pem, key.pem"
echo " CA根证书: ca.pem"
 
  • 执行脚本

chmod +x generate-docker-certs.sh
./generate-docker-certs.sh
 
  • 将以下证书文件部署到docker服务端

# 服务端:server-cert.pem, server-key.pem, ca.pem
cp server-cert.pem /etc/docker/server-cert.pem
cp server-key.pem /etc/docker/server-key.pem
cp ca.pem /etc/docker/ca.pem
 
  • 将以下证书文件部署到docker客户端

cert.pem, key.pem, ca.pem
 
  • 在docker服务端编辑 /etc/docker/daemon.json

{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tlsverify": true,
"tlscacert": "/etc/docker/ca.pem",
"tlscert": "/etc/docker/server-cert.pem",
"tlskey": "/etc/docker/server-key.pem"
}
 
  • 禁用 -H fd://(systemd 与 daemon.json 冲突的根源)

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vi /etc/systemd/system/docker.service.d/override.conf
# 填入
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --containerd=/run/containerd/containerd.sock
 
  • 重启 docker daemon

sudo systemctl daemon-reload
sudo systemctl restart docker
 
  • 在客户端测试连接

docker \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H tcp://166.189.9.114:2376 \
ps
 
  • 在客户端加入环境变量后就不需要每次都加上 -H 参数 和证书参数了

cat <<EOT >> ~/.bashrc
# 远程Docker IP和端口
export DOCKER_HOST=tcp://166.189.9.114:2376
# 用于通过 TLS(SSL)安全连接远程 Docker 守护进程,类似于 docker --tlsverify
export DOCKER_TLS_VERIFY=1
# 这个目录下要有这些证书文件:ca.pem, cert.pem, key.pem
export DOCKER_CERT_PATH=/path/to/certs
EOT
source ~/.bashrc
# 测试
docker ps
 

方式三:ssh:// 隧道访问

  • 最简单的方式就是使用 ssh 远程执行命令的方式,这种方式不需要任何配置,支持密码和证书认证,也支持指定端口,但这不是标准的远程连接docker方式,适用于偶尔访问的情况。

ssh -i ~/.ssh/lexing-test.pem -p22 centos@166.189.9.114 "docker ps"
 
# docker -H 远程访问 不支持在命令行直接输入密码或密钥文件,必须配置免密登录才可以,而且此时端口必须是默认的22
# 要求登录用户必须拥有docker的运行权限(加入 docker group)
docker -H ssh://centos@166.189.9.114 ps
 
  • 基于config配置(推荐)

    • 这种方式的优点是可以配置证书和端口
    • 在 ~/.ssh/config 中指定具体的密钥文件和端口,登录用户必须拥有docker的运行权限(加入 docker group)
    Host mydocker
    HostName 166.189.9.114
    User centos
    Port 22
    IdentityFile ~/.ssh/my_docker_key
     
    • 测试
    docker -H ssh://mydocker ps
     
  • 添加环境变量避免每次都加上 -H 参数

## 基于免密认证
echo "export DOCKER_HOST=ssh://user@host" >> ~/.bashrc
## 或者基于config的方式
echo "export DOCKER_HOST=ssh://mydocker" >> ~/.bashrc
source ~/.bashrc
docker ps
 

docker context: 同时连接多个远程docker

  • 上面介绍的三种方式,为了简化连接,都加上了DOCKER_HOST环境变量,但是DOCKER_HOST只能配置一个,如果我们要同时连接多个远程docker服务呢,每次切换DOCKER_HOST环境变量太过繁琐,可以通过下面的方式为每个远程docker服务创建一个 context

# TCP
docker context create remote-tcp \
--docker "host=tcp://166.189.9.114:2375"

# TCP + TLS
docker context create remote-tls \
--docker "host=tcp://166.189.9.114:2376,ca=/path/ca.pem,cert=/path/cert.pem,key=/path/key.pem"

# ssh隧道
docker context create remote-ssh --docker "host=ssh://mydocker"

# 使用
docker context ls # 列出所有context
docker context use remote-ssh # 切换到指定的context
docker ps # 查看容器
 
  • docker context 是 Docker CLI 的一个强大功能,它让你可以轻松地在 多个 Docker 后端环境之间切换,比如:

    • 本地 Docker(默认)
    • 远程主机的 Docker(通过 SSH 或 TCP/TLS)
    • Docker Desktop
    • Docker Swarm 或 Kubernetes(部分支持)
  • 就像你用 kubectl config use-context 切换 Kubernetes 集群,docker context 也允许你在多个 Docker 后端之间切换,而无需反复设置 DOCKER_HOST 环境变量或写繁琐的 SSH 隧道命令。

  • 常用命令一览

命令说明
docker context ls 列出所有上下文
docker context use <name> 切换到指定 context
docker context create <name> --docker "Docker endpoint config" 创建一个新的 context
docker context rm <name> 删除 context
docker context inspect <name> 查看 context 详情
docker context update <name> --docker "Docker endpoint config" 更新 context 参数(Docker 24+ 支持)
docker context show 显示当前 context
docker context export <name> <file.tar> 导出 context 到tar文件
docker context import <name> <file.tar> 导入 context 从tar文件
  • Docker endpoint config

参数名中文描述
from 复制指定 context 名称 的 Docker 端点配置
host 要连接的 Docker 端点地址
ca CA 签名的证书的路径
cert TLS 证书文件的路径
key TLS 密钥文件的路径
skip-tls-verify 跳过 TLS 证书验证(⚠️ 不建议用于生产环境)

三种远程连接 Docker 的方式及其优缺点总结

 

连接方式优点缺点适用场景
1. SSH 方式 (ssh://) - 配置简单,无需额外开启 Docker TCP 端口和 TLS
- 安全性高,基于 SSH 加密和认证
- 不用开放额外端口,防火墙友好
- 易于用 SSH 代理和密钥管理
- 需要远程用户有 Docker 权限(如属于 docker 组)
- 连接速度可能受 SSH 连接影响
- 需要在本地安装并配置 SSH
开发环境、内网管理、小规模远程操作
2. TCP + TLS 方式 - 标准的远程 Docker API 访问
- 支持证书认证,安全性高
- 可以配置多个客户端和权限控制
- 适合自动化脚本、CI/CD 访问
- 配置较复杂,需要生成和管理 CA、服务器和客户端证书
- 需要开放 TCP 端口(如 2376),增加安全风险
- 证书配置错误容易导致连接失败
生产环境、自动化集成、需要高安全认证
3. TCP 明文访问(无 TLS) - 配置最简单,只需监听 TCP 端口
- 方便快速测试和调试
- 极度不安全,数据明文传输
- 任何人都可访问 Docker API,极易被攻击
- 生产环境严重不建议使用
仅限局域网内测试或极简环境
  如要连接idea docker 需要重新生成服务端和客户端证书
1. 强行编写服务端扩展配置
创建(或覆盖)server.ext,在里面必须显式锁死 digitalSignaturekeyEncipherment 以及 serverAuth
bash
cat > server.ext << EOF
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:你的远程服务器公网IP,IP:你的远程服务器公网IP,IP:127.0.0.1
EOF

2. 重新用你的 CA 签名生成服务端证书
bash
openssl x509 -req -days 3650 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
  -CAcreateserial -out server-cert.pem -extfile server.ext

3. 将新证书部署到 Docker 并重启
把刚生成的 server-cert.pem 复制到 Docker 的配置目录下(替换掉旧的服务端证书文件),然后重启远程 Docker 服务:
bash
sudo systemctl restart docker

请切回你存放 CA 证书的目录,直接执行以下命令:
  1. 强行编写客户端扩展配置:
    bash
    cat > client.ext << EOF
    keyUsage = critical, digitalSignature, keyEncipherment
    extendedKeyUsage = clientAuth
    EOF
      2 .重新使用 CA 签名生成客户端证书(★注意:这次必须加上 -extfile client.ext):
    bash
    openssl x509 -req -days 3650 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
      -CAcreateserial -out client-cert.pem -extfile client.ext3.在服务器上肉眼验证(关键步骤)在把证书下载前,先在服务器终端运行这行命令,查看证书的权限是否真的写进去了:
    bash
    openssl x509 -in client-cert.pem -noout -text
    检查输出的文本中,有没有包含下面这两行。必须看到它们,IDEA 才会放行:
    X509v3 Key Usage: critical
    Digital Signature, Key Encipherment
    idea  指定本地 compose

    image

     

     
来源: https://blog.hanqunfeng.com/2025/06/05/docker-remote-connection/
posted @ 2026-09-11 15:17  2022——new_start  阅读(2)  评论(0)    收藏  举报