环境变量 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 ❌ dockerd 是 systemd 服务 ,启动时 没有 这些变量
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 分钟就能定位解决。

相关推荐
q27551300421 天前
AS8132 DP转HDMI 4K60(420)被动式 国产性价比AS方案
linux·算法·硬件架构·dash
刚入门的大一新生1 天前
Linux-进程间通信2
linux·运维·服务器
电科_银尘1 天前
【深度学习项目实战·02】Linux服务器环境搭建:从SSH登录到稳定运行项目
linux·服务器·深度学习
运维小斌1 天前
麒麟 V10 部署 OceanBase:故障速查与验收清单
linux·数据库·oceanbase·麒麟
水饺编程1 天前
第2章:Linux 基础,在 root 中创建用户账号
linux·c语言·汇编·1024程序员节
叼烟扛炮1 天前
Linux 学习笔记(四):文件检索与管道重定向
linux·笔记·学习
帷幕落秋1 天前
Linux 网络基础
linux
高晶1 天前
ARM 嵌入式 Linux 命令系统 BusyBox 实战指南
linux·设计模式·程序员
祥Sir的SRE笔记1 天前
CPU 100% 不一定是故障:压测打满、业务饱和、突变打满的判断与排查
linux·面试·性能优化·dba·sre·故障定位·性能排查
郝亚军1 天前
在win11上用openssl生成私钥、再从私钥导出公钥、...
linux·运维·服务器