如何在代理后面运行Docker/Jenkins

92次阅读
没有评论

问题描述

在尝试使用Jenkins的Docker镜像时遇到了问题。问题似乎是一个代理问题。
用户的操作系统是Ubuntu 16.04 LTS,正在使用工作代理。Docker版本是19.03.5,构建号是633a0ea838。用户尝试运行以下命令时,无法访问localhost:7000上的Jenkins:

docker run --name myjenkins -p 7000:8080 -p 50000:50000 -v /var/jenkins_home jenkins

但是,使用以下命令可以访问Jenkins:

docker run --name myjenkins -p 7000:8080 -p 50000:50000 --env HTTP_PROXY="http://localhost:8080" --env HTTPS_PROXY="https://localhost:8080" -v /var/jenkins_home jenkins

然而,使用第二个命令时,用户无法安装插件,并且需要配置代理设置,但在UI中配置代理没有起作用。
用户认为Jenkins默认使用端口8080,因为在上述命令中使用了端口7000,这导致Jenkins无法连接到互联网(如果我理解有误,请纠正我)。
用户下载了Jenkins的Dockerfile,并将端口从8080更改为7000,现在尝试使用以下命令构建镜像:

docker build --tag jenkins:1.0 .

但是,用户遇到了以下错误:

curl: (7) Failed to connect to github.com port 443: Connection timed out
The command '/bin/sh -c curl -fsSL https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-static-amd64 -o /bin/tini && chmod +x /bin/tini && echo "$TINI_SHA /bin/tini" | sha256sum -c -' returned a non-zero code: 7

用户怀疑这是一个代理问题,并在Dockerfile中添加了代理参数,但不确定是否正确。
用户想知道是否有解决方案。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

我认为问题出在代理环境变量上。
docker run命令中,$HTTP_PROXY$HTTP_PROXY的值不应该包含空格,并且协议应该是http。此外,虽然设置$HTTP_PROXY对于与容器内运行的其他应用程序兼容性很有用,但curl期望HTTP代理环境变量以小写形式编写,即$http_proxy。根据curl (1)手册页:

环境变量可以使用小写或大写字母指定。小写版本具有优先级。http_proxy是一个例外,因为它只能使用小写形式。
http_proxy [protocol://]<host>[:port] 设置用于HTTP的代理服务器。
HTTPS_PROXY [protocol://]<host>[:port] 设置用于HTTPS的代理服务器。
FTP_PROXY [protocol://]<host>[:port] 设置用于FTP的代理服务器。
ALL_PROXY [protocol://]<host>[:port] 如果没有设置特定协议的代理,则设置要使用的代理服务器。
NO_PROXY <comma-separated list of hosts> 不经过任何代理的主机名列表。如果设置为星号*,则匹配所有主机。

因此,docker run命令可以按照以下方式编写:

docker run \
    --name myjenkins \
    -p 7000:8080 \
    -p 50000:50000 \
    --env HTTP_PROXY="http://localhost:8080" \
    --env http_proxy="http://localhost:8080" \
    --env HTTPS_PROXY="http://localhost:8080" \
    --env https_proxy="http://localhost:8080" \
    -v /var/jenkins_home \
    jenkins

然而,我的解决方案肯定不会起作用,因为容器内部的端口8080被Jenkins使用,而不是HTTP代理。请问您能否提供有关工作代理的更多信息,以便我可以编辑我的答案并提供更准确的细节?您是否在计算机上运行类似squidcntlm的HTTP代理,它接收来自工作站上运行的应用程序的请求,并在身份验证后将其转发到公司代理?如果是这样,您将需要根据Stack Overflow问题“从Docker容器内部如何连接到主机的localhost?”调整容器的网络配置。


编辑:根据评论,本地运行的cntlm实例在端口8080/tcp上提供了一个HTTP代理服务,本地应用程序必须使用它才能访问互联网。我认为将其暴露给Jenkins容器的最简单方法是使用--network=host参数,并与Jenkins容器共享根网络命名空间。然而,Jenkins默认监听端口8080/tcp,因此必须指示其监听另一个端口,例如7000/tcp。可以通过通过Jenkins的JENKINS_OPTS环境变量传递--httpPort=#命令行参数来实现。

编辑2:在分析存储库代码时,我意识到Jenkins是一个Java应用程序,我不确定JVM是否正确识别$http_proxy$https_proxy环境变量。因此,为了确保Jenkins将使用cntlm作为HTTP代理,我还建议通过JAVA_OPTS环境变量将代理配置属性传递给JVM。

编辑3: Docker镜像jenkins已被弃用,取而代之的是jenkins/jenkins:lts镜像。前者目前不再维护,并且似乎包含一个与正在下载的插件不兼容的过时版本。

综上所述,为了使Jenkins在您的环境中正常工作,docker run命令应按照以下方式编写:

docker run \
    --name myjenkins \
    --network=host \
    --env HTTP_PROXY="http://localhost:8080" \
    --env http_proxy="http://localhost:8080" \
    --env HTTPS_PROXY="http://localhost:8080" \
    --env https_proxy="http://localhost:8080" \
    --env JAVA_OPTS="-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8080 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8080" \
    --env JENKINS_OPTS="--httpPort=7000" \
    -v /var/jenkins_home \
    jenkins/jenkins:lts

或者,尝试使用以下命令传递--env JAVA_OPTS="-Djava.net.useSystemProxies=true"

请注意,这些设置可能会有所不同,具体取决于您的代理设置和网络环境。

正文完