为 node.js 应用构建 docker 图像在代理后失败
Building a docker image for a node.js app fails behind proxy
我在 docker 构建期间遇到 npm 问题。我是一家公司代理人,阅读了大约 30 篇解决类似问题的文章(和 Whosebug 帖子)。然而我还是没能克服这个问题。
我能够 "npm install" 项目并在 docker 构建过程之外获取所有必要的依赖项(但也使用代理),但不能在构建过程中。
目前我尝试过的:
- 直接使用代理(连同硬编码的授权数据)以及
通过 CNTLM。下面的描述是使用 CNTLM 时的情况。
- 使用如下所示的 http 存储库 strict_ssl false。
npm config set strict-ssl=false \
npm config set registry=http://registry.npmjs.org/ \
将代理设置作为 --build-arg、env 并通过 运行 参数传递
从干净的 git 结帐(没有 node_modules)开始,之后
运行 npm 安装
我正在尝试构建:
$ 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" ]
使用 --build-arg
的方法是正确的:您只想在构建 Docker 图像时使用代理设置,而不是将它们放在 Docker 文件中,因此它不依赖于特定环境(您不需要 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 将监听本地主机和 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 日
我今天发现的一点是,如果您使用 docker-compose v2 格式的文件,启动 compose 文件将为您的容器创建一个新网络。这意味着您需要相应地调整您的 cntlm 文件以接受来自这些新范围的连接。
例如,我的一个撰写文件刚刚在 172.19.0.0/16
下创建了一个网络,但我的 cntlm 配置只允许来自 172.17.0.0/16
的连接。如果您遇到连接问题,请检查您的系统日志以确定问题所在。
我在 docker 构建期间遇到 npm 问题。我是一家公司代理人,阅读了大约 30 篇解决类似问题的文章(和 Whosebug 帖子)。然而我还是没能克服这个问题。
我能够 "npm install" 项目并在 docker 构建过程之外获取所有必要的依赖项(但也使用代理),但不能在构建过程中。
目前我尝试过的:
- 直接使用代理(连同硬编码的授权数据)以及 通过 CNTLM。下面的描述是使用 CNTLM 时的情况。
- 使用如下所示的 http 存储库 strict_ssl false。
npm config set strict-ssl=false \
npm config set registry=http://registry.npmjs.org/ \
将代理设置作为 --build-arg、env 并通过 运行 参数传递
从干净的 git 结帐(没有 node_modules)开始,之后 运行 npm 安装
我正在尝试构建:
$ 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" ]
使用 --build-arg
的方法是正确的:您只想在构建 Docker 图像时使用代理设置,而不是将它们放在 Docker 文件中,因此它不依赖于特定环境(您不需要 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 将监听本地主机和 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 日
我今天发现的一点是,如果您使用 docker-compose v2 格式的文件,启动 compose 文件将为您的容器创建一个新网络。这意味着您需要相应地调整您的 cntlm 文件以接受来自这些新范围的连接。
例如,我的一个撰写文件刚刚在 172.19.0.0/16
下创建了一个网络,但我的 cntlm 配置只允许来自 172.17.0.0/16
的连接。如果您遇到连接问题,请检查您的系统日志以确定问题所在。