如何通过Jenkins使用HTTP_PROXY构建Dockerfile的Docker镜像?

46

在桌面上构建Docker镜像没有问题。安装Node.js NPM依赖项与往常一样正常工作。然而,当使用诸如Jenkins之类的持续集成服务器时,由于被公司代理所控制,构建Docker镜像会失败。

Node.js NPM依赖项

在构建Node.js包时,当无法连接到GIT以克隆GIT依赖项时,命令npm install将失败。

e1ce5e8407d1: Already exists
Status: Image is up to date for node:0.10.33
 ---> e1ce5e8407d1
Step 1 : RUN mkdir -p /usr/src/app
 ---> Using cache
 ---> 965cad0c68b0
Step 2 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 4c498f0c07e9
Step 3 : COPY package.json /usr/src/app/
 ---> b0662a8275fb
Removing intermediate container 5aca20551452
Step 4 : RUN npm install
 ---> Running in 7ccf9e5362af
npm WARN package.json newww@2.0.0 No README data
npm WARN package.json Dependency 'async-cache' exists in both dependencies and devDependencies, using 'async-cache@^0.1.5' from dependencies
npm ERR! git clone https://github.com/npm/npm2es.git Cloning into bare repository '/root/.npm/_git-remotes/https-github-com-npm-npm2es-git-60a75edb'...
npm ERR! git clone https://github.com/npm/npm2es.git fatal: unable to access 'https://github.com/npm/npm2es.git/': Failed to connect to github.com port 443: Connection timed out

Java Maven、Ruby 和 Go Docker 镜像及其依赖

在构建 Java、Ruby 或 Go 容器时,同样会出现依赖位于公司代理服务器跨越的存储库服务器上的情况。

了解到您可以使用 HTTP_PROXY 环境变量配置 Docker,如何正确配置 Docker 以在 CI 环境中正确构建镜像呢?


为什么不在本地进行Docker构建,并让CI测试Docker镜像呢? - generalhenry
因为我们有一个内部私有的Docker Registry,带有代理的私有NPM Registry,私有的Maven仓库和代理。所有这些都已经为当前CI/CD环境正确设置(不仅公共云,而且我们在分布式数据中心中也有多个私有云)…所以,工程师们不知道图像将在哪里构建,但我们必须手动或通过某种自动化方式指定HTTP_PROXY变量。另一个原因是一些服务在构建和运行时还需要外部HTTP访问以检索依赖项。 - Marcello DeSales
这是一个常见的需求,解决方案是使用--build-arg。您也可以查看文档 - ahmadkarimi12
8个回答

64

注意:Docker 1.9 可能有助于解决此问题:

  • "Issue 14634": 构建器 - 构建时参数传递(例如,HTTP_PROXY
  • "PR 15182": 支持在构建上下文中传递构建时变量

使用方法(建议):

docker build --build-arg http_proxy=http://my.proxy.url  --build-arg foo=bar <<MARK
FROM busybox
RUN <command that need http_proxy>
ARG --description="foo's description" foo
USER $foo
MARK

谢谢提供这个...我一直在关注它的发展,迫不及待想要看到它的完成。 - Marcello DeSales
1
已发布,我们现在使用Docker 1.9.1版本。 - taco
我已经测试过了,非常棒! - Marcello DeSales
1
@MarcellodeSales 确实。我已经使用它几周了,它确实简化了代理管理。 - VonC
1
是的,有一个开放问题可以在docker-compose上支持它!这使得它具有完全支持!:) - Marcello DeSales
@MarcellodeSales 对的:https://github.com/docker/compose/issues/2111 我会持续关注它。 - VonC

35

Docker有多种方法来设置代理,在不同的时间生效。


如果您的docker build必须通过代理检索基本镜像,则需要指定build-arg参数:

docker build --build-arg HTTP_PROXY=$http_proxy \
--build-arg HTTPS_PROXY=$http_proxy --build-arg NO_PROXY="$no_proxy" \
--build-arg http_proxy=$http_proxy --build-arg https_proxy=$http_proxy \
--build-arg no_proxy="$no_proxy" -t myContainer /path/to/Dockerfile/directory

在我的bashrc中设置了$http_proxy$no_proxy。我同时使用了HTTP_PROXYhttp_proxy,因为不同的工具会检查不同的变量(curl会检查两者,wget只检查小写的变量等)。


如果你的docker build命令需要通过代理进行RUN curl/wget/etc操作,你需要在docker镜像内指定一个环境变量:

