如何在代理后面的dockerfile中运行`apt-get`?


76

我正在使用docker(版本0.8.1,构建a1598d1)运行虚拟机(Ubuntu 13.10)。我正在尝试使用dockerfile构建映像。首先,我想更新软件包(使用下面的代码-代理被混淆),但是apt-get由于错误:而超时Could not resolve 'archive.ubuntu.com'

FROM ubuntu:13.10
ENV HTTP_PROXY <HTTP_PROXY>
ENV HTTPS_PROXY <HTTPS_PROXY>
RUN export http_proxy=$HTTP_PROXY
RUN export https_proxy=$HTTPS_PROXY
RUN apt-get update && apt-get upgrade

我还在主机系统中运行了以下命令:

sudo HTTP_PROXY=http://<PROXY_DETAILS>/ docker -d &

主机能够正常运行apt-get

如何更改dockerfile以允许其从容器内部到达ubuntu服务器?

更新资料

我在CentOS中运行了代码(将更FROM ubuntu:13.10改为FROM centos),并且运行良好。Ubuntu似乎有问题。


我刚刚在centos(yum更新)和ubuntu:13.10(apt-get更新)中测试了HTTP代理。这两张图片都对我有用,我什至尝试从容器中删除dns设置以测试代理(它在没有dns的情况下也可以正常工作)。我仅使用http_proxy(不使用https)。
吉里(Jiri)2014年

您的Dockerfile中实际上是否有“ <HTTP_PROXY>”,或者这是一个占位符?
Behe 2014年

我在文件中有实际的代理。我只是无法分享地址。
Christopher Louden 2014年


Answers:


98

更新

您在ENV中对环境变量的大小写有误。正确的是http_proxy。您的示例应为:

FROM ubuntu:13.10
ENV http_proxy <HTTP_PROXY>
ENV https_proxy <HTTPS_PROXY>
RUN apt-get update && apt-get upgrade

要么

FROM centos
ENV http_proxy <HTTP_PROXY>
ENV https_proxy <HTTPS_PROXY>
RUN yum update 

ENV中指定的所有变量都在每个RUN命令之前。每个RUN命令都在自己的容器/环境中执行,因此它不会继承先前RUN命令的变量!

注意:无需调用带有代理的docker daemon即可工作,尽管如果您要拉映像等,也需要为docker deamon设置代理。您可以/etc/default/docker在Ubuntu中设置守护程序的代理(不影响容器设置)。


另外,如果您在主机(即localhost,127.0.0.1)上运行代理,则可能会发生这种情况。主机上的Localhost与容器中的localhost不同。在这种情况下,您需要使用另一个IP(例如172.17.42.1)将代理绑定到,或者,如果绑定到0.0.0.0,则可以在期间使用172.17.42.1而不是127.0.0.1从容器进行连接docker build

您还可以在此处查找示例:如何通过使用缓存快速重建dockerfile?


我在主机上没有代理。这是我落后的公司代理。相同的代码在FROM具有相同代理设置的CentOS上起作用(仅更改)。
Christopher Louden 2014年

3
使用Docker的当前状态,看起来ENV http_proxy corporate-proxy.com您的Dockerfile中必须包含该文件。那真是令人作呕,因为这意味着您无法与公司外部的任何人共享Dockerfile。我刚刚通过尝试在容器中运行polipo并尝试缓存apt-get install用于开发Dockerfile的命令来验证了这一点。也许将来的Docker版本将具有一些神奇的iptables配置,该配置允许HTTP请求的透明代理?
蒂姆·波特2014年

@TimPotter我认为还不错(没有必要使用高级魔术)。您需要使用父代理(polipo parentProxy=corporate-proxy.com)在主机上设置polipo,然后需要使用iptables:设置透明代理iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner <polipo-user> --dport 80 -j REDIRECT --to-port 8123
吉里(Jiri)2014年

1
我刚刚汇总了一个项目,该项目使用适当的iptables / ip规则命令为在容器中运行的鱿鱼提供重定向,使其通过鱿鱼容器重定向所有其他容器流量,从而实现透明代理。这可能对您描述的内容有用? silarsis.blogspot.com.au/2014/03/proxy-all-containers.html
KevinL 2014年

您是否有办法从docker容器中获取docker守护进程(/ etc / defailt / docker)中的http_proxy设置?所以我可以添加脚本以注入Dockerfile
Larry Cai

50

于02/10/2018更新

借助--configdocker选项中的新功能,您无需再在Dockerfile中设置Proxy。您可以在企业环境中使用相同的Dockerfile。

--config string      Location of client config files (default "~/.docker")

或环境变量 DOCKER_CONFIG

`DOCKER_CONFIG` The location of your client configuration files.

$ export DOCKER_CONFIG=~/.docker

https://docs.docker.com/engine/reference/commandline/cli/

https://docs.docker.com/network/proxy/

我建议使用httpProxy, httpsProxy, ftpProxy和设置代理noProxy(官方文档缺少ftpProxy有时有用的变量)

