为什么"配了代理还是拉不动镜像"
在服务器上 docker pull 频繁超时,是部署环节最磨人的问题之一。Docker 的代理配置分三个层级:守护进程、构建过程与容器运行时。层级搞混是大多数"配置不生效"的根源——给容器设了环境变量,拉镜像当然不会走代理;反之亦然。
守护进程层:解决镜像拉取
/etc/docker/daemon.json 只能配置镜像加速器,代理必须通过 systemd 环境变量注入:
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
重启后执行 docker info,输出中出现 Proxy 字段即说明守护进程代理已生效,这一层只影响 docker pull 与 docker search。
构建层:用 build-arg 注入代理
构建镜像时,Dockerfile 里的 RUN apt-get、pip install 等步骤不会继承守护进程的代理,需要显式传入构建参数:
docker build \
--build-arg HTTP_PROXY=http://host.docker.internal:7890 \
--build-arg HTTPS_PROXY=http://host.docker.internal:7890 \
-t myapp .
关键点:容器内的 127.0.0.1 指向容器自身而非宿主机,地址必须改写。Docker Desktop 提供了 host.docker.internal 这个域名;Linux 原生环境可用宿主机在 docker0 网桥上的地址(默认 172.17.0.1),或者构建时加 --network host 直接共用宿主网络。
运行时:容器内环境变量
# 单容器临时生效
docker run -e HTTPS_PROXY=http://172.17.0.1:7890 myapp
# 编排场景用 .env 文件持久化
docker run --env-file proxy.env myapp
容器里的应用程序各自读取环境变量,Java 系应用可能还需要额外的 JVM 参数,这一点要查对应镜像的文档。
三个最常见的坑
- 层级混淆: daemon 代理只管镜像拉取,容器内程序的请求需要单独传环境变量。
- 回环地址失效: 容器里的 localhost 不是宿主机,代理地址要写宿主机 IP 或网关地址。
- 重启后丢配置: docker run -e 的参数不落盘,改用 --env-file 或 compose 的 environment 字段固化。
Article ID: 86
(本文仅供技术交流,请遵守法律法规)