ENV https_proxy=http://proxy-us02.company.com:8080
ENV http_proxy=http://proxy-us02.company.com:8080
ENV HTTP_PROXY=http://proxy-us02.company.com:8080
ENV HTTPS_PROXY=http://proxy-us02.company.com:8080
ENV no_proxy="localhost,localdomain,127.0.0.1,etc"
ENV NO_PROXY="localhost,localdomain,127.0.0.1,etc"

如果您不希望在运行时在镜像中包含此环境变量,您可以在最后删除所有这些内容:
RUN unset http_proxy https_proxy no_proxy HTTP_PROXY HTTPS_PROXY NO_PROXY

为什么我们需要在参数中同时使用大写和小写字母? - Sibi John
1
请参考这个问题。基本上,一些应用程序使用大写字母,而另一些则使用小写字母。 - jeremysprofile

14

Docker守护进程HTTP代理

有很多关于为Docker守护进程设置HTTP_PROXY环境变量的文档可供参考。但是该环境变量只在运行容器时可用,因此它对我们没有帮助。

Dockerfile中的解决方案

虽然在Dockerfile中设置环境变量HTTP_ENVhttp_env可能有所帮助,但它也无法解决我们的问题。

ENV http_proxy http://proxy.mycompany.com:80

原因是每个特定的服务只在不同的方式下遵循HTTP代理设置。我能够解决的方法如下。

  • NPM:NPM需要使用CLI命令设置HTTP_PROXY变量。
  • GIT:GIT也需要使用CLI命令设置HTTP_PROXY变量。
  • MAVEN:MVN命令需要将HTTP_PROXY设置为用户目录下的XML文件,在~/.m2/settings.xml中。对于Docker,您可以将其添加到根目录的“/root/.m2/settings.xml”目录(不安全,仅限开发),或将其添加到Dockerfile的用户主目录中。

例如,使用Dockerfile运行应用程序,我可以使用以下Dockerfile构建镜像:

FROM node:0.10.33

# Prepare
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Use the cache for dependencies
COPY package.json /usr/src/app/

# If building behind an http_proxy, set them for git and npm
RUN git config --global http.proxy http://qypprdproxy02.ie.company.net:80 && \
    npm config set proxy http://qypprdproxy02.ie.company.net:80 && \
    npm config set https-proxy http://qypprdproxy02.ie.company.net:80

# Install dependencies
RUN npm install

# Copy all the source
COPY . /usr/src/app

# Execute the dev steps
COPY ./numbat-config.example.js /usr/src/app/numbat-config.js
COPY ./.env.example /usr/src/app/.evn
RUN touch /usr/src/app/config.admin.js

请注意,我已使用其CLI命令配置了GIT和NPM,以显式获取代理设置,然后再运行NPM install命令。这样,NPM和GIT依赖项将分别自动检索和克隆。

使用此Dockerfile构建图像的结果如预期所示:

[root@pppdc9prd6dq newww]# fig build
...
...
Building npmregistryserver...
 ---> Using cache
 ---> 965cad0c68b0
Step 2 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 4c498f0c07e9
Step 3 : COPY package.json /usr/src/app/
 ---> ae8ff7861246
Removing intermediate container ba1d7b8c9963
Step 4 : RUN npm config set proxy http://qypprdproxy02.ie.company.net:80 &&     npm config set https-proxy http://qypprdproxy02.ie.company.net:80 &&     npm install
 ---> Running in aa6e05d9c7a4
npm WARN package.json newww@2.0.0 No README data
npm WARN package.json Dependency 'async-cache' exists in both dependencies and devDependencies, using 'async-cache@^0.1.5' from dependencies
npm WARN deprecated extend@1.1.3: Please update to the latest version.

> v8flags@1.0.8 install /usr/src/app/node_modules/gulp/node_modules/v8flags
> node fetch.js


> hiredis@0.1.17 install /usr/src/app/node_modules/hiredis
> node-gyp rebuild

make: Entering directory '/usr/src/app/node_modules/hiredis/build'
  CC(target) Release/obj.target/hiredis/deps/hiredis/hiredis.o
  CC(target) Release/obj.target/hiredis/deps/hiredis/net.o
  CC(target) Release/obj.target/hiredis/deps/hiredis/sds.o
  CC(target) Release/obj.target/hiredis/deps/hiredis/async.o
  AR(target) Release/obj.target/deps/hiredis.a
  COPY Release/hiredis.a
  CXX(target) Release/obj.target/hiredis/src/hiredis.o
  CXX(target) Release/obj.target/hiredis/src/reader.o
  SOLINK_MODULE(target) Release/obj.target/hiredis.node
  SOLINK_MODULE(target) Release/obj.target/hiredis.node: Finished
  COPY Release/hiredis.node