{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://127.0.0.1:3001",
     "httpsProxy": "http://127.0.0.1:3001",
     "ftpProxy": "http://127.0.0.1:3001",
     "noProxy": "*.test.example.com,.example2.com"
   }
 }
}

调整代理IP和端口(如果需要)并保存到 ~/.docker/config.json

正确设置后,您可以运行docker build和docker run正常运行。

$ docker build -t demo . 

$ docker run -ti --rm demo env|grep -ri proxy
(standard input):http_proxy=http://127.0.0.1:3001
(standard input):HTTPS_PROXY=http://127.0.0.1:3001
(standard input):https_proxy=http://127.0.0.1:3001
(standard input):NO_PROXY=*.test.example.com,.example2.com
(standard input):no_proxy=*.test.example.com,.example2.com
(standard input):FTP_PROXY=http://127.0.0.1:3001
(standard input):ftp_proxy=http://127.0.0.1:3001
(standard input):HTTP_PROXY=http://127.0.0.1:3001

旧答案(已退役)

Dockerfile中的以下设置适用于我。我测试了CoreOSVagrantboot2docker。假设代理端口是3128

在Centos中:

ENV http_proxy=ip:3128 
ENV https_proxy=ip:3128

在Ubuntu中:

ENV http_proxy 'http://ip:3128'
ENV https_proxy 'http://ip:3128'

请注意格式,有些带有http,有些没有,有些带有单个配额。如果IP地址为192.168.0.193,则设置为:

在Centos中:

ENV http_proxy=192.168.0.193:3128 
ENV https_proxy=192.168.0.193:3128

在Ubuntu中:

ENV http_proxy 'http://192.168.0.193:3128'
ENV https_proxy 'http://192.168.0.193:3128'

如果您需要在coreos中设置代理,例如提取图像

cat /etc/systemd/system/docker.service.d/http-proxy.conf

[Service]
Environment="HTTP_PROXY=http://192.168.0.193:3128"

1
您可能还需要添加https代理设置,因为apt-get将使用安全连接。[服务] Environment =“ HTTP_PROXY = your-proxy-server:port ” HTTPS_PROXY = your-proxy-server:port:3128 “” NO_PROXY = localhost,127.0.0.0 / 8“
pharsfalvi

请注意,对于Centos,即使它是默认端口,也必须显式添加端口号80stackoverflow.com/a/46949277/1654763
Munchkin

1
这工作了。谢谢你的例子。Docker文档尚不清楚。
ToTenMilan

2
$DOCKER_CONFIG应该指向目录而不是直接指向config.json文件
Jakub Bochenski

43

--build-arg当您要使用Dockerfile进行构建时,可以使用该选项。

https://github.com/docker/docker/issues/14634上的链接,请参阅“使用--build-arg和多个HTTP_PROXY进行构建”部分:

[root@pppdc9prda2y java]# docker build 
  --build-arg https_proxy=$HTTP_PROXY --build-arg http_proxy=$HTTP_PROXY 
  --build-arg HTTP_PROXY=$HTTP_PROXY --build-arg HTTPS_PROXY=$HTTP_PROXY 
  --build-arg NO_PROXY=$NO_PROXY  --build-arg no_proxy=$NO_PROXY -t java .

注意:在您自己的系统上,请确保已设置HTTP_PROXY和NO_PROXY环境变量。


这是讨厌的解决办法,为持久设置你应该使用Dockerfile,像@Reza Farshi给了例子
帕维尔Smołka

18
讨厌的解决方法?在某些(大多数)情况下,最好不要将自己的代理放入图像中,如果(例如)您的图像供公司其他部门的人使用,而他们可能在其他代理的后面。
ventolin

11

在您的Dockerfile中的任何apt-get命令之前,您应该将这一行

COPY apt.conf /etc/apt/apt.conf

Dont'f忘记创建apt.conf在同一文件夹,你有Dockerfile的内容apt.conf文件应该是这样的:

Acquire::socks::proxy "socks://YOUR-PROXY-IP:PORT/";
Acquire::http::proxy "http://YOUR-PROXY-IP:PORT/";
Acquire::https::proxy "http://YOUR-PROXY-IP:PORT/";

如果使用用户名和密码连接到代理,则apt.conf应该如下所示:

Acquire::socks::proxy "socks://USERNAME:PASSWORD@YOUR-PROXY-IP:PORT/";
Acquire::http::proxy "http://USERNAME:PASSWORD@YOUR-PROXY-IP:PORT/";
Acquire::https::proxy "http://USERNAME:PASSWORD@YOUR-PROXY-IP:PORT/";

例如 :

Acquire::https::proxy "http://foo:bar@127.0.0.1:8080/";

其中foo是用户名,bar是密码。


apt根本不支持SOCKS代理。 Acquire::socks::proxy表示为所有以socks方案开头的URL设置代理。由于您sources.list没有任何socks://URL,因此该行将被完全忽略。我将提交修改以更正此问题。
汉斯·克里斯托夫·斯坦纳

