
도커 컨테이너 안에서 urllib3로 외부 HTTP 요청시 다음과 같은 SSL 에러가 발생하였다.
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='어떤 호스트', port=443):
Max retries exceeded with url: 어떤 URL (Caused by SSLError)
SSLCertVerificationError certificate verify failed:
self signed certificate in certificate chain
또는
unable to get local issuer certificate
urllib3에서 HTTPS 요청 수행을 위해 HTTPSConnectionPool을 만드는 과정에서 호스트로부터 certificate 정보를 가져오는데 실패하는 문제에서 비롯되었다.
삽질 끝에 해결하는데 이 스택오버플로우 글이 큰 도움이 되었다.
일부 도커 베이스 이미지에서는 ca-certificates 패키지가 구식인 경우가 있다. 이 경우 urllib3가 제대로 인증서 정보를 가져오지 못한다. 도커파일 안에 다음 구문을 추가해 최신버젼으로 업데이트하면 해결된다.
# for SSL
RUN apt-get update && apt-get install -y ca-certificates
여전히 에러가 발생한다면 ca-certificates에 수작업으로 인증 정보(crt 파일)를 등록해야한다. letsencrypt를 사용하는 경우엔 발급된 cert.pem 파일에 해당한다. 도커를 실행하는 호스트 서버 상에서 다음 명령을 실행한다.
sudo cp /etc/letsencrypt/live/{도메인명}/cert.pem /usr/local/share/ca-certificates/my-ca.crt
sudo update-ca-certificates
다음과 같이 나타나면 성공이다.
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
에러만 빨리 없애야 하는경우 다음과 같이 설정해 ssl을 조용하게 할 수 있으나 보안 문제를 야기할 수 있다. 스택오버플로우 글 참조
import ssl
import urllib3
http = urllib3.PoolManager(cert_reqs=ssl.CERT_NONE)
http.request(...)