Docker Server & VPS Tutorial

Cách xây dựng ứng dụng Node.js với Docker trên Ubuntu 20.04

Nền tảng Docker cho phép các nhà phát triển đóng gói và chạy các ứng dụng dưới dạng các thùng chứa. Container là một quá trình tách biệt chạy trên một hệ điều hành dùng chung, cung cấp một sự thay thế trọng lượng nhẹ hơn cho các máy ảo. Mặc dù các container không phải là mới, nhưng chúng mang lại lợi ích – bao gồm cách ly quy trình và tiêu chuẩn hóa môi trường – đang ngày càng trở nên quan trọng khi nhiều nhà phát triển sử dụng kiến ​​trúc ứng dụng phân tán.

Khi xây dựng và nhân rộng một ứng dụng bằng Docker, điểm bắt đầu thường là tạo một hình ảnh cho ứng dụng của bạn, sau đó bạn có thể chạy trong một thùng chứa. Hình ảnh bao gồm mã ứng dụng, thư viện, tệp cấu hình, biến môi trường và thời gian chạy của bạn. Sử dụng một hình ảnh đảm bảo rằng môi trường trong thùng chứa của bạn được chuẩn hóa và chỉ chứa những gì cần thiết để xây dựng và chạy ứng dụng của bạn.

Trong hướng dẫn này, bạn sẽ tạo một hình ảnh ứng dụng cho một trang web tĩnh sử dụng khung Express và Bootstrap. Sau đó, bạn sẽ xây dựng một thùng chứa bằng hình ảnh đó và đẩy nó đến Docker Hub để sử dụng trong tương lai. Cuối cùng, bạn sẽ kéo hình ảnh được lưu trữ từ kho lưu trữ Docker Hub của bạn và xây dựng một thùng chứa khác, trình bày cách bạn có thể tạo lại và chia tỷ lệ ứng dụng của mình.

Bước 1 – Cài đặt phụ thuộc ứng dụng của bạn

Để tạo hình ảnh của bạn, trước tiên bạn sẽ cần tạo các tệp ứng dụng của mình, sau đó bạn có thể sao chép vào thùng chứa của mình. Những tệp này sẽ bao gồm ứng dụng của bạn, nội dung tĩnh, mã và phụ thuộc.

Đầu tiên, tạo một thư mục cho dự án của bạn trong thư mục nhà người dùng không phải root của bạn. Chúng tôi sẽ gọi node_project  của chúng tôi, nhưng bạn nên thoải mái thay thế cái này bằng cái khác:

Điều hướng đến thư mục này:

Đây sẽ là thư mục gốc của dự án.

Tiếp theo, tạo một tệp pack.json với các phụ thuộc dự án của bạn và thông tin nhận dạng khác. Mở tệp bằng nano hoặc trình chỉnh sửa yêu thích của bạn:

Thêm thông tin sau về dự án, bao gồm tên, tác giả, giấy phép, điểm vào và phụ thuộc của dự án. Hãy chắc chắn để thay thế thông tin tác giả bằng tên của bạn và chi tiết liên lạc:

Tập tin này bao gồm tên dự án, tác giả và giấy phép mà nó đang được chia sẻ. Npm khuyên bạn nên đặt tên dự án của bạn ngắn gọn và mô tả và tránh trùng lặp trong sổ đăng ký npm. Chúng tôi đã liệt kê giấy phép MIT trong lĩnh vực giấy phép, cho phép sử dụng miễn phí và phân phối mã ứng dụng.

Ngoài ra, tệp chỉ định:

  • "main" : Điểm vào cho ứng dụng, app.js . Bạn sẽ tạo tập tin này tiếp theo.
  • "dependencies" : Các phụ thuộc của dự án – trong trường hợp này, Express 4.16.4 trở lên.

Mặc dù tệp này không liệt kê một kho lưu trữ, bạn có thể thêm một kho lưu trữ bằng cách làm theo các hướng dẫn này về cách thêm một kho lưu trữ vào tệp pack.json của bạn. Đây là một bổ sung tốt nếu bạn đang phiên bản ứng dụng của bạn.

