[英]What is the most secure way to use Let's Encrypt certificates with Node.js?
[英]How to use Let's Encrypt with Docker container based on the Node.js image
我做的第一件事就是創建一個簡單的基於表達式的docker鏡像。
我正在使用以下app.js
,取自他們的docs中的express的hello world示例 :
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
在同一個doc中運行npm init
后,我也得到了以下的packages.json
文件:
{
"name": "exampleexpress",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.14.0"
}
}
我創建了以下Dockerfile:
FROM node:onbuild
EXPOSE 3000
CMD node app.js
這是我執行docker build
步驟時的輸出。 為簡潔起見,我刪除了大部分的npm install
輸出:
$ docker build -t exampleexpress .
Sending build context to Docker daemon 1.262 MB
Step 1 : FROM node:onbuild
# Executing 3 build triggers...
Step 1 : COPY package.json /usr/src/app/
Step 1 : RUN npm install
---> Running in 981ca7cb7256
npm info it worked if it ends with ok
<snip>
npm info ok
Step 1 : COPY . /usr/src/app
---> cf82ea76e369
Removing intermediate container ccd3f79f8de3
Removing intermediate container 391d27f33348
Removing intermediate container 1c4feaccd08e
Step 2 : EXPOSE 3000
---> Running in 408ac1c8bbd8
---> c65c7e1bdb94
Removing intermediate container 408ac1c8bbd8
Step 3 : CMD node app.js
---> Running in f882a3a126b0
---> 5f0f03885df0
Removing intermediate container f882a3a126b0
Successfully built 5f0f03885df0
運行此圖像的工作方式如下:
$ docker run -d --name helloworld -p 3000:3000 exampleexpress
$ curl 127.0.0.1:3000
Hello World!
我們可以通過以下方式清理它: docker rm -f helloworld
現在,我已經在Docker容器中運行了我的基本的基於快速的網站,但它還沒有設置任何TLS。 再看一下expressjs文檔,使用TLS時的安全性最佳實踐是使用nginx。
由於我想介紹一個新組件(nginx),我將使用第二個容器。
由於nginx需要一些證書才能使用,讓我們繼續使用letsencrypt客戶端生成那些證書。 關於如何在Docker中使用letsencrypt的letsencrypt文檔可以在這里找到: http ://letsencrypt.readthedocs.io/en/latest/using.html#running-with-docker
運行以下命令以生成初始證書。 您需要在連接到公共Internet的系統上運行此程序,並且可以從letsencrypt服務器訪問端口80/443。 您還需要設置DNS名稱並指向您運行此命令的框:
export LETSENCRYPT_EMAIL=<youremailaddress>
export DNSNAME=www.example.com
docker run --rm \
-p 443:443 -p 80:80 --name letsencrypt \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
quay.io/letsencrypt/letsencrypt:latest \
certonly -n -m $LETSENCRYPT_EMAIL -d $DNSNAME --standalone --agree-tos
確保替換LETSENCRYPT_EMAIL
和DNSNAME
的值。 電子郵件地址用於到期通知。
現在,讓我們設置一個將使用這個新生成的證書的nginx服務器。 首先,我們需要一個為TLS配置的nginx配置文件:
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 /dev/stdout main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location ^~ /.well-known/ {
root /usr/share/nginx/html;
allow all;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://expresshelloworld:3000;
}
}
}
我們可以使用以下Dockerfile將此配置文件放入我們自己的自定義nginx映像中:
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
這可以使用以下命令docker build -t expressnginx .
: docker build -t expressnginx .
接下來,我們將創建一個自定義網絡,以便我們可以利用Docker的服務發現功能:
docker network create -d bridge expressnet
現在,我們可以啟動helloworld和nginx容器:
docker run -d \
--name expresshelloworld --net expressnet exampleexpress
docker run -d -p 80:80 -p 443:443 \
--name expressnginx --net expressnet \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /usr/share/nginx/html:/usr/share/nginx/html \
expressnginx
通過查看docker logs expressnginx
輸出,仔細檢查nginx是否正常。
nginx配置文件應該將端口80上的任何請求重定向到端口443.我們可以通過運行以下命令來測試它:
curl -v http://www.example.com/
此時,我們還應該能夠成功建立TLS連接,並查看我們的Hello World!
回復:
curl -v https://www.example.com/
現在,設置續訂過程。 上面的nginx.conf為webroot驗證方法提供了letsencrypt .well-known路徑。 如果運行以下命令,它將處理續訂。 通常,您將在某種類型的cron上運行此命令,以便在證書過期之前續訂證書:
export LETSENCRYPT_EMAIL=me@example.com
export DNSNAME=www.example.com
docker run --rm --name letsencrypt \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
-v "/usr/share/nginx/html:/usr/share/nginx/html" \
quay.io/letsencrypt/letsencrypt:latest \
certonly -n --webroot -w /usr/share/nginx/html -d $DNSNAME --agree-tos
我最近實現了https,讓我們使用nginx進行加密。 我列出了我所面臨的挑戰,以及我在這里逐步實施的方式。
挑戰 :
克服它的步驟 :
以下指南獨立於您擁有的應用程序類型,因為它只涉及nginx和docker。
現在停止這個nginx服務器並開始構建你的應用程序。 在容器上安裝nginx並在docker容器上打開端口80,443。 (如果在ec2實例上使用aws打開也默認為aws只打開端口80)
這將在您的應用上啟用https。 如果您無法觀察,並且正在使用chrome嘗試清除dns緩存中的chrome
自動續訂流程:
您可以在這里查看: https : //certbot.eff.org/docs/using.html?highlight = tokener#runingwithwith-bucketer
然后我個人做的是:
現在,如果您正確配置了nginx(指向正確的TLS證書路徑和代理到正確的URL,例如http:// my-app:3210 ),您應該可以通過https訪問您的應用。
前端 - NGINX - 監聽443端口,以及beck結束的代理
后端 - 您的泊塢窗容器
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.