在代理后构建 Node.js 应用程序的 Docker 镜像失败

4
我在docker构建过程中遇到了npm问题。我身处公司代理网络环境下,已经阅读了约30篇相关文章(以及stackoverflow帖子),但仍然无法解决问题。
我可以在docker构建过程之外(同样使用代理)执行“npm install”命令并获取所有必要的依赖项,但是在构建过程中无法执行。
目前我尝试过以下方法:
1. 直接使用代理(包括硬编码验证数据)以及使用CNTLM。以下描述是使用CNTLM时的情况。 2. 使用http存储库,并将strict_ssl设置为false。 npm config set strict-ssl=false \ npm config set registry=http://registry.npmjs.org/ \
3. 将代理设置传递给--build-arg、env和RUN参数 4. 在没有node_modules的情况下开始新的git checkout,并运行npm install
我正在尝试使用以下命令进行构建:
$ sudo docker build --build-arg HTTP_PROXY=http://127.0.0.1:3128 --build-arg HTTPS_PROXY=http://127.0.0.1:3128 .

输出结果

Sending build context to Docker daemon 226.6 MB
Step 1 : FROM node:argon
 ---> c74c117ed521
Step 2 : ENV http_proxy http://127.0.0.1:3128/
 ---> Using cache
 ---> ad2e2df7429b
Step 3 : ENV https_proxy http://127.0.0.1:3128/
 ---> Using cache
 ---> 75fb2eb0bb22
Step 4 : RUN mkdir -p /usr/src/app
 ---> Using cache
 ---> ee79de37d6d7
Step 5 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 404356f5def0
Step 6 : COPY package.json /usr/src/app/
 ---> Using cache
 ---> a2ec47267628
Step 7 : RUN git config --global http.proxy http://127.0.0.1:3128/
 ---> Running in 3cd5db8b1371
 ---> 7353cd94b67a
Removing intermediate container 3cd5db8b1371
Step 8 : RUN npm install
 ---> Running in 79ed0eb809d8
npm info it worked if it ends with ok
npm info using npm@2.15.5
npm info using node@v4.4.6
npm info preinstall app
npm info attempt registry request try #1 at 10:24:02 AM
npm http request GET https://registry.npmjs.org/bufferutil
npm info attempt registry request try #1 at 10:24:02 AM
npm http request GET https://registry.npmjs.org/connect-mongo
<snip>

npm info retry will retry, error on last attempt: Error: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:3128
npm info retry will retry, error on last attempt: Error: tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:3128
<snip>

npm ERR! Linux 3.13.0-88-generic
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install"
npm ERR! node v4.4.6
npm ERR! npm  v2.15.5
npm ERR! code ECONNRESET

npm ERR! network tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:3128
npm ERR! network This is most likely not a problem with npm itself
npm ERR! network and is related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network 
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'

npm ERR! Please include the following file with any support request:
npm ERR!     /usr/src/app/npm-debug.log

这是我的Docker脚本

FROM node:argon

ENV http_proxy http://127.0.0.1:3128/
ENV https_proxy http://127.0.0.1:3128/

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/

# setup proxies
RUN git config --global http.proxy http://127.0.0.1:3128/ && \
    npm config set strict-ssl=false \
    npm config set registry=http://registry.npmjs.org/ \
    npm config set proxy=http://127.0.0.1:3128/ && \
    npm config set https-proxy=http://127.0.0.1:3128/

# Install dependencies for node.js
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]
2个回答