Lưu và đóng tệp khi bạn đã hoàn tất thay đổi.

Để cài đặt các phụ thuộc dự án của bạn, hãy chạy lệnh sau:

Điều này sẽ cài đặt các gói bạn đã liệt kê trong tệp pack.json  trong thư mục dự án của bạn.

Bây giờ chúng ta có thể chuyển sang xây dựng các tệp ứng dụng.

Bước 2 – Tạo tập tin ứng dụng

Chúng tôi sẽ tạo một trang web cung cấp cho người dùng thông tin về cá mập. Ứng dụng của chúng tôi sẽ có một điểm truy cập chính, app.js  và views  khung nhìn sẽ bao gồm các tài sản tĩnh của dự án. Trang đích, index.html , sẽ cung cấp cho người dùng một số thông tin sơ bộ và liên kết đến một trang có thông tin cá mập chi tiết hơn, sharks.html . Trong thư mục views , chúng tôi sẽ tạo cả trang đích và sharks.html .

Đầu tiên, mở app.js  trong thư mục dự án chính để xác định các tuyến của dự án:

Phần đầu tiên của tệp sẽ tạo các ứng dụng Express và các đối tượng Bộ định tuyến và xác định thư mục cơ sở và cổng là các hằng số:

Require  tải mô-đun express , sau đó chúng ta sử dụng để tạo các đối tượng app  và router . Đối tượng router sẽ thực hiện chức năng định tuyến của ứng dụng và khi chúng tôi xác định các tuyến phương thức HTTP, chúng tôi sẽ thêm chúng vào đối tượng này để xác định cách ứng dụng của chúng tôi sẽ xử lý các yêu cầu.

Phần này của tệp cũng đặt một vài hằng số, path  và port :

  • path : Xác định thư mục cơ sở, đó sẽ là views  thư mục con trong thư mục dự án hiện tại.
  • port  : Yêu cầu ứng dụng lắng nghe và liên kết với cổng 8080 .
    Tiếp theo, đặt các tuyến cho ứng dụng bằng cách sử dụng đối tượng router :

Hàm router.use  tải một hàm phần mềm trung gian sẽ ghi nhật ký các yêu cầu của bộ định tuyến và chuyển chúng vào các tuyến ứng dụng. Chúng được xác định trong các hàm tiếp theo, xác định rằng yêu cầu GET cho URL dự án cơ sở sẽ trả về trang index.html , trong khi yêu cầu GET cho tuyến / sharks  sẽ trả về sharks.html .

Cuối cùng, gắn phần mềm trung gian của router  và ứng dụng Tài sản tĩnh tĩnh và yêu cầu ứng dụng lắng nghe trên cổng 8080 :

Tệp app.js  đã hoàn thành sẽ trông như thế này:

Lưu và đóng tệp khi bạn hoàn thành.

Tiếp theo, hãy để thêm một số nội dung tĩnh vào ứng dụng. Bắt đầu bằng cách tạo thư mục views :

Mở tệp trang đích, index.html :

Thêm mã sau vào tệp, tệp này sẽ nhập Bootstrap và tạo thành phần jumbotron với liên kết đến trang thông tin sharks.html  chi tiết hơn:

Thanh điều hướng cấp cao nhất ở đây cho phép người dùng chuyển đổi giữa các trang HomeSharks. Trong thành phần con navbar-nav , chúng tôi đang sử dụng lớp Bootstrap active , để chỉ ra trang hiện tại cho người dùng. Chúng tôi cũng đã chỉ định các tuyến đường đến các trang tĩnh của mình, khớp với các tuyến đường chúng tôi đã xác định trong app.js :

Ngoài ra, chúng tôi đã tạo một liên kết đến trang thông tin cá mập trong nút jumbotron của chúng tôi:

Ngoài ra còn có một liên kết đến một biểu định kiểu tùy chỉnh trong tiêu đề:

Chúng tôi sẽ tạo biểu định kiểu này ở cuối bước này.

Lưu và đóng tệp khi bạn hoàn thành.