您已/etc/apt/apt.conf.d/<config>打开jessie,因此DockerfileCOPY指令需要在此处进行更新。
艾因·托夫里

这是唯一对我有用的答案(在公司代理后面运行Docker for Windows)。
康纳·戈达德

8

在小写的环境变量中使用--build-arg:

docker build --build-arg http_proxy=http://proxy:port/ --build-arg https_proxy=http://proxy:port/ --build-arg ftp_proxy=http://proxy:port --build-arg no_proxy=localhost,127.0.0.1,company.com -q=false .

5

如其他答案所建议,--build-arg可能是解决方案。就我而言,--network=host除了--build-arg选项之外,我还必须添加其他内容。

docker build -t <TARGET> --build-arg http_proxy=http://<IP:PORT> --build-arg https_proxy=http://<IP:PORT> --network=host .

如果仅在使用--network = host时有效,则可能是dnsmasq的问题。参见wisbucky的回答。在主机上的/ etc / resolv,conf中获得正确的dns之后,您不需要--network = host
user2707671

4

@Reza Farshi(在我的情况下效果更好)提供的答案的一种替代方法是通过Dockerfile将代理设置写出来/etc/apt/apt.conf使用echo,例如:

FROM ubuntu:16.04

RUN echo "Acquire::http::proxy \"$HTTP_PROXY\";\nAcquire::https::proxy \"$HTTPS_PROXY\";" > /etc/apt/apt.conf

# Test that we can now retrieve packages via 'apt-get'
RUN apt-get update

这种方法的优点是可以在映像构建时动态传递代理地址,而不必从主机复制设置文件。

例如

docker build --build-arg HTTP_PROXY=http://<host>:<port> --build-arg HTTPS_PROXY=http://<host>:<port> .

根据docker build docs。


3

我遇到了同样的问题,并找到了另一个解决方法:我有一个从Docker构建环境添加的Provisioner脚本。在脚本中,我根据ping检查设置环境变量:

Dockerfile:

ADD script.sh /tmp/script.sh
RUN /tmp/script.sh

script.sh:

if ping -c 1 ix.de ; then
    echo "direct internet doing nothing"
else
    echo "proxy environment detected setting proxy"
    export http_proxy=<proxy address>
fi

这仍然有些粗糙,但对我有用


这对你有用吗?我可以使脚本正常运行,但是环境变量仅可用于脚本。诸如apt-get,cURL和wget之类的东西最终都看不到环境变量。
Ryan J. McDonough

3

如果您正确设置了代理,但仍然无法访问Internet,则可能是DNS解析。检查/etc/resolve.conf主机Ubuntu VM。如果包含nameserver 127.0.1.1,那是错误的。

在主机Ubuntu VM上运行以下命令以对其进行修复:

sudo vi /etc/NetworkManager/NetworkManager.conf
# Comment out the line `dns=dnsmasq` with a `#`

# restart the network manager service
sudo systemctl restart network-manager

cat /etc/resolv.conf

现在/etc/resolv.conf应该为nameserver提供一个有效值,该值将由docker容器复制。


谢谢!这个答案非常有帮助,并最终帮助我pip install在代理之后与docker一起工作。这不是OP真正想要的,但是对我有很大帮助!:)
colidyre

同样在这里,谢谢!以下是有关此问题的详细信息:superuser.com/questions/681993/...
user2707671

1

我们正在做 ...

ENV http_proxy http://9.9.9.9:9999
ENV https_proxy http://9.9.9.9:9999

并在dockerfile结尾...

ENV http_proxy ""
ENV https_proxy ""

目前,这(直到docker引入build env vars),才允许将代理env vars仅用于构建而不暴露它们

解决方案的替代方案不是在代理之后本地构建映像,而是让docker使用docker“自动构建”为您构建映像。由于泊坞窗未在代理后面构建映像,因此问题得以解决。自动构建的示例可从以下网站获得:

https://github.com/danday74/docker-nginx-lua(GITHUB回购)

https://registry.hub.docker.com/u/danday74/nginx-lua(DOCKER存储库正在使用自动构建监视github存储库,并通过推送到github master分支进行了docker构建)


只是想提一下,由于这些ENV变量在EACH中间容器中公开,因此在最后将它们取消设置不会隐藏它们,并且仍然可以轻松地对其进行访问。据我所知
Squadrons

1

如果要为wget设置代理,则应将这些行放在Dockerfile中

ENV http_proxy YOUR-PROXY-IP:PORT/
ENV https_proxy YOUR-PROXY-IP:PORT/
ENV all_proxy YOUR-PROXY-IP:PORT/

1

正如Tim Potter所指出的那样,在dockerfile中设置代理非常可怕。构建映像时,您为公司网络添加了代理,但是您可能在不需要代理或代理服务器不同的云或DMZ中进行部署。

同样,您不能与公司外部的其他人共享您的图像。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.