Контейнер Docker всегда показывает ошибку соединения ssl
Я начинаю с docker compose и работаю через простое демо-приложение. Дело в том, что я запускаю это изнутри организации, которая перехватывает все коммуникации таким образом, что ошибки SSL выбрасываются вправо и влево. Они предоставляют нам три корневых сертификата, которые нам нужно установить, и я обычно заставляю их работать на моем собственном компьютере, но я теряюсь, когда дело доходит до того, чтобы заставить их работать внутри развертываний docker-compose.
Когда я запускаю 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))
Пип не может ничего установить.
Файл docker-compose.yml выглядит так:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
И основной Dockerfile выглядит так:
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
Есть ли способ сделать эту работу в данном конкретном случае? Существует ли общее решение проблемы такого рода, которое позволило бы мне перейти к любому контейнеру, в котором развернуты сертификаты SSL, и можно ли их использовать?
1 ответ
На самом деле это не специфический для докера вопрос: вы спрашиваете, "как мне установить центры сертификации в Linux"? Ответ будет одинаковым, независимо от того, используете ли вы свой ssl-клиент внутри или снаружи контейнера.
Ваш образ Python основан на Alpine, и Alpine использует пакет "ca-Certificates" для управления сертификатами CA. Чтобы установить локальные сертификаты CA, вам необходимо (а) скопировать их в /usr/share/ca-certificates
каталог и (б) запустить update-ca-certificates
,
Например, добавив что-то подобное в ваш Dockerfile (до pip install
):
COPY company-ca.crt /usr/share/ca-certificates
RUN update-ca-certificates
В моем случае я должен добавить в свой 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
Вам нужен сертификат вашей компании в формате.crt. Когда docker выполнит update-ca-сертификаты, linux создаст файл.pem с тем же именем в пути: /etc/ssl/certs/. Это преобразует сеть между пунктами в SSL.
В моем случае MTU хост-машины равен 1450, а MTU докера - 1500.
Это приводит к тому, что docker устанавливает MSS на 1460, а затем пакет TLS "server hello" становится больше 1450 байт, поэтому хост-машина его отбрасывает.
Чтобы убедиться, что это тоже ваш случай, запустите ifconfig как на контейнере Docker, так и на вашем хост-компьютере. Если MTU хоста меньше 1500, легко столкнуться с такой ситуацией отбрасывания пакетов. Особенно в HTTPS, для этого "сервер привет" необходимо отправить сертификат, который представляет собой большой пакет
Я пытался прочитать данные из API в моем коде Go и столкнулся с аналогичной ошибкой ssl:
x509: certificate signed by unknown authority
Мой контейнер был основан на debian:stretch
что действительно очень мало ~100 МБ. Это случается когдаca-certificates
не установлены. Я установил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/*
# ...
Это также будет работать для любых других базовых изображений, которые могут не иметь ca-certificates
установлен.