Với trang đích của ứng dụng, chúng ta có thể tạo trang thông tin cá mập của mình, sharks.html , sẽ cung cấp cho người dùng quan tâm nhiều thông tin hơn về cá mập.

Mở tập tin:

Thêm mã sau đây, nhập Bootstrap và biểu định kiểu tùy chỉnh và cung cấp cho người dùng thông tin chi tiết về một số cá mập nhất định:

Lưu ý rằng trong tệp này, chúng tôi lại sử dụng lớp active  để chỉ ra trang hiện tại.

Lưu và đóng tệp khi bạn hoàn thành.

Cuối cùng, tạo biểu định kiểu CSS tùy chỉnh mà bạn đã liên kết với trong index.html  và sharks.html  bằng cách trước tiên tạo thư mục css  trong thư mục views :

Mở biểu định kiểu:

Thêm mã sau đây, mã này sẽ đặt màu và phông chữ mong muốn cho các trang của chúng tôi:

Ngoài cài đặt phông chữ và màu sắc, tệp này cũng giới hạn kích thước của hình ảnh bằng cách chỉ định max-width  80%. Điều này sẽ ngăn họ chiếm nhiều phòng hơn chúng ta muốn trên trang.

Lưu và đóng tệp khi bạn hoàn thành.

Với các tệp ứng dụng tại chỗ và các phụ thuộc dự án được cài đặt, bạn đã sẵn sàng để khởi động ứng dụng.

Nếu bạn đã làm theo hướng dẫn thiết lập máy chủ ban đầu trong các điều kiện tiên quyết, bạn sẽ có một tường lửa hoạt động chỉ cho phép lưu lượng SSH. Để cho phép lưu lượng truy cập vào cổng 8080 :

Để khởi động ứng dụng, hãy chắc chắn rằng bạn đang ở trong thư mục gốc của dự án của bạn:

Bắt đầu ứng dụng với node app.js :

Điều hướng trình duyệt của bạn đến http://your_server_ip:8080 . Bạn sẽ tải trang đích sau:

 

Nhấp vào nút Get Shark Info. Trang thông tin sau sẽ tải:

 

Bây giờ bạn có một ứng dụng và chạy. Khi bạn đã sẵn sàng, thoát khỏi máy chủ bằng cách nhập CTRL + C . Bây giờ chúng ta có thể chuyển sang tạo Dockerfile cho phép chúng ta tạo lại và mở rộng ứng dụng này theo ý muốn.

Bước 3 – Viết Dockerfile

Dockerfile của bạn chỉ định những gì sẽ được bao gồm trong vùng chứa ứng dụng của bạn khi nó được thực thi. Sử dụng Dockerfile cho phép bạn xác định môi trường vùng chứa của mình và tránh sự khác biệt với các phiên bản phụ thuộc hoặc thời gian chạy.

Theo các hướng dẫn về xây dựng các thùng chứa được tối ưu hóa, chúng tôi sẽ làm cho hình ảnh của mình hiệu quả nhất có thể bằng cách giảm thiểu số lượng lớp hình ảnh và hạn chế chức năng hình ảnh trong một mục đích duy nhất – tái tạo các tệp ứng dụng và nội dung tĩnh của chúng tôi.

Trong thư mục gốc của dự án, hãy tạo Dockerfile:

Hình ảnh Docker được tạo ra bằng cách sử dụng một loạt các hình ảnh xếp chồng lên nhau. Bước đầu tiên của chúng tôi sẽ là thêm hình ảnh cơ sở cho ứng dụng của chúng tôi sẽ tạo thành điểm bắt đầu của quá trình xây dựng ứng dụng.

Hãy để sử dụng hình ảnh node 10-alpine , vì tại thời điểm viết bài này, đây là phiên bản LTS được đề xuất của Node.js. Hình ảnh alpine  có nguồn gốc từ dự án Alpine Linux và sẽ giúp chúng tôi giữ kích thước hình ảnh của chúng tôi xuống. Để biết thêm thông tin về việc hình ảnh alpine  có phải là lựa chọn phù hợp cho dự án của bạn hay không, vui lòng xem lại toàn bộ cuộc thảo luận trong phần Biến thể hình ảnh của trang hình ảnh Docker Hub Node.

