环境变量 HTTP_PROXY/HTTPS_PROXY 深度解析:为什么 cURL 行,Docker 不行?

关键词:HTTP_PROXY、HTTPS_PROXY、代理、Docker、containerd、cURL、systemd、Linux


一、前言

在 Linux 服务器或 Kubernetes 集群中,我们经常会遇到「命令行走代理成功,但后台服务始终连不通」的诡异现象。最典型的例子就是:

bash 复制代码
export HTTP_PROXY=http://192.168.1.100:7897
curl -I https://www.google.com     # ✅ 秒出 200
docker pull hello-world            # ❌ 卡住不动

本文将带你彻底搞懂:

  1. HTTP_PROXY / HTTPS_PROXY 到底影响了谁?
  2. 为什么 cURL 能用,Docker 却用不了
  3. 怎样让 系统级服务 也乖乖走代理?

二、HTTP_PROXY 是什么?

1. 定义

HTTP_PROXY / HTTPS_PROXY进程级别的环境变量 ,用于告诉 支持它的应用程序

"你的 HTTP/HTTPS 请求不要直接发,先发到这个代理地址,由它帮你转发。"

2. 作用域

  • 仅对「读取该变量」的进程有效
  • 谁启动时拿到,谁就用;拿不到就直连
  • 不会自动继承给「已运行」的系统服务

三、实验:同一台机器,三种不同结果

场景 是否走代理 原因
curl www.google.com curl 是当前 shell 子进程,继承了 HTTP_PROXY
wget www.google.com wget 同样读变量
docker pull hello-world dockerdsystemd 服务 ,启动时 没有 这些变量
kubelet 拉镜像 同上,也读不到终端里 export 的变量

四、底层原理:变量传递链条

text 复制代码
┌--------------------┐
│ 终端 export        │──┐
└--------------------┘  │ 继承
                        ▼
┌--------------------┐
│ curl / wget / 其他  │◀- 子进程,能用代理
└--------------------┘

┌--------------------┐
│ dockerd / kubelet  │◀- systemd 启动,**不继承**终端变量
└--------------------┘

结论

临时 export 只能影响「当前 shell 及后续子进程」
对「已开机启动」的系统服务无效!


五、实战:让 Docker 也走代理

1. 写入 systemd

bash 复制代码
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://192.168.1.100:7897"
Environment="HTTPS_PROXY=http://192.168.1.100:7897"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
EOF

2. 重载 & 重启

bash 复制代码
sudo systemctl daemon-reload
sudo systemctl restart docker

3. 验证

bash 复制代码
docker info | grep -i proxy
# 输出里能看到刚写的地址
docker pull hello-world
# 秒拉完成

六、Kubernetes 场景扩展

1. 只让 镜像拉取 走代理

  • 仅给 containerd 配代理(kubelet 不配,避免它连 apiserver 也绕远路)

  • 同样写 systemd:

    bash 复制代码
    sudo mkdir -p /etc/systemd/system/containerd.service.d
    # 同上写 http-proxy.conf
    sudo systemctl restart containerd

2. 给 Pod 内业务 走代理

  • 在 Deployment/Helm 的 env 里显式写:

    yaml 复制代码
    env:
    - name: http_proxy
      value: "http://192.168.1.100:7897"
    - name: https_proxy
      value: "http://192.168.1.100:7897"

七、一张图总结

text 复制代码
终端 export HTTP_PROXY
   │
   ├─▶ 子进程(curl、wget、python 脚本...) ✅
   │
   ├─▶ 后台服务(dockerd、containerd、kubelet) ❌
   │     └─▶ 必须写 systemd 单元文件 ✅
   │
   └─▶ Pod 内容器 ✅
         └─▶ 在 YAML 里显式声明 env ✅

八、常见坑 checklist

现象 排查点
curl 行,Docker 不行 是否给 dockerd 写了 systemd 代理
重启后又失效 代理文件是否在 /etc/systemd/system/服务.service.d/ 目录
空格导致失败 cat -A 查看文件,确认 7897" 后面没有空格
kubelet 连不上 apiserver 不要把 kubelet 的代理指向外网;NO_PROXY 里加上集群内网、apiserver 地址

九、结语

HTTP_PROXY/HTTPS_PROXY 本身很简单,但**"谁能读到它"**决定了流量走向。

记住一句话:

临时 export 只能玩终端;要让系统服务走代理,就去 systemd 写文件!

把这篇博客收藏起来,下次再遇到「cURL 行,Docker 不行」的怪事,5 分钟就能定位解决。

相关推荐
A小辣椒1 天前
TShark:Wireshark CLI 功能
linux
A小辣椒1 天前
TShark:基础知识
linux
AlfredZhao1 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言