docker項目ssl 安全證書的種種
一,使用nginx代理,將證書掛著宿主的nginx上
這個很簡單,只需要修改宿主nginx的配置文件即可
server { listen 443 ssl default; server_name www.abc.com; #項目域名 ssl_certificate "cert/ssl_certificate.pem"; #證書文件 ssl_certificate_key "cert/ssl_certificate.key"; #秘鑰文件 ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #SSL算法加密選項 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location / { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:9001; #指向本機docker 容器端口 } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
二,spingboot項目內部掛在證書
項目目錄結構如下:
即我們在項目根目錄創建一個cert目錄裏面存放證書,然後我們修改項目配置文件application.yml掛上證書
server: ssl: key-store: classpath:cert/ssl_certificate.pfx #證書文件 key-store-password: 123456 #證書密碼
打包成docker image
docker build -t springio/demo-docker .
運行
docker run -t -p 8433:8080 springio/demo-docker
本地輸入http://www.abc.com:8433 會提示
Bad Request
This combination of host and port requires TLS.
直接改為 https://www.abc.com:8433 訪問正常
三,使用openssl生成不受信任的證書
上面兩種方法都是在我們有證書的情況,如果你沒有證書,可以使用openssl生產一個測試證書,在我們的Dokcerfile中加入證書生成
FROM openjdk VOLUME /tmp ADD demo-docker-0.0.1-SNAPSHOT.war app.war RUN sh -c ‘touch /app.war‘ RUN echo "Asia/Shanghai" > /etc/timezone ENV JAVA_OPTS="" ENV spring.profiles.active="prod" #以下是生成證書 #定義簽名密碼 ENV certPassword 123456 RUN openssl genrsa -des3 -passout pass:${certPassword} -out server.key 2048 RUN openssl rsa -passin pass:${certPassword} -in server.key -out server.key RUN openssl req -sha256 -new -key server.key -out server.csr -subj ‘/CN=www.abc.com‘ #這裏是證書綁定的域名 RUN openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt RUN openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt -certfile server.crt -passout pass:${certPassword} #將證書文件綁定到項目中 ENV key-store="server.pfx" #將證書密碼傳遞給項目 ENV key-password=${certPassword} #編譯選項 ENTRYPOINT ["java", "-jar", "/app.war"]
這裏有兩點要註意,dockerfile文件中FROM 不能來源於簡化版即不是“FROM openjdk:8-jdk-alpine” ,因為alpine版本的jdk中不包含openssl,關於openssl詳細使用可以參考這裏 https://www.cnblogs.com/yangxiaolan/p/6256838.html
對應的項目配置文件application.yml內容如下
server: ssl: key-store: ${key-store} #接收證書文件 key-store-password: ${key-password} #接收證書密碼
啟動docker項目,瀏覽器輸入 https://www.abc.com,會提示證書不受信任
登錄到docker bash 會看到對應的證書文件
四,使用Let‘s Encrypt 生成受信任的證書
Let‘s Encrypt生成證書有多種方式:
Plugin |
認證 |
安裝 |
備註 |
認證方式 (端口) |
apache |
Y |
Y |
自動獲取和安裝證書,適用於Apache2.4 on OSes with libaugeas0 1.0+。 |
tls-sni-01 (443) |
webroot |
Y |
N |
通過webserver的root目錄認證來獲取證書,適用於處於運行狀態的webserver。 |
http-01 (80) |
nginx |
Y |
Y |
自動獲取和安裝證書,適用於Nginx。 |
tls-sni-01 (443) |
standalone |
Y |
N |
通過letsencrypt自帶的standalone服務來獲取證書,standalone服務將占用服務器的80或443端口,這就意味著服務器本身的webserver需要處於關閉狀態,除非它使用特殊端口。 |
http-01 (80) or tls-sni-01 (443) |
DNS plugins |
Y |
N |
通過修改DNS記錄來認證域名所有者以獲取證書,這是使用letsencrypt為通配符域名獲取證書的唯一方式。 |
dns-01 (53) |
manual |
Y |
N |
以用戶自定義的方式獲取證書,根據提示指令,用戶自己來完成域名認證。即使用交互式或腳本鉤子的方式獲取證書。 |
http-01 (80), dns-01 (53) or tls-sni-01 (443) |
使用,Let‘s Encrypt生成證書必須在你的服務器上完成,而且必須確認你的域名已經解析到服務器上,否者無法完成驗證,會提示沒有權限“ urn:ietf:params:acme:error:unauthorized” ,這裏介紹兩種比較常用方式
必須保證你在網站在運行,可以通過域名的80端口正常訪問,需要在你的服務器上安裝 certbot,最好不要使用yum install certbot 安裝 這裏會有依賴問題,因為Certbot是Python程序,最好先創建一個Python虛擬環境,然後再安裝Certbot,具體步驟如下:
sudo yum install python-virtualenv #安裝虛擬環境軟件包(針對於Python2.7) sudo virtualenv /usr/local/python-certbot #創建虛擬環境 source /usr/local/python-certbot/bin/activate #激活虛擬環境 pip install certbot #安裝Certbot pip install certbot-nginx #安裝nginx插件,如果不使用 nginx模式生成證書可不需要
也可以不安裝certbot,使用“quay.io/letsencrypt/letsencrypt”鏡像完成只需要在你的服務器上 docker pull quay.io/letsencrypt/letsencrypt 然後通過下面命令啟動
1,webroot方式:
執行證書生成命令
certbot certonly --webroot -w /usr/share/nginx/html -d www.abc.com -m ejiyuan@163.com --agree-tos
docker 鏡像方式
docker run --rm -p 8770:80 -v /etc/letsencrypt:/etc/letsencrypt -v /usr/share/nginx/html:/usr/share/nginx/html quay.io/letsencrypt/letsencrypt auth --webroot -w /usr/share/nginx/html -d q.meylink.cn -m [email protected] --agree-tos
-w
指定網站項目目錄,這個項目必須是可用的,而且是通過你的域名80端口能正常訪問的
-d
指定生成蒸魚的域名 這個域名必須已經解析到執行命令的本服務器上
-m
指定一個email 最好是真實的電郵地址
webroot方式,必須你的服務的 80 端口上運行一個能處理靜態文件的 web 服務,我這裏 nginx 為例 (註意,webroot + nginx 與 nginx 是完全不同的兩種方式)
server { listen 80 default_server; # 必須是80端口 server_name www.abc.com; # 必須能夠解析到本機 root /usr/share/nginx/html; #項目所在目錄 location / { index index.html; } }
在執行命令後,certbot 會向指定的 webroot 目錄中添加一個隨機文件,隨後 letsencrypt 會通過 http 訪問那個文件,比如 http://www.abc.com/.well-known/acme-challenge/gdEMr7ZXOiZE51he9QwuvnbrrTnkwlpFhNAcArBt2uE, 如果能返回正確的數據則通過認證,否則認證失敗,執行結果如下:
2,standalone方式:
這個方式不需要先部署項目,但是必須保證你的域名能解析到服務器上
certbot certonly --standalone -n --agree-tos --email you@gmail.com --preferred-challenges http -d you.domain.com
docker 鏡像方式
docker run --rm -p 80:80 -p 443:443 -v /etc/letsencrypt:/etc/letsencrypt quay.io/letsencrypt/letsencrypt auth --standalone -m ejiyuan@email.com --agree-tos -d www.meylink.cn
-n 非交互式
--email 指定賬戶
--agree-tos 同意服務協議
--preferred-challenges http 使用http模式 必須保證80端口沒有被占用
--preferred-challenges tls-sni:使用443端口必須保證80端口沒有被占用
默認 standalone 是使用 443 端口,也就是說要停止服務器現在占用 443 端口的進程,我們也可以將其改為使用 80 端口,同樣道理,這時需要停止 80 端口的占用,執行結果
3,apache與nginx模式,可是非常簡單的生成並掛在證書這裏以nginx為例
保證你的域名可以解析到本機,並且nginx已安裝,設置nginx配置文件
server { server_name you.domain.com; }
然後執行
certbot --nginx -d a.abc.com
執行結果如下:
nginx配置文件修改如下:
server { server_name a.abc.com; .... #一下內容是 Certbot 加入 listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/a.abc.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/a.abc.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }
4,生成證書部署docker image
FROM alpine #安裝證書生成工具 RUN apk add --update bash certbot RUN apk add --no-cache libressl #掛在一個外部路徑 VOLUME ["/etc/letsencrypt"] RUN apk add --update bash nginx #拷貝證書 #COPY ./cert /etc/letsencrypt/live #拷貝項目文件 COPY ./www /usr/share/nginx/html #拷貝項目配置文件 COPY ./nginx/nginx.conf /etc/nginx/nginx.conf COPY ./nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf #切換目錄設置權限 WORKDIR /usr/share/nginx/html RUN chown -R daemon:daemon * && chmod -R 755 * EXPOSE 80 EXPOSE 433 #切換到nginx目錄,啟動nginx WORKDIR /run/nginx #ENTRYPOINT nginx -g "daemon off;" ENTRYPOINT certbot certonly --standalone -n --agree-tos --email [email protected] --preferred-challenges http -d www.meylink.cn && nginx -g "daemon off;"
參考文檔
全民https時代,Let‘s Encrypt免費SSL證書的申請及使用(Tomcat版)
https 證書工具 Letsencrypt 簡單教程
Certbot 自動化生成 https 證書
Letsencrypt SSL免費證書申請(Docker)
CentOS7運行Certbot提示:ImportError: ‘pyOpenSSL‘ module missing required functionality. Try upgrading to v0.14 or newer.
Docker:使用Dockerfile構建Nginx鏡像
通過Laradock學Docker-HTTPS
給Docker中的Nginx搭建HTTPS環境
docker項目ssl 安全證書的種種