Thêm hướng dẫn FROM  sau để thiết lập hình ảnh cơ sở của ứng dụng:

Hình ảnh này bao gồm Node.js và npm. Mỗi Dockerfile phải bắt đầu bằng một lệnh FROM .

Theo mặc định, hình ảnh Docker Node bao gồm người dùng node không phải root mà bạn có thể sử dụng để tránh chạy bộ chứa ứng dụng của mình dưới dạng root. Đó là một thực tiễn bảo mật được khuyến nghị để tránh chạy các container như root và để hạn chế các khả năng trong container chỉ với những yêu cầu để chạy các quy trình của nó. Do đó, chúng tôi sẽ sử dụng thư mục nhà của người dùng node làm thư mục làm việc cho ứng dụng của chúng tôi và đặt chúng làm người dùng của chúng tôi trong vùng chứa. Để biết thêm thông tin về các thực tiễn tốt nhất khi làm việc với hình ảnh Docker Node, hãy xem hướng dẫn thực hành tốt nhất này.

Để tinh chỉnh các quyền trên mã ứng dụng của chúng tôi trong vùng chứa, hãy để LÊ tạo thư mục con node_modules  trong / home / node cùng với danh mục app . Tạo các thư mục này sẽ đảm bảo rằng chúng có các quyền mà chúng ta muốn, điều này sẽ rất quan trọng khi chúng ta tạo các mô-đun nút cục bộ trong vùng chứa với npm install . Ngoài việc tạo các thư mục này, chúng tôi sẽ đặt quyền sở hữu chúng cho người dùng node của chúng tôi:

Để biết thêm thông tin về tiện ích hợp nhất các hướng dẫn RUN , hãy đọc qua cuộc thảo luận này về cách quản lý các lớp container.

Tiếp theo, đặt thư mục làm việc của ứng dụng thành / home / node / app :

Nếu một bộ WORKDIR  không được cài đặt, Docker sẽ tạo một cái theo mặc định, do đó, đó là một ý tưởng tốt để đặt nó một cách rõ ràng.

Tiếp theo, sao chép các tệp package.json  và package-lock.json  (đối với npm 5+):

Thêm hướng dẫn COPY  này trước khi chạy npm install  hoặc sao chép mã ứng dụng cho phép chúng tôi tận dụng cơ chế lưu trữ bộ đệm Docker. Ở mỗi giai đoạn trong quá trình xây dựng, Docker sẽ kiểm tra xem nó có một lớp được lưu trong bộ đệm cho hướng dẫn cụ thể đó không. Nếu chúng ta thay đổi package.json , lớp này sẽ được xây dựng lại, nhưng nếu chúng ta không có giá trị, hướng dẫn này sẽ cho phép Docker sử dụng lớp hình ảnh hiện có và bỏ qua việc cài đặt lại các mô-đun nút của chúng ta.

Để đảm bảo rằng tất cả các tệp ứng dụng được sở hữu bởi người dùng node không gốc, bao gồm nội dung của thư mục node_modules , hãy chuyển người dùng sang node trước khi chạy npm install :

Sau khi sao chép phụ thuộc dự án và chuyển đổi người dùng của chúng tôi, chúng tôi có thể chạy npm install :

Tiếp theo, sao chép mã ứng dụng của bạn với các quyền thích hợp vào thư mục ứng dụng trên vùng chứa:

Điều này sẽ đảm bảo rằng các tệp ứng dụng được sở hữu bởi người dùng node không phải root.

Cuối cùng, hiển thị cổng 8080  trên container và khởi động ứng dụng:

EXPOSE  không xuất bản cổng, mà thay vào đó hoạt động như một cách ghi lại các cổng nào trên container sẽ được xuất bản trong thời gian chạy. CMD  chạy lệnh để khởi động ứng dụng – trong trường hợp này là node app.js . Lưu ý rằng chỉ nên có một lệnh CMD trong mỗi Dockerfile. Nếu bạn bao gồm nhiều hơn một, chỉ cuối cùng sẽ có hiệu lực.