6
使用--build-arg的方法是正确的:您只想在构建Docker镜像时使用代理设置,而不是将它们放在Dockerfile中,因此它不会绑定到特定环境(您不需要在其中使用ENV条目)。
您的问题在于您正在尝试在docker构建localhost中使用cntlm代理,这是无效的,因为在构建时它将指向运行构建的docker容器,但实际上应该指向在docker网络中提供cntlm的主机地址。
为了使其工作,您可以将cntlm配置为侦听多个接口,然后激活网关模式,以便您可以从其他计算机使用它。这样,在构建映像时,您将从docker实例将请求发送到主机。
我的docker桥接网络如下所示(我的主机在docker0中获得地址172.17.0.1):
$ docker network inspect bridge
...
            "Config": [
            {
                "Subnet": "172.17.0.0/16",
                "Gateway": "172.17.0.1"
            }
...

在我的 `cntlm.conf` 文件中:
...
Listen          127.0.0.1:3128
Listen          172.17.0.1:3128
...
Gateway yes
Allow           127.0.0.1/32
Allow           172.17.0.0/16
Deny            0/0
...

使用此配置,cntlm 将同时监听 localhost 和 docker 桥接网络,仅允许来自任何 docker 容器的远程连接。 然后,在使用 npm 构建映像时,您可以使用代理设置:
$ docker build --build-arg=HTTP_PROXY=http://172.17.0.1:3128 --build-arg=HTTPS_PROXY=http://172.17.0.1:3128 .

我希望能对您有所帮助,我知道在企业网络中进行所有这些操作真的很麻烦!
编辑于2016年8月18日:今天我发现一个新事物,如果你使用v2格式的docker-compose文件,则启动compose文件将为容器创建一个新网络。这意味着您需要相应地调整cntlm文件以接受来自这些新范围的连接。
例如,我的一个compose文件刚刚在172.19.0.0/16下创建了一个网络,但是我的cntlm配置只允许从172.17.0.0/16进行连接。如果您遇到连接问题,请检查syslog以确定问题所在。
参考链接:https://docs.docker.com/compose/networking/

这个问题与我的情况非常接近(尽管我的是pip而不是npm),但不幸的是,这个解决方案似乎对我不起作用。我尝试将代理放在build-args中,并尝试将其放在ENV中,但两者都没有起作用。我的端口不是3128,因为它被其他东西使用了(不清楚是什么),所以我改用8080。 我怀疑还有另一个相关的问题:https://dev59.com/irDla4cB1Zd3GeqP3Bs7 你有其他想法吗? - Leonard AB
这真的取决于你的设置。如果你正在使用本地的Windows Docker,我知道在那里使用HyperV会出现网络问题。我想你最好的选择是打开一个新的问题,详细记录你的设置。 - dlouzan
1
@dlouzan 感谢您的回复。我终于成功解决了这个问题。在我的情况下,问题不是将其更改为“bridge”网络,而是更改为“dockerNAT” IP本身。不确定为什么它会以这种方式工作。我在这里记录了详细信息(https://dev59.com/irDla4cB1Zd3GeqP3Bs7#53551452)。 - Leonard AB
FYI,在遇到相同问题并查看了包括这篇文章在内的数十篇帖子后(其解决方案似乎非常复杂),有效的方法是将简单的代理配置传递给 npm 本身。这在 Docker 构建过程中解决了问题。我所要做的就是在运行 npm install 命令之前将以下行添加到我的 Dockerfile 中:RUN npm config set http-proxy http://<my company proxy>:8099RUN npm config set https-proxy http://<my company proxy>:8099 - Lester Gray
@LesterGray 感谢你的提醒!原始问题是使用在本地主机上运行的CNTLM作为代理,这是企业开发人员典型的设置,如果您的公司代理使用NTLM身份验证(是的,生活可以如此可怕)。因此,答案从那个角度进行了解答。仅针对npm使用代理配置还有另一个缺点:它在一般情况下不起作用,例如,如果您的构建执行某种curl操作,http(s)_proxy变量将会遵循。 - dlouzan

0

我也遇到了完全相同的情况!只需在.npmrc中设置proxyhttp-proxy就可以解决问题。

proxy = http://your-company-proxy
https-proxy = http://your-company-proxy

如果你运行,可能也会起作用

RUN npm config set proxy http://your-company-proxy
RUN npm config set https-proxy http://your-company-proxy

在你的Dockerfile中。


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