Ngày đăng: 1 tháng 4 năm 2024
Có nhiều cách để nâng cao tính linh hoạt và bảo mật cho ứng dụng Node.js của bạn. Sử dụng proxy ngược như Nginx sẽ cung cấp cho bạn các yêu cầu cân bằng tải, lưu trữ nội dung tĩnh và triển khai Transport Layer Security (TLS). Việc bật HTTPS được mã hóa trên máy chủ của bạn sẽ đảm bảo rằng hoạt động liên lạc đến và đi từ ứng dụng của bạn vẫn được an toàn.
Việc triển khai proxy ngược bằng TLS/SSL trên vùng chứa bao gồm một bộ quy trình khác với hoạt động trực tiếp trên hệ điều hành máy chủ. Ví dụ: nếu bạn đang lấy chứng chỉ từ Let's Encrypt cho một ứng dụng chạy trên máy chủ, bạn sẽ cài đặt phần mềm cần thiết trực tiếp trên máy chủ của mình. Vùng chứa cho phép bạn thực hiện một cách tiếp cận khác. Khi sử dụng Docker Compose, bạn có thể tạo các vùng chứa cho ứng dụng, máy chủ web và ứng dụng khách Certbot để cho phép bạn lấy chứng chỉ của mình. Bằng cách làm theo các bước này, bạn có thể tận dụng tính mô-đun và tính di động của quy trình làm việc được đóng gói.
Trong hướng dẫn này, bạn sẽ triển khai ứng dụng Node.js với proxy ngược Nginx bằng Docker Compose. Bạn sẽ nhận được chứng chỉ TLS/SSL cho miền được liên kết với ứng dụng của bạn và đảm bảo rằng nó nhận được xếp hạng bảo mật cao từ SSL Labs. Cuối cùng, bạn sẽ thiết lập một công việc cron
để gia hạn chứng chỉ của mình và giúp miền của bạn luôn được bảo mật.
Để làm theo hướng dẫn này, bạn sẽ cần:
sudo
và tường lửa đang hoạt động. Để được hướng dẫn về cách thiết lập những thứ này, vui lòng đọc hướng dẫn Thiết lập máy chủ ban đầu với Ubuntu 18.04.your_domain
trỏ đến địa chỉ IP công cộng của máy chủ của bạn.www.your_domain
trỏ đến địa chỉ IP công cộng của máy chủ của bạn.Khi bạn đã thiết lập xong mọi thứ, bạn đã sẵn sàng bắt đầu bước đầu tiên.
Bước đầu tiên, bạn sẽ sao chép kho lưu trữ bằng mã ứng dụng Node, bao gồm Dockerfile để xây dựng hình ảnh ứng dụng của bạn bằng Compose. Sau đó, bạn sẽ kiểm tra ứng dụng bằng cách xây dựng và chạy nó bằng lệnh docker run
mà không cần proxy ngược hoặc SSL.
Trong thư mục chính của non-root user của bạn, hãy sao chép kho lưu trữ nodejs-image-demo
từ tài khoản GitHub. Kho lưu trữ này bao gồm mã từ quá trình thiết lập được mô tả trong Cách xây dựng ứng dụng Node.js bằng Docker.
Sao chép kho lưu trữ vào một thư mục. Ví dụ này sử dụng node_project
làm tên thư mục. Hãy đặt tên thư mục này theo ý thích của bạn:
- git clone https://github.com/do-community/nodejs-image-demo.git node_project
Thay đổi vào thư mục node_project
:
- cd node_project
Trong thư mục này, có một Dockerfile chứa hướng dẫn xây dựng ứng dụng Node bằng cách sử dụng hình ảnh Docker node:10
và nội dung của thư mục dự án hiện tại của bạn. Bạn có thể xem trước nội dung của Dockerfile bằng cách sau:
- cat Dockerfile
OutputFROM node:10-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 8080
CMD [ "node", "app.js" ]
Các hướng dẫn này xây dựng hình ảnh Node bằng cách sao chép mã dự án từ thư mục hiện tại vào vùng chứa và cài đặt các phần phụ thuộc bằng npm install
. Họ cũng tận dụng bộ nhớ đệm và phân lớp hình ảnh của Docker bằng cách tách bản sao của pack.json
và package-lock.json
, chứa các phần phụ thuộc được liệt kê của dự án, từ bản sao của phần còn lại của mã ứng dụng. Cuối cùng, hướng dẫn chỉ định rằng vùng chứa sẽ được chạy với tư cách là non-root node user với các quyền thích hợp được đặt trên mã ứng dụng và thư mục node_modules
.
Để biết thêm thông tin về các phương pháp hay nhất về Dockerfile và hình ảnh Node này, vui lòng khám phá phần thảo luận đầy đủ trong Bước 3 của Cách xây dựng ứng dụng Node.js bằng Docker.
Để kiểm tra ứng dụng không có SSL, bạn có thể xây dựng và gắn thẻ hình ảnh bằng cách sử dụng docker build
và cờ -t
. Ví dụ này đặt tên cho hình ảnh node-demo
, nhưng bạn có thể tự do đặt tên cho nó bằng tên khác:
- docker build -t node-demo .
Khi quá trình xây dựng hoàn tất, bạn có thể liệt kê hình ảnh của mình bằng docker images
:
- docker images
Đầu ra sau đây xác nhận việc xây dựng hình ảnh ứng dụng:
OutputREPOSITORY TAG IMAGE ID CREATED SIZE
node-demo latest 23961524051d 7 seconds ago 73MB
node 10-alpine 8a752d5af4ce 3 weeks ago 70.7MB
Tiếp theo, tạo vùng chứa bằng docker run
. Ba cờ được bao gồm trong lệnh này:
-p
: Điều này xuất bản cổng trên vùng chứa và ánh xạ nó tới một cổng trên máy chủ của bạn. Bạn sẽ sử dụng cổng 80
trên máy chủ trong ví dụ này, nhưng vui lòng sửa đổi cổng này nếu cần nếu bạn có một quy trình khác đang chạy trên cổng đó. Để biết thêm thông tin về cách thức hoạt động của tính năng này, hãy xem lại cuộc thảo luận này trong tài liệu Docker về liên kết cổng.-d
: Cái này chạy container ở chế độ nền.--name
: Điều này cho phép bạn đặt cho vùng chứa một cái tên dễ nhớ.Chạy lệnh sau để xây dựng vùng chứa:
- docker run --name node-demo -p 80:8080 -d node-demo
Kiểm tra các container đang chạy của bạn bằng docker ps
:
- docker ps
Đầu ra sau đây xác nhận rằng vùng chứa ứng dụng của bạn đang chạy:
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo
Bây giờ bạn có thể truy cập miền của mình để kiểm tra thiết lập của mình: http://your_domain
. Hãy nhớ thay thế your_domain
bằng tên miền của riêng bạn. Ứng dụng của bạn sẽ hiển thị trang đích sau:
Bây giờ bạn đã kiểm tra ứng dụng, bạn có thể dừng vùng chứa và xóa hình ảnh. Sử dụng docker ps
để lấy CONTAINER ID
của bạn:
- docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4133b72391da node-demo "node app.js" 17 seconds ago Up 16 seconds 0.0.0.0:80->8080/tcp node-demo
Dừng vùng chứa bằng docker stop
. Đảm bảo thay thế CONTAINER ID
được liệt kê ở đây bằng CONTAINER ID
ứng dụng của riêng bạn:
- docker stop 4133b72391da
Bây giờ bạn có thể xóa vùng chứa đã dừng và tất cả các hình ảnh, bao gồm cả hình ảnh không được sử dụng và hình ảnh lơ lửng (dangling images), bằng docker system prune
và cờ -a
:
- docker system prune -a
Nhấn y
khi được nhắc ở đầu ra để xác nhận rằng bạn muốn xóa vùng chứa và hình ảnh đã dừng. Xin lưu ý rằng thao tác này cũng sẽ xóa bộ nhớ đệm bản dựng của bạn.
Sau khi thử nghiệm hình ảnh ứng dụng, bạn có thể chuyển sang xây dựng phần còn lại của thiết lập bằng Docker Compose.
Với ứng dụng Dockerfile của chúng ta đã có sẵn, bạn sẽ tạo một tệp cấu hình để chạy vùng chứa Nginx của mình. Bạn có thể bắt đầu với cấu hình tối thiểu bao gồm tên miền, gốc tài liệu, thông tin proxy và khối vị trí để chuyển các yêu cầu của Certbot tới thư mục .well-known
, nơi nó sẽ đặt một tệp tạm thời để xác thực DNS cho của bạn tên miền phân giải đến máy chủ của bạn.
Đầu tiên, tạo một thư mục trong thư mục dự án hiện tại, node_project
, cho tệp cấu hình:
- mkdir nginx-conf
Tạo và mở tệp bằng nano
hoặc trình chỉnh sửa yêu thích của bạn:
- nano nginx-conf/nginx.conf
Thêm khối máy chủ sau vào các yêu cầu của proxy user vào vùng chứa ứng dụng Node của bạn và chuyển các yêu cầu của Certbot tới thư mục .well-known
. Đảm bảo thay thế your_domain
bằng tên miền của riêng bạn:
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name your_domain www.your_domain;
location / {
proxy_pass http://nodejs:8080;
}
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
}
Khối máy chủ này sẽ cho phép bạn khởi động vùng chứa Nginx làm proxy ngược, nó sẽ chuyển các yêu cầu đến vùng chứa ứng dụng Node của bạn. Nó cũng sẽ cho phép bạn sử dụng plugin webroot của Certbot để lấy chứng chỉ cho miền của bạn. Plugin này phụ thuộc vào phương thức xác thực HTTP-01, sử dụng yêu cầu HTTP để chứng minh rằng Certbot có thể truy cập tài nguyên từ máy chủ phản hồi một tên miền nhất định.
Sau khi chỉnh sửa xong, hãy lưu và đóng tệp. Nếu bạn đã sử dụng nano
, bạn có thể thực hiện việc này bằng cách nhấn CTRL + X
, sau đó là Y
và ENTER
. Để tìm hiểu thêm về máy chủ Nginx và thuật toán khối vị trí, vui lòng tham khảo bài viết về Tìm hiểu thuật toán lựa chọn khối vị trí và máy chủ Nginx.
Với các chi tiết cấu hình máy chủ web đã có, bạn có thể chuyển sang tạo tệp docker-compose.yml
, tệp này sẽ cho phép bạn tạo các dịch vụ ứng dụng và vùng chứa Certbot mà bạn sẽ sử dụng để lấy chứng chỉ của mình.
Tệp docker-compose.yml
sẽ xác định các dịch vụ của bạn, bao gồm ứng dụng Node và máy chủ web. Nó sẽ chỉ định các chi tiết như khối lượng (volumes) được đặt tên, điều này sẽ rất quan trọng để chia sẻ thông tin xác thực SSL giữa các vùng chứa, cũng như thông tin mạng và cổng. Nó cũng sẽ cho phép bạn chỉ định các lệnh sẽ chạy khi vùng chứa của bạn được tạo. Tệp này là tài nguyên trung tâm sẽ xác định cách các dịch vụ của bạn sẽ hoạt động cùng nhau.
Tạo và mở tệp trong thư mục hiện tại của bạn:
- nano docker-compose.yml
Đầu tiên, xác định dịch vụ ứng dụng:
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
Định nghĩa dịch vụ của nodejs
bao gồm:
build
: Phần này xác định các tùy chọn cấu hình, bao gồm context
và dockerfile
, sẽ được áp dụng khi Compose xây dựng hình ảnh ứng dụng. Nếu muốn sử dụng hình ảnh hiện có từ sổ đăng ký như Docker Hub, bạn có thể sử dụng hướng dẫn image
thay thế, kèm theo thông tin về tên người dùng, kho lưu trữ và thẻ hình ảnh của bạn.context
: Điều này xác định bối cảnh xây dựng cho hình ảnh ứng dụng build. Trong trường hợp này, đó là thư mục dự án hiện tại được biểu thị bằng phần mở rộng .
.dockerfile
: Điều này chỉ định Dockerfile mà Compose sẽ sử dụng cho bản dựng - Dockerfile đã được xem xét ở Bước 1.image
, container_name
: Những tên này áp dụng cho hình ảnh và vùng chứa.restart
: Điều này xác định chính sách khởi động lại. Mặc định là no
, nhưng trong ví dụ này, vùng chứa được đặt để khởi động lại trừ khi nó bị dừng.Lưu ý rằng bạn không bao gồm các liên kết gắn kết với dịch vụ này vì thiết lập của bạn tập trung vào việc triển khai hơn là phát triển. Để biết thêm thông tin, vui lòng đọc tài liệu Docker về bind mounts và volumes.
Để cho phép liên lạc giữa ứng dụng và vùng chứa máy chủ web, hãy thêm bridge network có tên là app-network
sau định nghĩa khởi động lại:
services:
nodejs:
...
networks:
- app-network
Bridge network do người dùng xác định như thế này cho phép liên lạc giữa các vùng chứa trên cùng một máy chủ Docker daemon. Điều này hợp lý hóa lưu lượng truy cập và liên lạc trong ứng dụng của bạn, vì nó mở tất cả các cổng giữa các vùng chứa trên cùng một bridge network, trong khi không để lộ cổng nào ra thế giới bên ngoài. Do đó, bạn có thể chọn lọc chỉ mở các cổng bạn cần để hiển thị các dịch vụ giao diện người dùng của mình.
Tiếp theo, xác định dịch vụ webserver
:
...
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- nodejs
networks:
- app-network
Một số cài đặt được xác định ở đây cho dịch vụ nodejs
vẫn giữ nguyên, nhưng một số thay đổi sau đã được thực hiện:
image
: Lệnh này yêu cầu Compose lấy hình ảnh Nginx dựa trên Alpine mới nhất từ Docker Hub. Để biết thêm thông tin về hình ảnh alpine
, vui lòng đọc Bước 3 của Cách xây dựng ứng dụng Node.js bằng Docker.ports
: Điều này hiển thị cổng 80
để kích hoạt các tùy chọn cấu hình mà bạn đã xác định trong cấu hình Nginx của mình.Các volumes và bind mounts được đặt tên sau đây cũng được chỉ định:
web-root:/var/www/html
: Điều này sẽ thêm nội dung tĩnh của trang web của bạn, được sao chép vào một ổ đĩa có tên là web-root
, vào thư mục /var/www/html
trên vùng chứa../nginx-conf:/etc/nginx/conf.d
: Điều này sẽ liên kết gắn thư mục cấu hình Nginx trên máy chủ với thư mục có liên quan trên vùng chứa, đảm bảo rằng mọi thay đổi bạn thực hiện đối với các tệp trên máy chủ sẽ được phản ánh trong vùng chứa.certbot-etc:/etc/letsencrypt
: Điều này sẽ gắn các chứng chỉ và khóa Let's Encrypt có liên quan cho miền của bạn vào thư mục thích hợp trên vùng chứa.certbot-var:/var/lib/letsencrypt
: Điều này gắn kết thư mục làm việc mặc định của Let's Encrypt vào thư mục thích hợp trên vùng chứa.Tiếp theo, thêm các tùy chọn cấu hình cho vùng chứa certbot
. Đảm bảo thay thế thông tin tên miền và email bằng tên miền và email liên hệ của riêng bạn:
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
Định nghĩa này yêu cầu Compose lấy hình ảnh certbot/certbot từ Docker Hub. Nó cũng sử dụng các volumes được đặt tên để chia sẻ tài nguyên với bộ chứa Nginx, bao gồm chứng chỉ miền và khóa trong certbot-etc
, thư mục làm việc Let's Encrypt trong certbot-var
và mã ứng dụng trong web-root
.
Một lần nữa, bạn đã sử dụng depends_on
để chỉ định rằng vùng chứa certbot
sẽ được khởi động sau khi dịch vụ webserver
đang chạy.
Tùy chọn command
chỉ định lệnh sẽ chạy khi vùng chứa được khởi động. Nó bao gồm lệnh con certonly
với các tùy chọn sau:
--webroot
: Điều này yêu cầu Certbot sử dụng plugin webroot để đặt các tệp vào thư mục webroot để xác thực.--webroot-path
: Điều này chỉ định đường dẫn của thư mục webroot.--email
: Email ưa thích của bạn để đăng ký và khôi phục.--agree-tos
: Điều này xác định rằng bạn đồng ý với Thỏa thuận thuê bao của ACME.--no-eff-email
: Điều này cho Certbot biết rằng bạn không muốn chia sẻ email của mình với Electronic Frontier Foundation (EFF). Hãy bỏ qua điều này nếu bạn muốn.--staging
: Điều này cho Certbot biết rằng bạn muốn sử dụng môi trường chạy thử của Let's Encrypt để lấy chứng chỉ kiểm tra. Việc sử dụng tùy chọn này cho phép bạn kiểm tra các tùy chọn cấu hình của mình và tránh các giới hạn yêu cầu tên miền có thể có. Để biết thêm thông tin về các giới hạn này, vui lòng đọc tài liệu về giới hạn tốc độ của Let's Encrypt.-d
: Điều này cho phép bạn chỉ định tên miền bạn muốn áp dụng cho yêu cầu của mình. Trong trường hợp này, bạn đã bao gồm your_domain
và www.your_domain
. Hãy chắc chắn thay thế chúng bằng tên miền của riêng bạn.Bước cuối cùng, thêm định nghĩa volume và network. Hãy nhớ thay thế tên người dùng ở đây bằng non-root user của riêng bạn:
...
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/views/
o: bind
networks:
app-network:
driver: bridge
Volumes được đặt tên của bạn bao gồm chứng chỉ Certbot và volumes thư mục làm việc của bạn và volumes cho tài nguyên tĩnh trên trang web của bạn, web-root
. Trong hầu hết các trường hợp, trình điều khiển mặc định cho tập Docker là trình điều khiển local
, trên Linux chấp nhận các tùy chọn tương tự như lệnh mount
. Nhờ điều này, bạn có thể chỉ định danh sách các tùy chọn trình điều khiển với driver_opts
, gắn thư mục views
trên máy chủ, trong đó chứa các tài nguyên tĩnh ứng dụng của bạn, vào volume khi chạy. Nội dung thư mục sau đó có thể được chia sẻ giữa các vùng chứa. Để biết thêm thông tin về nội dung của thư mục views
, vui lòng đọc Bước 2 về cách xây dựng ứng dụng Node.js với Docker.
Sau đây là tệp docker-compose.yml
hoàn chỉnh:
version: '3'
services:
nodejs:
build:
context: .
dockerfile: Dockerfile
image: nodejs
container_name: nodejs
restart: unless-stopped
networks:
- app-network
webserver:
image: nginx:mainline-alpine
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
depends_on:
- nodejs
networks:
- app-network
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
volumes:
certbot-etc:
certbot-var:
web-root:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/views/
o: bind
networks:
app-network:
driver: bridge
Với các định nghĩa dịch vụ được áp dụng bạn đã sẵn sàng khởi động vùng chứa và kiểm tra các yêu cầu chứng chỉ của mình.
Bạn có thể khởi động các vùng chứa bằng docker-compose up
. Điều này sẽ tạo và chạy các vùng chứa và dịch vụ của bạn theo thứ tự bạn đã chỉ định. Sau khi yêu cầu miền của bạn thành công, chứng chỉ của bạn sẽ được gắn vào thư mục /etc/letsencrypt/live
trên vùng chứa webserver
.
Tạo các dịch vụ với docker-compose up
bằng cờ -d
, cờ này sẽ chạy các vùng chứa nodejs
và webserver
trong nền:
- docker-compose up -d
Đầu ra của bạn sẽ xác nhận rằng dịch vụ của bạn đã được tạo:
OutputCreating nodejs ... done
Creating webserver ... done
Creating certbot ... done
Sử dụng docker-compose ps
để kiểm tra trạng thái dịch vụ của bạn:
- docker-compose ps
Nếu mọi thứ đều thành công, các dịch vụ nodejs
và webserver
của bạn sẽ Up
và vùng chứa certbot
sẽ thoát với thông báo trạng thái 0
:
Output Name Command State Ports
------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nodejs node app.js Up 8080/tcp
webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp
Nếu bạn nhận thấy bất cứ điều gì khác ngoài Up
trong cột State
đối với các dịch vụ nodejs
và webserver
hoặc trạng thái thoát khác 0
đối với vùng chứa certbot
, hãy nhớ kiểm tra nhật ký dịch vụ bằng lệnh docker-compose logs
. Ví dụ: nếu bạn muốn kiểm tra nhật ký Certbot, bạn sẽ chạy:
- docker-compose logs certbot
Bây giờ bạn có thể kiểm tra xem thông tin đăng nhập của bạn đã được gắn vào vùng chứa webserver
hay chưa bằng docker-compose exec
:
- docker-compose exec webserver ls -la /etc/letsencrypt/live
Khi yêu cầu của bạn thành công, đầu ra của bạn sẽ hiển thị như sau:
Outputtotal 16
drwx------ 3 root root 4096 Dec 23 16:48 .
drwxr-xr-x 9 root root 4096 Dec 23 16:48 ..
-rw-r--r-- 1 root root 740 Dec 23 16:48 README
drwxr-xr-x 2 root root 4096 Dec 23 16:48 your_domain
Bây giờ bạn biết yêu cầu của mình sẽ thành công, bạn có thể chỉnh sửa định nghĩa dịch vụ certbot
để xóa cờ --staging
.
Mở tệp docker-compose.yml
:
- nano docker-compose.yml
Tìm phần của tệp có định nghĩa dịch vụ certbot
và thay thế cờ --staging
trong tùy chọn command
bằng cờ --force-renewal
. Điều này sẽ cho Certbot biết rằng bạn muốn yêu cầu chứng chỉ mới có cùng tên miền với chứng chỉ hiện có. Định nghĩa dịch vụ certbot
phải có các định nghĩa sau:
...
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- web-root:/var/www/html
depends_on:
- webserver
command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
...
Khi bạn chỉnh sửa xong, hãy lưu và thoát tệp. Bây giờ bạn có thể chạy docker-compose up
để tạo lại vùng chứa certbot
và các volumes liên quan của nó. Bằng cách bao gồm tùy chọn --no-deps
, bạn đang thông báo cho Compose rằng Compose có thể bỏ qua việc khởi động dịch vụ webserver
vì nó đã chạy:
- docker-compose up --force-recreate --no-deps certbot
Kết quả đầu ra sau đây cho biết yêu cầu chứng chỉ của bạn đã thành công:
OutputRecreating certbot ... done
Attaching to certbot
certbot | Account registered.
certbot | Renewing an existing certificate for your_domain and www.your_domain
certbot |
certbot | Successfully received certificate.
certbot | Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem
certbot | Key is saved at: /etc/letsencrypt/live/your_domain phd.com/privkey.pem
certbot | This certificate expires on 2022-11-03.
certbot | These files will be updated when the certificate renews.
certbot | NEXT STEPS:
certbot | - The certificate will need to be renewed before it expires. Cert bot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setu p for instructions.
certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log
certbot |
certbot | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot | If you like Certbot, please consider supporting our work by:
certbot | * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/do nate
certbot | * Donating to EFF: https://eff.org/donate-le
certbot | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot exited with code 0
Với chứng chỉ đã có, bạn có thể chuyển sang sửa đổi cấu hình Nginx của mình để bao gồm SSL.
Việc bật SSL trong cấu hình Nginx của bạn sẽ liên quan đến việc thêm chuyển hướng HTTP vào HTTPS và chỉ định chứng chỉ SSL cũng như các vị trí chính của bạn. Nó cũng sẽ liên quan đến việc chỉ định nhóm Diffie-Hellman mà bạn sẽ sử dụng cho Perfect Forward Secrecy.
Vì bạn sắp tạo lại dịch vụ webserver
để bao gồm những phần bổ sung này nên bạn có thể dừng dịch vụ đó ngay bây giờ:
- docker-compose stop webserver
Tiếp theo, tạo một thư mục trong thư mục dự án hiện tại của bạn cho khóa Diffie-Hellman:
- mkdir dhparam
Tạo khóa của bạn bằng lệnh openssl
:
- sudo openssl dhparam -out /home/sammy/node_project/dhparam/dhparam-2048.pem 2048
Sẽ mất một chút thời gian để tạo khóa.
Để thêm thông tin Diffie-Hellman và SSL có liên quan vào cấu hình Nginx của bạn, trước tiên hãy xóa tệp cấu hình Nginx bạn đã tạo trước đó:
- rm nginx-conf/nginx.conf
Mở phiên bản khác của tệp:
- nano nginx-conf/nginx.conf
Thêm mã sau vào tệp để chuyển hướng HTTP sang HTTPS và thêm thông tin xác thực, giao thức và tiêu đề bảo mật SSL. Hãy nhớ thay thế your_domain
bằng tên miền của riêng bạn:
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your_domain www.your_domain;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri @nodejs;
}
location @nodejs {
proxy_pass http://nodejs:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}
Khối máy chủ HTTP chỉ định webroot cho các yêu cầu gia hạn Certbot tới thư mục .well-known/acme-challenge
. Nó cũng bao gồm một lệnh viết lại hướng các yêu cầu HTTP đến thư mục gốc tới HTTPS.
Khối máy chủ HTTPS cho phép ssl
và http2
. Để đọc thêm về cách HTTP/2 lặp lại trên các giao thức HTTP và những lợi ích mà nó có thể mang lại cho hiệu suất trang web, vui lòng đọc phần giới thiệu về Cách thiết lập Nginx với hỗ trợ HTTP/2 trên Ubuntu 18.04. Khối này cũng bao gồm một loạt tùy chọn để đảm bảo rằng bạn đang sử dụng các giao thức và mật mã SSL cập nhật nhất cũng như tính năng ghim OSCP được bật. Việc ghim OSCP cho phép bạn đưa ra phản hồi theo thời gian từ cơ quan cấp chứng chỉ của bạn trong quá trình TLS handshake ban đầu, điều này có thể tăng tốc quá trình xác thực.
Khối này cũng chỉ định thông tin xác thực SSL và Diffie-Hellman cũng như các vị trí chính của bạn.
Cuối cùng, bạn đã di chuyển thông tin chuyển proxy sang khối này, bao gồm khối vị trí có lệnh try_files
, trỏ yêu cầu tới vùng chứa ứng dụng Node.js bí danh của bạn và khối vị trí cho bí danh đó, bao gồm các tiêu đề bảo mật sẽ cho phép bạn để nhận được xếp hạng A về những thứ như trang web thử nghiệm máy chủ SSL Labs và Security Headers. Các tiêu đề này bao gồm X-Frame-Options
, X-Content-Type-Options
, Referrer Policy
, Content-Security-Policy
, và X-XSS-Protection
. Tiêu đề HTTP Strict Transport Security
(HSTS) đã được nhận xét - chỉ bật tiêu đề này nếu bạn hiểu ý nghĩa và đã đánh giá chức năng "preload" của nó.
Sau khi chỉnh sửa xong, hãy lưu và đóng tệp.
Trước khi tạo lại dịch vụ webserver
, bạn cần thêm một số nội dung vào định nghĩa dịch vụ trong tệp docker-compose.yml
, bao gồm thông tin cổng có liên quan cho HTTPS và định nghĩa volume Diffie-Hellman.
Mở tập tin:
- nano docker-compose.yml
Trong định nghĩa dịch vụ webserver
, hãy thêm ánh xạ cổng dưới đây và volume có tên dhparam
:
...
webserver:
image: nginx:latest
container_name: webserver
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- web-root:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- dhparam:/etc/ssl/certs
depends_on:
- nodejs
networks:
- app-network
Tiếp theo, thêm volume dhparam
vào định nghĩa volumes
của bạn. Hãy nhớ thay thế các thư mục sammy
và node_project
để khớp với thư mục của bạn:
...
volumes:
...
webroot:
...
dhparam:
driver: local
driver_opts:
type: none
device: /home/sammy/node_project/dhparam/
o: bind
Tương tự như volume web-root
, volume dhparam
sẽ gắn khóa Diffie-Hellman được lưu trữ trên máy chủ vào vùng chứa webserver
.
Lưu và đóng tệp khi bạn chỉnh sửa xong.
Tạo lại dịch vụ webserver
:
- docker-compose up -d --force-recreate --no-deps webserver
Kiểm tra dịch vụ của bạn với docker-compose ps
:
- docker-compose ps
Đầu ra sau cho biết rằng các dịch vụ nodejs
và webserver
của bạn đang chạy:
Output Name Command State Ports
----------------------------------------------------------------------------------------------
certbot certbot certonly --webroot ... Exit 0
nodejs node app.js Up 8080/tcp
webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
Cuối cùng, bạn có thể truy cập miền của mình để đảm bảo rằng mọi thứ đều hoạt động như mong đợi. Điều hướng trình duyệt của bạn tới https://your_domain
, đảm bảo thay thế your_domain
bằng tên miền của riêng bạn:
Biểu tượng lock sẽ xuất hiện trong chỉ báo bảo mật của trình duyệt của bạn. Nếu muốn, bạn có thể điều hướng đến trang đích SSL Labs Server Test hoặc trang đích Security Headers server test. Các tùy chọn cấu hình được bao gồm sẽ giúp trang web của bạn được xếp hạng A trong SSL Labs Server Test. Để nhận được xếp hạng A trong Security Headers server test, bạn sẽ phải bỏ ghi chú tiêu đề Strict Transport Security (HSTS) trong tệp nginx-conf/nginx.conf
của mình:
…
location @nodejs {
proxy_pass http://nodejs:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
…
Một lần nữa, chỉ bật tùy chọn này nếu bạn hiểu ý nghĩa và đã đánh giá chức năng “preload” của nó.
Chứng chỉ Let’s Encrypt có hiệu lực trong 90 ngày. Bạn có thể thiết lập quy trình gia hạn tự động để đảm bảo rằng chúng không bị mất hiệu lực. Một cách để làm điều này là tạo một công việc bằng tiện ích lập lịch trình cron
. Bạn có thể lên lịch công việc cron
bằng cách sử dụng tập lệnh sẽ gia hạn chứng chỉ và tải lại cấu hình Nginx của bạn.
Mở tập lệnh có tên ssl_renew.sh
trong thư mục dự án của bạn:
- nano ssl_renew.sh
Thêm mã sau vào tập lệnh để gia hạn chứng chỉ và tải lại cấu hình máy chủ web của bạn:
[label ~/node_project/ssl_renew.sh
]
#!/bin/bash
COMPOSE="/usr/local/bin/docker-compose --ansi never"
DOCKER="/usr/bin/docker"
cd /home/sammy/node_project/
$COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af
Tập lệnh này trước tiên gán tệp nhị phân docker-compose
cho một biến có tên COMPOSE
và chỉ định tùy chọn --no-ansi
, tùy chọn này sẽ chạy các lệnh docker-compose
mà không có ký tự điều khiển ANSI. Sau đó nó thực hiện tương tự với docker
nhị phân. Cuối cùng, nó thay đổi thư mục ~/node_project
và chạy các lệnh docker-compose
sau:
docker-compose run
: Điều này sẽ khởi động vùng chứa certbot
và ghi đè command
được cung cấp trong định nghĩa dịch vụ certbot
. Thay vì sử dụng lệnh con certonly
, hãy sử dụng lệnh con renew
, lệnh này sẽ gia hạn các chứng chỉ sắp hết hạn. Cũng bao gồm tùy chọn --dry-run
để kiểm tra tập lệnh.docker-compose kill
: Điều này sẽ gửi tín hiệu SIGHUP
đến vùng chứa webserver
để tải lại cấu hình Nginx.Sau đó, nó chạy docker system prune
để loại bỏ tất cả các vùng chứa và hình ảnh không sử dụng.
Đóng tệp khi bạn chỉnh sửa xong, sau đó làm cho nó có thể thực thi được:
- chmod +x ssl_renew.sh
Tiếp theo, mở tệp crontab
root của bạn để chạy tập lệnh gia hạn theo một khoảng thời gian nhất định:
sudo crontab -e
Nếu đây là lần đầu tiên bạn chỉnh sửa tệp này, bạn sẽ được yêu cầu chọn một trình chỉnh sửa:
no crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano <---- easiest
3. /usr/bin/vim.basic
4. /usr/bin/vim.tiny
Choose 1-4 [2]:
...
Ở cuối tập tin, thêm dòng sau:
...
*/5 * * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1
Thao tác này sẽ đặt khoảng thời gian thực hiện công việc là 5 phút một lần, do đó bạn có thể kiểm tra xem yêu cầu gia hạn của mình có hoạt động như dự kiến hay không. Bạn cũng đã tạo một tệp nhật ký, cron.log
, để ghi lại kết quả đầu ra liên quan từ công việc.
Sau năm phút, hãy kiểm tra cron.log
để xác nhận xem yêu cầu gia hạn có thành công hay không:
- tail -f /var/log/cron.log
Sau một lúc, đầu ra sau đây báo hiệu việc gia hạn thành công:
Output- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/your_domain/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Killing webserver ... done
Output…
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/your_domain/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Killing webserver ...
Killing webserver ... done
Deleted Containers:
00cad94050985261e5b377de43e314b30ad0a6a724189753a9a23ec76488fd78
Total reclaimed space: 824.5kB
Thoát ra bằng cách nhập CTRL + C
trong thiết bị đầu cuối của bạn.
Bây giờ bạn có thể sửa đổi tệp crontab
để đặt khoảng thời gian hàng ngày. Ví dụ: để chạy tập lệnh hàng ngày vào buổi trưa, bạn có thể sửa đổi dòng cuối cùng của tệp như sau:
...
0 12 * * * /home/sammy/node_project/ssl_renew.sh >> /var/log/cron.log 2>&1
Bạn cũng có thể xóa tùy chọn --dry-run
khỏi tập lệnh ssl_renew.sh
của mình:
#!/bin/bash
COMPOSE="/usr/local/bin/docker-compose --no-ansi"
DOCKER="/usr/bin/docker"
cd /home/sammy/node_project/
$COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
$DOCKER system prune -af
Công việc cron
của bạn sẽ đảm bảo rằng chứng chỉ Let's Encrypt của bạn không bị mất hiệu lực khi gia hạn nếu chúng đủ điều kiện. Bạn cũng có thể thiết lập xoay vòng nhật ký bằng tiện ích Logrotate để xoay và nén các tệp nhật ký của mình.
Bạn đã sử dụng vùng chứa để thiết lập và chạy ứng dụng Node với proxy ngược Nginx. Bạn cũng đã bảo mật chứng chỉ SSL cho miền ứng dụng của mình và thiết lập công việc cron
để gia hạn các chứng chỉ này khi cần thiết.
Nếu bạn muốn tìm hiểu thêm về plugin Let's Encrypt, vui lòng xem lại bài viết của chúng tôi về cách sử dụng plugin Nginx hoặc plugin độc lập.
Bạn cũng có thể tìm hiểu thêm về Docker Compose bằng các tài nguyên sau: