Vì bài này ta triển khai trên server thật nên đương nhiên điều kiện cần có là các bạn có 1 VPS của riêng mình, nhớ là VPS chứ không phải Hosting nhé. Nên chọn Ubuntu nhé các bạn (Centos, Redhat cũng không sao) Thành lậpĐầu tiên các bạn clone mã nguồn của mình ở đây (nhánh FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
6). Bài này chúng ta chỉ quan tâm đến thư mục FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
7 nhédự án tổng quan - Về chức năng, dự án này vẫn giống với các dự án NodeJS ở các bài trước đó có. đăng nhập, đăng xuất, thêm sản phẩm, lưu phiên người dùng,
- Tất cả các container đều được chạy với người dùng không root
Tiếp theo các bạn copy thư mục FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
7 này ra 1 chỗ riêng biệt nào đó để lát nữa ta đẩy lên Repository nhéSau đó các bạn tạo 1 repository trên Gitlab với tên là FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
7 để tẹo nữa chạy ở local ngon nghẻ xong ta sẽ đẩy code lên repository, rồi lên server pull về và build image nhé.Chạy tại địa phươngNhư thường lệ, công việc đầu tiên ta cần làm là build Docker image và chạy thử ở local trước để đảm bảo mọi thứ vẫn ổn định trước khi ta up server nhé. Bởi vì tất cả các vùng chứa của ta đều chạy với non-root user nên trước khi chạy ta cần xác định UserID + Group ID của user ở môi trường gốc của ta là gì nhé (nếu các bạn không hiểu tại sao tạo lại thì làm thế nào At the root environment, you run command after id -u
----> 501
id -g
----> 20
Như các bạn thấy User ID ở môi trường gốc của mình là docker build -t learning-docker:deploy-node .
0 và Group ID là docker build -t learning-docker:deploy-node .
1Chú ý quan trọng. nếu UserID + Group ID của các bạn là docker build -t learning-docker:deploy-node .
2 thì ở Dockerfile bên dưới có chút khác, vì trùng với user docker build -t learning-docker:deploy-node .
3 trong container NodeJS ở bài trước mình đã nói là rất giỏi rồi nhé.Sau đó các bạn mở docker build -t learning-docker:deploy-node .
4 và cùng sửa lại phần user như sau nhéFROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
0Ở trên docker build -t learning-docker:deploy-node .
5 của mình là docker build -t learning-docker:deploy-node .
6 nhéSau đó ta tiến hành build image nhé docker build -t learning-docker:deploy-node .
BÙMMMM , Lỗi @@. : Triển khaiĐầu tiên các bạn nhớ SSH vào server nhé Điểm hay ho và cũng là điều tuyệt vời nhất khi làm việc với ứng dụng Docker đó là việc ít (hoặc thậm chí là không) bị ảnh hưởng bởi môi trường bên ngoài và 1 khi ta đã Dockerize thành công ở đó . Thứ ta cần chỉ là FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
45 và FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
46 (tất nhiên là ). Bắt đầu hủy nào Đầu tiên các bạn kiểm tra xem server đã có Docker chưa và Docker soạn chưa nhé FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
01Nếu chưa có các bạn cài đặt theo hướng dẫn tại đây(Docker) và tại đây(Docker soạn) nhé Sau đó các bạn chuyển sang 1 thư mục bất kỳ trước khi bắt đầu nhé, ở đây mình chọn FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
47FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
02Sau đó ta clone source code từ Gitlab về nhé FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
03Ghi chú. at on your your account Gitlab thay tên của các bạn vào nhé Nếu được hỏi username + pass thì các bạn nhập email + pass tài khoản Gitlab Cũng giống như ở local, trước khi chạy ta cần kiểm tra xem User ID và Groupd ID của user ở môi trường gốc của chúng ta là gì nhé FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
04Ở trên mình có docker build -t learning-docker:deploy-node .
5 là docker build -t learning-docker:deploy-node .
2 (yeah, lát nữa viết Dockerfile cho nhàn )Các bạn sửa lại Dockerfile với nội dung như sau nhé FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
05Lưu ý quan trọng. vì ở trên UID. GID của mình là 1000. 1000 nên mình dùng luôn user docker build -t learning-docker:deploy-node .
3, còn không thì các bạn lại làm như ở local vừa khít nhéTiếp theo ta cần cập nhật lại user cho MongoDB và Redis trong docker build -t learning-docker:deploy-node .
9 nữaFROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
06Ổn rồi đó ta tiến hành build image nhé docker build -t learning-docker:deploy-node .
Sau khi build xong thì ta run project lên thôi FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
8Chờ khoảng 1 phút để MongoDB khởi động hoàn toàn, ta mở trình duyệt tại địa chỉ FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
82 nhéAnd. BÙM
Cố gắng kiểm tra xem container đã chạy chưa nhé FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
09Ổn rồi mà nhỉ Vấn đề là với các VPS ta mua, thì thông thường ban đầu sẽ không có cổng nào được mở để lưu lượng truy cập từ thế giới bên ngoài đi vào, mà ta phải tự tay mở. Có 2 cách. 1 is ta used FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
83 (Firewall) as 1 number of tutorial has doing, but way this don't or if you buy VPS at theỒn nhà cung cấp lớn (Google, AWS, Azure, Digital Ocean,. ) thì họ cho phép ta có thể mở cổng trên giao diện web quản lý riêng. Mình thấy điều này tốt hơn, ta chỉ cần định cổng nào cần mở, việc còn lại thì nhà cung cấp cho họ lo, cũng đỡ lo cho các vấn đề bảo mật hơn. Sử dụng FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
83 không đọc kỹ hướng dẫn lúc FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
85 lên khéo léo lại bị chấm dứt và không được SSH lạiVí dụ như mình sử dụng Azure thì giao diện danh nghĩa như sau
Quá đơn giản khi triển khai ứng dụng Container với Docker phải không nào HTTPSTrỏ tên miền về máy chủKhi ta chạy dự án ở giai đoạn sản xuất thông thường ta sẽ sử dụng tên miền để trông chuyên nghiệp, có thương hiệu hơn mà còn có những lợi ích lớn như sau - Sử dụng tên miền lấy HTTPS rất dễ dàng
- Không được mở cổng vô tội khi số dự án trên máy chủ của ta tăng lên nhiều, khi đó mỗi dự án ta phải chạy ở các cổng khác nhau
- Use domain ta only to open duy nhất 2 cổng. 80 cho HTTP và 443 cho HTTPS, dù số lượng dự án có nhiều thế nào.
Ở đây mình không khuyến khích các bạn dùng Self-signed certificate để lấy HTTPS cho IP nhé, vì gần như chẳng bao giờ ta dùng cái đó ở production vì các trình duyệt hiện giờ đã không cho phép Self-Signed Certificate và sẽ hiển thị . Do đó, điều kiện cần có để lấy HTTPS ở bài này là các bạn phải có 1 tên miền (tên miền) nhé. Mình khuyến khích các bạn mua ở những nhà cung cấp lớn như Goddady, chọn 1 tên cùi để học tập (loanh quanh 100K là cùng )Sau khi các bạn có domain thì các bạn vào trang quản trị của domain đó, sửa lại địa chỉ IP của bản ghi FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
86 mà được tạo sẵn để trỏ về IP máy chủ của chúng ta nhé
Ghi chú. Ở trên các bạn thấy mình đang tạo 1 bản ghi FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
88 là FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
89 và con trỏ về FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
000 tức là con trỏ về cùng IP với bản ghi FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
86 để lát nữa ta có thể truy cập theo cả 2 kiểu FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
002 hoặc FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
003 nhé
Cách lấy HTTPSỞ nơi sản xuất, người ta thường sử dụng 1 webserver đứng trước ứng dụng của họ để đóng vai trò vừa là tầng bảo mật, cân bằng tải, bộ nhớ đệm hoặc proxy để nhận yêu cầu từ người dùng giúp tăng hiệu suất cho ứng dụng của họ. Và 1 trong những webserver mình thấy người ta dùng nhiều nhất bây giờ là Nginx. Ở bài này ta sẽ dùng nó nhé. Cùng với đó, để lấy chứng chỉ HTTPS miễn phí thì ta sử dụng Certbot nhé Từ đây ta có luồng xử lý như sau
Do that problems at here is. thế Nginx kia ta đặt ở môi trường bên ngoài hay môi trường bên trong Docker? Ô hay đang làm Docker, muốn giữ môi trường bên ngoài "nguyên trinh" mà, tất nhiên là đặt Nginx chạy trong container luôn chứ không nên chỉ định chi tiết thiết kế sẽ như sau Cùng với đó mình hay dùng Wildcard Certificate (dạng FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
004) thì hơi khó lấy hơnDo vậy sau 1 thời gian làm mình đã chuyển qua cách khác, đó là đưa Nginx + Certbot ra môi trường bên ngoài, làm nhiệm vụ chuyên nghiệp như 1 tầng bảo mật chứ không chạy trong container nữa. Design new nom will like after vui sướng Mục đích chính nhất khi mình lựa chọn cách tiếp cận này là vì ta có thể lấy HTTPS rất dễ dàng, dù chúng có chạy trong Docker hay được triển khai theo kiểu truyền thống
Các bạn hoàn toàn có thể chạy cả Nginx + Certbot trong container cũng được nhé, những nhược điểm bên trên chỉ có thể với mình, với các bạn lại không sao. Các bạn thử xem và comment cho mình nhé
Bắt đầu hủy nào Đầu tiên ở môi trường gốc khi bạn cài đặt Nginx docker build -t learning-docker:deploy-node .
1Sau khi cài đặt xong các bạn kiểm tra xem Nginx có chạy chưa nhé docker build -t learning-docker:deploy-node .
2Sau đó ta cần mở port 80 cho HTTP và 443 HTTPS cho traffic bên ngoài truy cập vào được nhé. Chú ý rằng dù ta chỉ mong người dùng truy cập bằng HTTPS nhưng cổng 80 vẫn cần được mở vì khi người dùng gõ trực tiếp vào trình duyệt FROM node:12.18-alpine
WORKDIR /app
RUN npm install -g pm2
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production --silent
COPY . .
RUN adduser -D -u 501 appuser -G dialout
RUN chown -R appuser:dialout /app
USER appuser
CMD ["pm2-runtime", "ecosystem.config.js", "--env", "production"]
005 (không có S) mà cổng 80 ta không mở được là người dùng sẽ không truy cập được đâu. . And to open port, you re use 1 in 2 way. qua trang quản trị nhà cung cấp VPS (nên dùng) hoặc dùng UFW. If used UFW, you are doing as afterdocker build -t learning-docker:deploy-node .
3Đến đây các bạn quay lại trình duyệt truy cập vào địa chỉ domain của các bạn (cổng 80) thấy như sau là oke nhé . Thứ nữa là với những dự án cần cài nhiều thứ, như dự án chat realtime kia của mình chẳng hạn, việc nhớ cài tất cả mọi thứ nhiều lúc là 1 điều khó khăn, đặc biệt những hôm nào cãi nhau với người yêu Ngoài ra còn N + 1 nỗi sợ nữa Khi các bạn xem lại phần triển khai ở bài viết này, ta thấy rằng rất nhanh đơn giản và tiện lợi, thích thì cập nhật phiên bản bằng tên ảnh mới, thích thì xóa, thay mới, vô cùng dễ dàng. Điều mà nếu ta triển khai theo kiểu truyền thống khó mà có được. Và đó cũng là điều tuyệt vời nhất mình muốn truyền tải với các bạn trong bộ truyện này Đóng máyQua bài này ta đã hoàn thành triển khai hoàn chỉnh 1 ứng dụng NodeJS cùng với đó là lấy HTTPS tầm gửi cho ứng dụng của chúng ta |