如何在 Jenkins 的 HTTP_PROXY 后面使用 Dockerfile 构建 Docker 映像?

Posted

技术标签:

【中文标题】如何在 Jenkins 的 HTTP_PROXY 后面使用 Dockerfile 构建 Docker 映像?【英文标题】:How to build Docker Images with Dockerfile behind HTTP_PROXY by Jenkins? 【发布时间】:2015-03-01 04:48:12 【问题描述】:

在桌面上构建 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 镜像? 因为我们有一个内部私有 Docker Registry、私有 NPM Registry with Proxy、私有 Maven 存储库和代理。所有这些都针对当前的 CI/CD 环境进行了正确设置(不仅是公共云,而且我们在分布式数据中心中确实有多个私有云)......所以,工程师不知道将在哪里构建映像,但我们必须手动或通过某种自动化指定 HTTP_PROXY 变​​量。另一个原因是某些服务还需要外部 HTTP 访问,以便在构建和运行时检索依赖项。 这是一个常见的需求,解决方案是使用--build-arg。您也可以查看docs。 【参考方案1】:

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


如果您的docker build 必须通过代理检索基本图像,您需要指定build-args:

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

$http_proxy$no_proxy 在我的 bashrc 中设置。我同时使用了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

【讨论】:

为什么我们需要大写和小写的参数? 查看this question基本上,一些应用程序使用大写,一些使用小写。 span> 【参考方案2】:

从 Docker 17.07 开始,您可以选择使用 Docker 客户端配置文件来集中提供代理配置:

https://docs.docker.com/network/proxy/#configure-the-docker-client

【讨论】:

我尝试使用 --build-argENV 变量,但似乎不起作用。只有这种方式似乎适用于我的Ubuntu 18.04 图像。感谢分享。我按照帖子中的建议创建了一个带有代理网址的文件~/.docker/config.json 所有其他使用环境变量或构建参数的答案均已弃用。这种方法(配置docker客户端)是当今解决代理问题的正确方法!【参考方案3】:

您可以使用透明代理,如下所述:

https://jpetazzo.github.io/2014/06/17/transparent-squid-proxy-docker/

docker run --net host jpetazzo/squid-in-a-can
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 3129

【讨论】:

【参考方案4】:

当公司网络不允许下载和设置 docker 映像时,我遇到了问题,因此 n/w 提供了 http 代理信息。在运行 docker image build 时,我传递了变量,它可以正常工作。

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

【讨论】:

【参考方案5】:

注意: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

【讨论】:

感谢您提供...我一直在关注它的发展,我迫不及待... 出来了。我们现在是 Docker 1.9.1。 我已经测试过了,非常棒! @MarcellodeSales 确实如此。我已经使用它几个星期了,它确实简化了代理管理。 是的,在 docker-compose 上有一个未解决的问题来支持它!这使它成为一个完整的支持! :)【参考方案6】:

我们正在做...

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 引入构建环境变量),允许代理变量用于构建而不公开暴露它们

【讨论】:

当 docker build 从 Visual Studio 内部运行时,这似乎是我可以让它识别代理设置的唯一方法。我尝试使用 NuGet.Config 文件并设置 http_proxy 和 https_proxy 环境变量,但这些都不起作用。我必须在构建语句之后添加 if 。就我而言,它遵循“FROM microsoft/dotnet:2.1-sdk AS build”。谢谢!【参考方案7】:

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 安装命令之前显式获取代理设置。这样,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 重建映像。

【讨论】:

这行得通,但我担心它会阻止 Dockerfile 在其他设备上构建。 这正是问题/答案的内容:如果您有一个 CI/CD 环境,其中 Docker 映像是由单独的盒子构建的!!!您的应用程序仍然可以通过在运行时替换或完全取消代理设置来正常运行,方法是安装一个新的 .npmrc,在您执行“docker run”时删除该设置。 ;)

以上是关于如何在 Jenkins 的 HTTP_PROXY 后面使用 Dockerfile 构建 Docker 映像?的主要内容,如果未能解决你的问题,请参考以下文章

代理后面的 Java 应用程序在 linux 中使用 http_proxy 变量

Settings.Secure.HTTP_PROXY 在 ICS 中已弃用,但没有关于更换的信息

执行Docker build时,有部分需要×××的需求,通过引入http_proxy 解决:

在 Mac 上通过导出 http_proxy 将 Ruby 与 Charles Proxy 一起使用

wget和curl中使用代理

Linux下设置代理