简体   繁体   English

Docker 容器总是显示 ssl 连接错误

[英]Docker container always shows ssl connection error

I'm getting started with docker compose and have been working through the simple demo flask application.我开始使用 docker compose 并且一直在研究简单的演示烧瓶应用程序。 The thing is, I'm running this from inside of an organization that intercepts all communication in such a way that SSL errors are thrown right and left.问题是,我在一个组织内部运行它,该组织拦截所有通信,从而左右抛出 SSL 错误。 They provide us with three root certificates we need to install, and I've generally got these working on my own machine, but I'm lost when it comes to getting these to work inside docker-compose deployments.他们为我们提供了我们需要安装的三个根证书,我通常在我自己的机器上使用这些证书,但是当让它们在 docker-compose 部署中工作时,我迷路了。

When I run docker-compose up, I get the following:当我运行 docker-compose up 时,我得到以下信息:

$ sudo docker-compose up 
Creating network "project_default" with the default driver
Building web
Step 1/5 : FROM python:3.4-alpine
3.4-alpine: Pulling from library/python
81033e7c1d6a: Pull complete
9b61101706a6: Pull complete
415e2a07c89b: Pull complete
f22df7a3f000: Pull complete
8c16bf19c1f9: Pull complete
Digest: sha256:fe436cb066394d81cf49448a04dec7c765082445a500bc44f1ae5e8a455793bd
Status: Downloaded newer image for python:3.4-alpine
 ---> 5c72717ec319
Step 2/5 : ADD . /code
 ---> a5790c0e3e94
Removing intermediate container 052c614e41d0
Step 3/5 : WORKDIR /code
 ---> a2ea9acb3005
Removing intermediate container 77f2375ca0a6
Step 4/5 : RUN pip install -r requirements.txt
 ---> Running in 5f4fe856776d
Collecting flask (from -r requirements.txt (line 1))
  Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fb0061f1d30>: Failed to establish a new connection: [Errno -3] Try again',)': /simple/flask/
  Retrying (Retry(total=3, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fb0061f19b0>: Failed to establish a new connection: [Errno -3] Try again',)': /simple/flask/
  Retrying (Retry(total=2, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fb0061f1828>: Failed to establish a new connection: [Errno -3] Try again',)': /simple/flask/
  Retrying (Retry(total=1, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fb0061f1588>: Failed to establish a new connection: [Errno -3] Try again',)': /simple/flask/
  Retrying (Retry(total=0, connect=None, read=None, redirect=None)) after connection broken by 'NewConnectionError('<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fb0061f1390>: Failed to establish a new connection: [Errno -3] Try again',)': /simple/flask/
  Could not find a version that satisfies the requirement flask (from -r requirements.txt (line 1)) (from versions: )
No matching distribution found for flask (from -r requirements.txt (line 1))

Pip fails to install anything. Pip 无法安装任何东西。

The docker-compose.yml file looks like this: docker-compose.yml 文件如下所示:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"

And the main Dockerfile looks like this:主 Dockerfile 如下所示:

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

Is there any way to be able to make this work in this particular case?在这种特殊情况下,有什么方法可以使这项工作? Is there a general solution to this sort of problem that would allow me to pass to any container deployed the SSL certificates and have them be used?是否有针对此类问题的通用解决方案,可以让我将 SSL 证书传递给任何部署的容器并使用它们?

In my case, Host machine's MTU is 1450, and Docker's MTU is 1500.就我而言,主机的 MTU 是 1450,而 Docker 的 MTU 是 1500。

Which causes docker set MSS to 1460, and then TLS "server hello" packet got bigger than 1450 bytes, so the Host machine discard it.这导致 docker 将 MSS 设置为 1460,然后 TLS “server hello” 数据包大于 1450 字节,因此主机将其丢弃。

To see if it's your case too, run ifconfig on both you Docker container and your host machine.要查看是否也是您的情况,请在 Docker 容器和主机上运行 ifconfig。 If Host's MTU is less than 1500, it's easy to run into this discarding packet situation.如果Host的MTU小于1500,很容易遇到这种丢包的情况。 Especially in HTTPS, for that "server hello" needs to send the certificate, which is a big packet特别是在HTTPS中,对于那个“server hello”需要发送证书,这是一个大包

This isn't really a docker-specific question: you are asking, in effect, "how do I install certificate authorities under Linux"?这实际上并不是一个特定于 docker 的问题:您实际上是在问“如何在 Linux 下安装证书颁发机构”? The answer is going to be the same regardless of whether you are running your ssl client inside or outside of a container.无论您是在容器内部还是外部运行 ssl 客户端,答案都是一样的。

Your Python image is based on alpine, and alpine uses the "ca-certificates" package to manage CA certificiates.您的 Python 映像基于 alpine,而 alpine 使用“ca-certificates”包来管理 CA 证书。 To install your local CA certificates, you would need to (a) copy them into the /usr/share/ca-certificates directory and (b) run update-ca-certificates .要安装本地 CA 证书,您需要 (a) 将它们复制到/usr/share/ca-certificates目录和 (b) 运行update-ca-certificates

For example, adding something like this to your Dockerfile (before your pip install ):例如,将这样的内容添加到您的 Dockerfile(在您的pip install之前):

COPY company-ca.crt /usr/share/ca-certificates
RUN update-ca-certificates

In my case, I must add in my Dockerfile these sentences:就我而言,我必须在我的 Dockerfile 中添加以下句子:

COPY company.crt /usr/local/share/ca-certificates/company.crt
RUN update-ca-certificates
...
RUN pip install --cert /etc/ssl/certs/company.pem -r requirements.txt

You need the certificate of your company in .crt format.您需要 .crt 格式的公司证书。 When docker execute update-ca-certificates, linux will create a .pem file with the same name in the path: /etc/ssl/certs/.当docker执行update-ca-certificates时,linux会在/etc/ssl/certs/路径下创建一个同名的.pem文件。 It will convert the network between pip in SSL.它将在 SSL 中的 pip 之间转换网络。

I was trying to read data from an API in my Go code and I was facing similar ssl error:我试图从 Go 代码中的 API 读取数据,但遇到了类似的 ssl 错误:

x509: certificate signed by unknown authority

My container was based on debian:stretch which is really really small ~100MB.我的容器基于debian:stretch ,它真的很小~100MB。 This happens when ca-certificates are not installed.当未安装ca-certificates时会发生这种情况。 I installed ca-certificates (which also installs openssl ) as shown below:我安装了ca-certificates (也安装了openssl ),如下所示:

FROM debian:stretch

RUN apt-get update && apt-get install -y ca-certificates --no-install-recommends && rm -rf /var/lib/apt/lists/*

# ...

This will also work for any other base images which might not have ca-certificates installed.这也适用于可能未安装ca-certificates任何其他基本映像。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM