docker項目ssl 安全證書的種種

一,證書掛着宿主的nginx上html

這個很簡單,只須要修改宿主nginx的配置文件便可java

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 {
        }
    }

二,證書掛載到容器項目上python

這裏以nginx爲例,docker文件以下:linux

FROM alpine
#安裝nginx服務器 RUN apk add --update bash nginx #拷貝證書 COPY ./cert /usr/nginx/cert #拷貝項目文件 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 443 #切換到nginx目錄,啓動nginx WORKDIR /run/nginx ENTRYPOINT nginx -g "daemon off;"

或直接 from nginxnginx

#這裏咱們用alpine簡版就能夠
FROM nginx:alpine 
#拷貝證書
COPY ./cert /usr/nginx/cert
#拷貝項目配置文件,配置文件主要是掛載證書開啓443監聽
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
COPY ./www /usr/share/nginx/html/
WORKDIR /usr/share/nginx/html/
RUN chown -R daemon:daemon * && chmod -R 755 *
EXPOSE 80
EXPOSE 443

nginx 配置文件web

1) nginx.conf算法

user nginx;
worker_processes  1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on;  keepalive_timeout 65; #gzip on;  include /etc/nginx/conf.d/*.conf; }

2) conf.d/default.confspring

server {
    listen 80; listen 443 ssl; 開啓443 ssl server_name www.abc.com; #你的域名 ssl_certificate "/usr/nginx/cert/cn.pem"; #證書文件 ssl_certificate_key "/usr/nginx/cert/cn.key"; #證書祕鑰  location / { root /usr/share/nginx/html; index index.html index.htm; } }

 三,spingboot項目內部掛在證書docker

項目目錄結構以下:apache

 

即咱們在項目根目錄建立一個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詳細使用能夠參考這裏 http://www.javashuo.com/article/p-hxpcxuic-p.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 ejiyuan@263.com --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 you.domain.com

-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
#安裝nginx服務器
RUN apk add --update bash nginx
#拷貝項目文件
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
#掛在外部路徑方便查看生產的證書與容器內部nginx配置
VOLUME ["/etc/letsencrypt","etc/nginx"]
#切換目錄設置權限
WORKDIR /usr/share/nginx/html
RUN chown -R daemon:daemon * && chmod -R 755 *
EXPOSE 80
EXPOSE 443
#切換到nginx目錄,啓動nginx
WORKDIR /run/nginx
ENTRYPOINT certbot certonly --standalone -n --agree-tos --email ejiyuan@gmail.com --preferred-challenges http -d you.domain.com && nginx -g "daemon off;"

因一個Dockerfile不能同時FROM certbot又FROM nginx,因此這裏使用alpine(它一個小型的 linux髮型版本,想了解他看這裏:Alpine Linux 使用簡介)而後安裝 certbot和nginx

 對應的nginx配置文件nginx.conf以下:

user nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

conf.d/default.conf

server {
    listen 80;
    listen 443 ssl;
    server_name www.abc.cn; #配置的域名
     ssl_certificate "/etc/letsencrypt/live/www.abc.cn/fullchain.pem";  #letsencrypt證書路徑,證書會自動生成在這個路徑下面
    ssl_certificate_key "/etc/letsencrypt/live/www.abc.cn/privkey.pem"; #letsencrypt祕鑰路徑,證書祕鑰會自動生成在這個路徑下面
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

 

六,參考文檔

全民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環境

相關文章
相關標籤/搜索