一份 docker-compose.yml,改造成让容器 和 构建过程都能走代理,看起来简单,实际上分两层——很多人只加了一层就以为好了。
场景一:容器运行时走代理
只要在 environment 里加 4 个变量(大小写都写一份最保险):
services:
web:
build:
context: .
dockerfile: Dockerfile
environment:
http_proxy: http://host.docker.internal:7890
https_proxy: http://host.docker.internal:7890
HTTP_PROXY: http://host.docker.internal:7890
HTTPS_PROXY: http://host.docker.internal:7890
extra_hosts:
- "host.docker.internal:host-gateway"
host.docker.internal是宿主机地址(Mac / Windows 原生支持)- Linux 需要显式声明
extra_hosts——不然容器里根本不认这个名字
宿主机上代理是 Clash / v2ray,默认端口通常 7890。用之前先在宿主机测:
curl -x http://127.0.0.1:7890 https://www.google.com
场景二:build 阶段也要走代理
environment 只影响运行时。build 阶段 apt install、git clone、pecl 这些走的还是宿主机网络。要让它们也走代理,得从 args 传进去,再在 Dockerfile 里 ARG + ENV。
docker-compose.yml:
services:
web:
build:
context: .
dockerfile: Dockerfile
args:
http_proxy: http://host.docker.internal:7890
https_proxy: http://host.docker.internal:7890
extra_hosts:
- "host.docker.internal:host-gateway"
Dockerfile 顶部:
FROM php:7.4-apache
ARG http_proxy
ARG https_proxy
ENV http_proxy=$http_proxy
ENV https_proxy=$https_proxy
ENV HTTP_PROXY=$http_proxy
ENV HTTPS_PROXY=$https_proxy
# 之后所有 apt / curl / git / composer 都会走代理
写在最前面很重要——ENV 只对后续 RUN 生效。
Linux 老坑:host.docker.internal 不通
Linux 上 host.docker.internal 默认解析不了。有两种解法:
推荐:extra_hosts + host-gateway
extra_hosts:
- "host.docker.internal:host-gateway"
这是 Docker 20.10+ 的标准写法,比手动填 IP 稳。
兜底:用 docker0 网桥 IP
environment:
http_proxy: http://172.17.0.1:7890
前提是宿主机代理监听 0.0.0.0 或者 172.17.0.1——只监听 127.0.0.1 是不行的。
构建后清掉代理(可选)
代理只用于 build 阶段,不希望被镜像继承的话:
FROM base
ARG http_proxy
ARG https_proxy
ENV http_proxy=$http_proxy https_proxy=$https_proxy
RUN apt-get update && apt-get install -y curl git
# 用完就抹掉
ENV http_proxy= https_proxy= HTTP_PROXY= HTTPS_PROXY=
镜像跑起来后就不会带代理设置了。
一句话总结
environment 只管跑起来之后,build 阶段的代理要靠 args + ARG + ENV。Linux 上别忘 extra_hosts: host-gateway。