make: Leaving directory '/usr/src/app/node_modules/hiredis/build'
npm WARN engine hawk@0.10.2: wanted: {"node":"0.8.x"} (current: {"node":"0.10.33","npm":"2.1.11"})

> pngcrush-bin@1.0.0 postinstall /usr/src/app/node_modules/imagemin-pngcrush/node_modules/pngcrush-bin
> node lib/install.js

     fetch : https://raw.githubusercontent.com/imagemin/pngcrush-bin/v1.0.0/vendor/linux/pngcrush


 pre-build test passed successfully!

> dtrace-provider@0.3.1 install /usr/src/app/node_modules/npm-typeahead/node_modules/restify/node_modules/dtrace-provider
> scripts/install.js

npm WARN engine cryptiles@0.1.3: wanted: {"node":"0.8.x"} (current: {"node":"0.10.33","npm":"2.1.11"})
npm WARN engine sntp@0.1.4: wanted: {"node":"0.8.x"} (current: {"node":"0.10.33","npm":"2.1.11"})
npm WARN engine boom@0.3.8: wanted: {"node":"0.8.x"} (current: {"node":"0.10.33","npm":"2.1.11"})
npm WARN engine hoek@0.7.6: wanted: {"node":"0.8.x"} (current: {"node":"0.10.33","npm":"2.1.11"})
npm WARN cannot run in wd newww@2.0.0 gulp build (wd=/usr/src/app)
newww-metrics@1.0.0 node_modules/newww-metrics

murmurhash@0.0.2 node_modules/murmurhash

npm-humans@2.0.1 node_modules/npm-humans

leven@1.0.1 node_modules/leven

chunk@0.0.2 node_modules/chunk

npm-expansions@1.14.0 node_modules/npm-expansions

similarity@1.0.1 node_modules/similarity

truncate@1.0.4 node_modules/truncate

这个功能按预期正常工作,您可以在http代理后面拥有一个CI/CD环境,以根据此Dockerfile重新构建镜像。


3
这个方法虽然可行,但我担心它会阻止 Dockerfile 在其他设备上的构建。 - K..
这正是问题/答案所涉及的:如果您有一个CI / CD环境,在该环境中,Docker镜像由不同的盒子构建!!! 您可以通过挂载一个新的 .npmrc 文件,在运行时替换或完全取消代理设置,从而使您的应用程序仍然能够正常运行,并删除该设置,同时执行“docker run”。;) - Marcello DeSales

10

1
我尝试使用--build-argENV变量,但似乎不起作用。只有这种方式在我的Ubuntu 18.04镜像上才能正常工作。感谢分享。我按照帖子中建议的创建了一个包含代理URL的文件~/.docker/config.json - Dan
所有使用环境变量或构建参数的其他答案都已过时。 配置Docker客户端的这种方法是解决代理问题的正确方式! - Donatello

4

We are doing ...

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 引入构建环境变量之前)允许使用代理变量进行构建,而不会公开暴露它们。


当在Visual Studio内部运行docker build时,这似乎是我唯一可以让它识别代理设置的方法。尝试使用NuGet.Config文件和设置http_proxy和https_proxy环境变量,但这些都没有起作用。我不得不在构建语句之后添加if。在我的情况下,它遵循"FROM microsoft/dotnet:2.1-sdk AS build"。谢谢! - Nimblejoe

0

当企业网络不允许下载和设置Docker镜像时,我遇到了问题,因此网络提供了HTTP代理信息。在运行Docker镜像构建时,我传递了变量,而且没有出现任何问题。

  docker build  --build-arg http_proxy="http://userid:pwd@iaisystem.com:8080" - < Dockerfile

0

我遇到了一个类似的问题,即docker build无法从托管在Amazon ECR上的注册表中拉取基本镜像。我发现,在docker构建命令行、Dockerfile或我的shell中添加代理配置都没有任何影响。

对我有用的解决方法是更改docker守护程序的环境。我正在使用CentOS盒子,在该系统中有一个配置目录/etc/systemd/system/docker.service.d,里面有一个http-proxy.conf文件。

我编辑了那个文件以放置正确的代理配置,并重新启动了docker守护进程,然后我的docker构建开始工作了。

[Service]
Environment="HTTP_PROXY=http://<hostname>:8080"
Environment="HTTPS_PROXY=http://<hostname>:8080"
Environment="NO_PROXY=<suffix>,<another suffix>"

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - rastasheep

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接