問題描述
在使用 docker build 打包鏡像時茄猫,遇到了需要使用代理訪問網(wǎng)絡(luò)的需求狈蚤。使用如下的 Dockerfile 來模擬這個場景:
FROM golang:1.12
RUN curl www.google.com --max-time 3
國內(nèi)一般網(wǎng)絡(luò)環(huán)境下困肩,curl www.google.com 是無法正常返回的,加入 --max-time 讓 curl 的耗時不要太長脆侮。
配置 http_proxy 變量
首先需要在環(huán)境變量中設(shè)置 http_proxy 和 https_proxy锌畸,使得訪問網(wǎng)絡(luò)的命令(這里使用 curl 來代表)能夠通過環(huán)境變量中配置的代理服務(wù)器訪問 www.google.com。
docker build 命令雖然是在 docker 所在的宿主機上執(zhí)行的靖避,看上去像是直接使用了宿主機的網(wǎng)絡(luò)環(huán)境潭枣,但實際上 docker build 也是啟動了一個 container 進行構(gòu)建,所以在構(gòu)建過程中的所有命令都是在 container 中執(zhí)行的幻捏,http_proxy 和 https_proxy 的配置也應(yīng)該是在 container 中進行的盆犁。可以使用 ENV 來配置 container 中的環(huán)境變量篡九。
代理服務(wù)器啟動在宿主機的 1087 端口上谐岁,修改 dockerfile 文件:
FROM golang:1.12
ENV http_proxy "http://127.0.0.1:1087"
ENV HTTP_PROXY "http://127.0.0.1:1087"
ENV https_proxy "http://127.0.0.1:1087"
ENV HTTPS_PROXY "http://127.0.0.1:1087"
RUN curl www.google.com --max-time 3
重新執(zhí)行 docker build 會發(fā)現(xiàn) curl 依舊無法訪問 www.google.com,從報錯信息上可以看到 127.0.0.1 上的 1087 端口上并沒有服務(wù)榛臼。
訪問宿主機
由于 container 默認是橋接網(wǎng)絡(luò)伊佃,宿主機和 container 是平級的,被放在了一個虛擬的網(wǎng)段里沛善。訪問宿主機上的代理服務(wù)器锭魔,對于 container 來說實際上是訪問另一臺機器上的服務(wù)器,127.0.0.1 指向的是 container 本身路呜。在 docker 默認的橋接網(wǎng)絡(luò)中,宿主機的 IP 一般是 172.17.0.1(Linux)织咧,或者 192.168.65.1(MacOS)胀葱,可以將 http_proxy 中的 IP 換成 172.17.0.1/192.168.65.1,來實現(xiàn)通過宿主的代理服務(wù)器訪問網(wǎng)絡(luò)笙蒙,修改 dockerfile:
FROM golang:1.12
ENV http_proxy "http://172.17.0.1:1087"
ENV HTTP_PROXY "http://172.17.0.1:1087"
ENV https_proxy "http://172.17.0.1:1087"
ENV HTTPS_PROXY "http://172.17.0.1:1087"
RUN curl www.google.com --max-time 3
雖然使用這種方式可以達到目的抵屿,但是如果編譯環(huán)境變了或者代理服務(wù)器的配置變了,哪怕只是操作系統(tǒng)從 Linux 變成了 MacOS捅位,都得修改 dockerfile轧葛,顯然不夠解耦,也不方便艇搀。
配置網(wǎng)絡(luò)模式
docker 中還有一種 host 網(wǎng)絡(luò)模式尿扯,就是讓 container 使用宿主機的網(wǎng)絡(luò),相當于 container 在網(wǎng)絡(luò)層面和宿主機不做隔離焰雕,使用這種網(wǎng)絡(luò)模式執(zhí)行 docker build衷笋,就不需要在 dockerfile 中添加 http_proxy 環(huán)境變量,container 可以直接讀取宿主上的環(huán)境變量矩屁。
首先在宿主上導(dǎo)入 http_proxy 環(huán)境變量:
export http_proxy="http://127.0.0.1:1087";
export HTTP_PROXY="http://127.0.0.1:1087";
export https_proxy="http://127.0.0.1:1087";
export HTTPS_PROXY="http://127.0.0.1:1087"
接下來將 dockerfile 簡化:
FROM golang:1.12
RUN curl www.google.com --max-time 3
重新執(zhí)行辟宗,curl 就可以像在宿主上直接執(zhí)行一樣爵赵,通過代理訪問 www.google.com 了。