Có rất nhiều điều bạn có thể làm với Dockerfile. Để biết danh sách đầy đủ các hướng dẫn, vui lòng tham khảo tài liệu tham khảo Dockerf Dockerfile.

Dockerfile hoàn chỉnh trông như thế này:

Lưu và đóng tệp khi bạn chỉnh sửa xong.

Trước khi xây dựng hình ảnh ứng dụng, hãy để thêm một tệp .dockerignore . Hoạt động theo cách tương tự với tệp .gitignore , .dockerignore  chỉ định tệp và thư mục nào trong thư mục dự án của bạn không nên được sao chép sang vùng chứa của bạn.

Mở tệp .dockerignore :

Trong tệp, thêm các mô-đun nút cục bộ, nhật ký npm, Dockerfile và tệp .dockerignore :

Nếu bạn đang làm việc với Git thì bạn cũng sẽ muốn thêm thư mục .git và tệp .gitignore  của mình.

Lưu và đóng tệp khi bạn hoàn thành.

Bây giờ bạn đã sẵn sàng để xây dựng hình ảnh ứng dụng bằng lệnh docker build . Sử dụng cờ -t với  docker build  sẽ cho phép bạn gắn thẻ hình ảnh với một tên dễ nhớ. Bởi vì chúng tôi sẽ đẩy hình ảnh lên Docker Hub, hãy cho phép đưa tên người dùng Docker Hub của chúng tôi vào thẻ. Chúng tôi sẽ gắn thẻ hình ảnh dưới dạng nodejs-image-demo, nhưng vui lòng thay thế hình ảnh này bằng tên bạn chọn. Hãy nhớ thay thế your_dockerhub_username bằng tên người dùng Docker Hub của riêng bạn:

Các .  xác định rằng bối cảnh xây dựng là thư mục hiện tại.

Sẽ mất một hoặc hai phút để xây dựng hình ảnh. Khi nó hoàn thành, kiểm tra hình ảnh của bạn:

sudo docker images

Bạn sẽ nhận được đầu ra sau:

Bây giờ có thể tạo một thùng chứa với hình ảnh này bằng cách sử dụng docker run . Chúng tôi sẽ bao gồm ba cờ với lệnh này:

  • -p : Điều này xuất bản cổng trên container và ánh xạ nó tới một cổng trên máy chủ của chúng tôi. Chúng tôi sẽ sử dụng cổng 80 trên máy chủ, nhưng bạn nên thoải mái sửa đổi điều này khi cần thiết 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ề ràng buộc cổng.
  • -d : Điều này chạy container trong nền.
  • --name : Điều này cho phép chúng tôi đặt cho container một cái tên dễ nhớ.

Chạy lệnh sau để xây dựng thùng chứa:

Khi container của bạn hoạt động, bạn có thể kiểm tra danh sách các container đang chạy của mình với docker ps :

Bạn sẽ nhận được đầu ra sau:

Khi container của bạn đang chạy, giờ đây bạn có thể truy cập ứng dụng của mình bằng cách điều hướng trình duyệt đến IP máy chủ của bạn mà không cần cổng:

Trang đích ứng dụng của bạn sẽ tải lại một lần nữa.

 

Bây giờ bạn đã tạo một hình ảnh cho ứng dụng của mình, bạn có thể đẩy nó lên Docker Hub để sử dụng trong tương lai.

Bước 4 – Sử dụng Kho lưu trữ để làm việc với hình ảnh

Bằng cách đẩy hình ảnh ứng dụng của bạn đến một sổ đăng ký như Docker Hub, bạn làm cho nó có sẵn để sử dụng tiếp theo khi bạn xây dựng và chia tỷ lệ các thùng chứa của mình. Chúng tôi sẽ trình bày cách thức hoạt động của nó bằng cách đẩy hình ảnh ứng dụng vào kho lưu trữ và sau đó sử dụng hình ảnh để tạo lại vùng chứa của chúng tôi.

Bước đầu tiên để đẩy hình ảnh là đăng nhập vào tài khoản Docker Hub mà bạn đã tạo trong các điều kiện tiên quyết:

Khi được nhắc, hãy nhập mật khẩu tài khoản Docker Hub của bạn. Đăng nhập theo cách này sẽ tạo tệp ~ / .docker / config.json  trong thư mục nhà người dùng của bạn với thông tin đăng nhập Docker Hub của bạn.

Bây giờ bạn có thể đẩy hình ảnh ứng dụng lên Docker Hub bằng cách sử dụng thẻ bạn đã tạo trước đó, your_dockerhub_username / nodejs-image-demo:

Hãy để thử nghiệm tiện ích của sổ đăng ký hình ảnh bằng cách phá hủy vùng chứa ứng dụng và hình ảnh hiện tại của chúng tôi và xây dựng lại chúng bằng hình ảnh trong kho lưu trữ của chúng tôi.

Đầu tiên, liệt kê các container đang chạy của bạn:

Bạn sẽ nhận được đầu ra sau:

Sử dụng ID CONTAINER  được liệt kê trong đầu ra của bạn, dừng bộ chứa ứng dụng đang chạy. Đảm bảo thay thế ID được tô sáng bên dưới bằng ID CONTAINER  của riêng bạn:

Liệt kê tất cả các hình ảnh của bạn với cờ -a :

Bạn sẽ nhận được đầu ra sau với tên hình ảnh của bạn, your_dockerhub_username / nodejs-image-demo, cùng với hình ảnh node  và các hình ảnh khác từ bản dựng của bạn:

Xóa bộ chứa đã dừng và tất cả các hình ảnh, bao gồm cả hình ảnh không sử dụng hoặc treo lủng lẳng, bằng lệnh sau:

Nhập y  khi được nhắc trong đầu ra để xác nhận rằng bạn muốn xóa vùng chứa và hình ảnh đã dừng. Hãy lưu ý rằng điều này cũng sẽ xóa bộ nhớ cache xây dựng của bạn.

Bây giờ bạn đã loại bỏ cả container đang chạy hình ảnh ứng dụng của bạn và chính hình ảnh đó. Để biết thêm thông tin về việc loại bỏ các thùng chứa, hình ảnh và khối lượng của Docker, vui lòng xem lại Cách xóa hình ảnh, bộ chứa và khối của Docker.

Với tất cả hình ảnh và vùng chứa của bạn đã bị xóa, giờ đây bạn có thể kéo hình ảnh ứng dụng từ Docker Hub:

Liệt kê hình ảnh của bạn một lần nữa:

Đầu ra của bạn sẽ có hình ảnh ứng dụng của bạn:

Bây giờ bạn có thể xây dựng lại container của mình bằng lệnh từ Bước 3:

Liệt kê các container đang chạy của bạn:

Truy cập http: // your_server_ip  một lần nữa để xem ứng dụng đang chạy của bạn.

Phần kết luận:

Trong hướng dẫn này, bạn đã tạo một ứng dụng web tĩnh với Express và Bootstrap, cũng như hình ảnh Docker cho ứng dụng này. Bạn đã sử dụng hình ảnh này để tạo một thùng chứa và đẩy hình ảnh lên Docker Hub. Từ đó, bạn có thể hủy hình ảnh và vùng chứa của mình và tạo lại chúng bằng kho lưu trữ Docker Hub.

Nếu bạn muốn tìm hiểu thêm về cách làm việc với các công cụ như Docker Compose và Docker Machine để tạo các thiết lập đa container, bạn có thể xem các hướng dẫn sau:

  • Cách cài đặt Docker Soạn trên Ubuntu.
  • Cách cung cấp và quản lý máy chủ Docker từ xa với máy Docker trên Ubuntu.

Để biết các mẹo chung về làm việc với dữ liệu container, hãy xem:

  • Cách chia sẻ dữ liệu giữa các Docker Container.
  • Cách chia sẻ dữ liệu giữa Docker Container và Host.

Nếu bạn quan tâm đến các chủ đề liên quan đến Docker khác, vui lòng tìm thư viện hướng dẫn Docker hoàn chỉnh của chúng tôi.