Thứ sáu, 22/12/2017 | 00:00 GMT+7

Loạt hội thảo trên web: Xây dựng các ứng dụng chứa đựng


Chuỗi hội thảo trên web

Bài viết này bổ sung chuỗi hội thảo trên web về triển khai và quản lý dung lượng công việc được chứa trong cloud . Loạt bài này bao gồm các yếu tố cơ bản của containers , bao gồm quản lý vòng đời của containers , triển khai ứng dụng đa containers , mở rộng dung lượng công việc và hiểu Kubernetes, cùng với nêu bật các phương pháp hay nhất để chạy các ứng dụng trạng thái.

Hướng dẫn này bao gồm các khái niệm và lệnh được đề cập trong phần thứ hai của loạt bài, Xây dựng các ứng dụng được chứa trong thùng.

Trong hướng dẫn cuối cùng, Cách cài đặt và cấu hình Docker , ta đã khám phá một phương pháp để chuyển đổi vùng chứa Docker thành Docker image . Mặc dù phương pháp ta đã sử dụng có hiệu quả nhưng nó không phải lúc nào cũng là cách tối ưu để xây dựng hình ảnh.

Trong nhiều trường hợp, bạn cần đưa mã hiện có vào containers images và bạn cần có một cơ chế nhất quán, có thể lặp lại để tạo Docker image đồng bộ với version mới nhất của cơ sở mã của bạn.

Dockerfile giải quyết các yêu cầu này bằng cách cung cấp một cách khai báo và nhất quán để xây dựng Docker image .

Ngoài ra, đôi khi bạn cần chứa toàn bộ ứng dụng bao gồm nhiều containers không đồng nhất được triển khai và quản lý cùng nhau.

Docker Compose , giống như Dockerfile, có cách tiếp cận khai báo để cung cấp cho bạn phương pháp xác định toàn bộ ngăn xếp công nghệ, bao gồm các yêu cầu về mạng và lưu trữ. Điều này không chỉ giúp dễ dàng xây dựng các ứng dụng được container hơn mà còn giúp dễ dàng quản lý và mở rộng quy mô chúng.

Trong hướng dẫn này, bạn sẽ sử dụng một ứng dụng web mẫu dựa trên Node.jsMongoDB để tạo Docker image từ Dockerfile, bạn sẽ tạo một mạng tùy chỉnh cho phép các containers Docker của bạn giao tiếp và bạn sẽ sử dụng Docker Compose để chạy và quy mô một ứng dụng được đóng gói.

Yêu cầu

Để làm theo hướng dẫn này, bạn cần :

Bước 1 - Xây dựng hình ảnh bằng Dockerfile

Bắt đầu bằng cách thay đổi folder chính của bạn, sau đó sử dụng Git để sao chép ứng dụng web mẫu của hướng dẫn này từ kho lưu trữ chính thức của nó trên GitHub .

  • cd ~
  • git clone https://github.com/janakiramm/todo-app.git

Thao tác này sẽ sao chép ứng dụng mẫu vào một folder mới có tên là todo-app .

Chuyển sang todo-app và sử dụng ls để xem nội dung của folder .

  • cd todo-app
  • ls

Thư mục mới chứa hai folder con và hai file :

  • app - folder lưu trữ mã nguồn của ứng dụng mẫu
  • compose - folder lưu trữ file cấu hình Docker Compose
  • Dockerfile - một file chứa hướng dẫn để xây dựng Docker image
  • README.md - file chứa tóm tắt một câu của ứng dụng mẫu

Chạy cat Dockerfile cho ta thấy những điều sau:

~ / todo-app / Dockerfile
FROM node:slim LABEL maintainer = "jani@janakiram.com" RUN mkdir -p /usr/src/app WORKDIR /usr/src/app COPY ./app/ ./ RUN npm install CMD ["node", "app.js"] 

Hãy xem nội dung của file này chi tiết hơn:

  • FROM cho biết hình ảnh cơ sở mà bạn đang xây dựng hình ảnh tùy chỉnh từ đó. Trong ví dụ này, hình ảnh dựa trên node:slim , một hình ảnh Node.js công khai chỉ chứa các gói tối thiểu cần thiết để chạy node .
  • LABEL là một cặp giá trị khóa thường được sử dụng để thêm thông tin mô tả. Trong trường hợp này, nó chứa địa chỉ email của người bảo trì.
  • RUN thực hiện các lệnh trong containers . Điều này bao gồm các việc như tạo folder và khởi tạo containers bằng cách chạy các lệnh Linux cơ bản. Lệnh RUN đầu tiên trong file này được sử dụng để tạo folder /usr/src/app chứa mã nguồn.
  • WORKDIR xác định folder nơi tất cả các lệnh được thực thi. Nó thường là folder nơi mã được sao chép.
  • COPY sao chép các file từ server vào containers images . Trong trường hợp này, bạn đang sao chép toàn bộ folder app vào hình ảnh.
  • Lệnh RUN thứ hai thực hiện npm install để cài đặt các phụ thuộc của ứng dụng như được định nghĩa trong package.json .
  • CMD chạy quá trình sẽ giữ cho containers hoạt động. Trong ví dụ này, bạn sẽ thực thi node với tham số app.js

Bây giờ là lúc xây dựng hình ảnh từ Dockerfile . Sử dụng chuyển đổi -t để gắn thẻ hình ảnh bằng tên user đăng ký, tên hình ảnh và thẻ tùy chọn.

  • docker build -t sammy/todo-web .

Đầu ra xác nhận hình ảnh được Successfully built và được gắn thẻ thích hợp.

Output from docker build -t
Sending build context to Docker daemon 8.238MB Step 1/7 : FROM node:slim ---> 286b1e0e7d3f Step 2/7 : LABEL maintainer = "jani@janakiram.com" ---> Using cache ---> ab0e049cf6f8 Step 3/7 : RUN mkdir -p /usr/src/app ---> Using cache ---> 897176832f4d Step 4/7 : WORKDIR /usr/src/app ---> Using cache ---> 3670f0147bed Step 5/7 : COPY ./app/ ./ ---> Using cache ---> e28c7c1be1a0 Step 6/7 : RUN npm install ---> Using cache ---> 7ce5b1d0aa65 Step 7/7 : CMD node app.js ---> Using cache ---> 2cef2238de24 Successfully built 2cef2238de24 Successfully tagged sammy/todo-web:latest

Ta có thể xác minh hình ảnh được tạo bằng cách chạy lệnh docker images .

  • docker images

Tại đây, ta có thể thấy kích thước của hình ảnh cùng với thời gian đã trôi qua kể từ khi nó được tạo.

Output from docker images
REPOSITORY TAG IMAGE ID CREATED SIZE sammy/todo-web latest 81f5f605d1ca 9 minutes ago 236MB

Vì ta cũng cần một containers MongoDB để chạy ứng dụng web mẫu, hãy đưa nó vào máy của ta .

  • docker pull mongo:latest

Đầu ra báo cáo chính xác hình ảnh nào được kéo cùng với trạng thái download .

Output from docker pull
latest: Pulling from library/mongo Digest: sha256:18b239b996e0d10f4ce2b0f64db6f410c17ad337e2cecb6210a3dcf2f732ed82 Status: Downloaded newer image for mongo:latest

Bây giờ ta có mọi thứ ta cần để chạy ứng dụng mẫu, vì vậy hãy tạo một mạng tùy chỉnh cho phép các containers của ta giao tiếp với nhau.

Nếu ta chạy ứng dụng web và containers database một cách độc lập thông qua lệnh docker run , chúng sẽ không thể tìm thấy nhau.

Để biết lý do, hãy xem nội dung của file cấu hình database của ứng dụng web.

  • cat app/db.js

Sau khi nhập Mongoose - một thư viện mô hình hóa đối tượng MongoDB cho Node.js - và xác định một lược đồ database mới, ứng dụng web sẽ cố gắng kết nối với database tại tên server , db , chưa tồn tại.

~ / todo-app / app / db.js
var mongoose = require( 'mongoose' ); var Schema   = mongoose.Schema;  var Todo = new Schema({     user_id    : String,     content    : String,     updated_at : Date });  mongoose.model( 'Todo', Todo );  mongoose.connect( 'mongodb://db/express-todo' ); 

Để đảm bảo các containers thuộc cùng một ứng dụng phát hiện ra nhau, ta cần chạy chúng trên cùng một mạng.

Docker cung cấp khả năng tạo các mạng tùy chỉnh ngoài các mạng mặc định được tạo trong quá trình cài đặt.

Bạn có thể kiểm tra các mạng hiện có của bạn bằng lệnh sau:

  • docker network ls

Mỗi mạng do Docker tạo dựa trên một trình điều khiển . Trong kết quả kết quả sau đây, ta thấy rằng mạng được đặt tên là bridge dựa trên bridge trình điều khiển. Phạm vi local cho biết mạng chỉ khả dụng trên server này.

Output from docker network ls
NETWORK ID NAME DRIVER SCOPE 5029df19d0cf bridge bridge local 367330960d5c host host local f280c1593b89 none null local

Bây giờ ta sẽ tạo một mạng tùy chỉnh có tên là todo_net cho ứng dụng của bạn và sau đó ta sẽ chạy các containers trên mạng đó.

  • docker network create todo_net

Đầu ra cho ta biết hàm băm của mạng đã được tạo.

Output from docker network create
C09f199809ccb9928dd9a93408612bb99ae08bb5a65833fefd6db2181bfe17ac

Bây giờ, hãy liệt kê lại các mạng khả dụng.

  • docker network ls

Ở đây, ta thấy rằng todo_net đã sẵn sàng để sử dụng.

Output from docker network ls
NETWORK ID NAME DRIVER SCOPE c51377a045ff bridge bridge local 2e4106b07544 host host local 7a8b4801a712 none null local bc992f0b2be6 todo_net bridge local

Khi sử dụng lệnh --network docker run , bây giờ ta có thể tham chiếu đến mạng này bằng lựa chọn --network . Hãy chạy cả containers web và database với các tên server cụ thể. Điều này sẽ đảm bảo các containers có thể kết nối với nhau thông qua các tên server đó.

Đầu tiên, chạy containers database MongoDB.

  • docker run -d \
  • --name=db \
  • --hostname=db \
  • --network=todo_net \
  • mongo

Xem xét kỹ hơn lệnh đó, ta thấy:

  • Lựa chọn -d chạy containers ở chế độ tách rời .
  • Các lựa chọn --name--hostname chỉ định một tên do user xác định cho containers . Lựa chọn --hostname cũng thêm một mục nhập vào dịch vụ DNS do Docker quản lý . Điều này giúp giải quyết containers theo tên server .
  • Lựa chọn --network hướng dẫn Docker Engine chạy containers trên mạng tùy chỉnh thay vì mạng cầu nối mặc định.

Khi ta thấy một chuỗi dài là kết quả từ lệnh docker run , ta có thể giả định containers đã được chạy thành công. Tuy nhiên, điều này có thể không đảm bảo containers đang thực sự chạy.

Output docker run
aa56250f2421c5112cf8e383b68faefea91cd4b6da846cbc56cf3a0f04ff4295

Xác minh containers db được cài đặt và đang chạy bằng lệnh docker logs .

  • docker logs db

Thao tác này sẽ in các bản ghi containers thành stdout . Dòng cuối cùng của log cho biết MongoDB đã sẵn sàng và waiting for connections .

Output from docker logs
2017-12-10T02:55:08.284+0000 I CONTROL [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=db . . . . 2017-12-10T02:55:08.366+0000 I NETWORK [initandlisten] waiting for connections on port 27017

Bây giờ, hãy chạy containers web và xác minh nó. Lần này, ta cũng đang bao gồm --publish=3000:3000 trong đó công bố cổng của server 3000 đến cổng của container 3000 .

  • docker run -d \
  • --name=web \
  • --publish=3000:3000 \
  • --hostname=web \
  • --network=todo_net \
  • sammy/todo-web

Bạn sẽ nhận được một chuỗi dài dưới dạng kết quả như trước đây.

Hãy cũng xác minh containers này đang hoạt động.

  • docker logs web

Kết quả kết quả xác nhận Express - khung Node.js mà ứng dụng thử nghiệm của ta dựa trên - đang listening on port 3000 .

Output from docker logs
Express server listening on port 3000

Xác minh containers web có thể nói chuyện với containers db bằng lệnh ping . Ta thực hiện điều này bằng cách chạy lệnh thực thi docker exec trong chế độ tương tác ( -i ) được gắn với TTY giả ( -t ).

  • docker exec -it web ping db

Lệnh tạo ra kết quả ping tiêu chuẩn và cho ta biết rằng hai containers có thể giao tiếp với nhau.

Output from docker exec -it web ping db
PING db (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.210 ms 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.095 ms ...

Nhấn CTRL+C để dừng lệnh ping .

Cuối cùng, truy cập ứng dụng mẫu bằng cách trỏ trình duyệt web tới http://your_server_ip:3000 . Bạn sẽ thấy một trang web có nhãn ghi Ví dụ Todo của Container cùng với một hộp văn bản chấp nhận một công việc cần làm làm đầu vào.

Để tránh xung đột đặt tên, bây giờ bạn có thể dừng các containers và dọn dẹp tài nguyên bằng các lệnh docker network remove docker rmdocker network remove .

  • docker rm -f db
  • docker rm -f web
  • docker network remove todo_net

Đến đây, ta có một ứng dụng web được tạo thành từ hai containers riêng biệt. Trong bước tiếp theo, ta sẽ khám phá một cách tiếp cận mạnh mẽ hơn.

Bước 3 - Triển khai ứng dụng nhiều containers

Mặc dù ta có thể chạy các containers được liên kết, nhưng đó không phải là cách thanh lịch nhất để xử lý các ứng dụng nhiều containers . Ta cần một cách tốt hơn để khai báo tất cả các containers có liên quan và quản lý chúng như một đơn vị logic.

Docker Compose là một khung có sẵn cho các nhà phát triển để xử lý các ứng dụng nhiều containers . Giống như Dockefile, nó là một cơ chế khai báo để xác định toàn bộ ngăn xếp. Bây giờ ta sẽ chuyển đổi ứng dụng Node.js và MongoDB của ta thành một ứng dụng dựa trên Docker Compose.

Bắt đầu bằng cách cài đặt Docker Compose.

  • sudo apt-get install -y docker-compose

Hãy kiểm tra file docker-compose.yaml nằm trong compose thư của ứng dụng web mẫu.

  • cat compose/docker-compose.yaml

Tệp docker-compose.yaml kết hợp mọi thứ lại với nhau. Nó định nghĩa containers MongoDB trong db: block, containers web Node.js trong web: block và mạng tùy chỉnh trong các networks: block.

Lưu ý với bản build: ../. chỉ thị, ta đang trỏ Soạn thư tới Dockerfile trong folder app . Thao tác này sẽ hướng dẫn Soạn xây dựng hình ảnh trước khi chạy containers web.

~ / todo-app / compo / docker-compos.yaml
version: '2' services:   db:     image: mongo:latest     container_name: db     networks:       - todonet   web:     build: ../.     networks:       - todonet     ports:      - "3000" networks:   todonet:     driver: bridge 

Bây giờ, hãy chuyển sang compose thư và chạy ứng dụng bằng lệnh docker-compose up . Giống như khi docker run , lựa chọn -d khởi động containers ở chế độ tách rời.

  • cd compose
  • docker-compose up -d

Kết quả kết quả báo cáo rằng Docker Compose đã tạo một mạng gọi là compose_todonet và chạy cả hai containers trên đó.

Output from docker-compose up -d
Creating network "compose_todonet" with driver "bridge" Creating db Creating compose_web_1

Lưu ý ta không cung cấp ánh xạ cổng server rõ ràng. Điều này sẽ buộc Docker Compose chỉ định một cổng ngẫu nhiên để hiển thị ứng dụng web trên server . Ta có thể tìm thấy cổng đó bằng cách chạy lệnh sau:

  • docker ps

Ta thấy rằng ứng dụng web được hiển thị trên cổng server 32782 .

Output from docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6700761c0a1e compose_web "node app.js" 2 minutes ago Up 2 minutes 0.0.0.0:32782->3000/tcp compose_web_1 ad7656ef5db7 mongo:latest "docker-entrypoint..." 2 minutes ago Up 2 minutes 27017/tcp db

Xác minh điều này bằng cách chuyển trình duyệt web đến http://your_server_ip:32782 . Thao tác này sẽ hiển thị ứng dụng web giống như bạn đã thấy ở cuối Bước 2 .

Với ứng dụng đa containers của ta được cài đặt và chạy thông qua Docker Compose, hãy cùng xem cách quản lý và mở rộng ứng dụng của ta .

Bước 4 - Quản lý và mở rộng ứng dụng

Docker Compose giúp dễ dàng mở rộng các ứng dụng web không trạng thái. Ta có thể chạy 10 version của containers web của web bằng một lệnh duy nhất.

  • docker-compose scale web=10

Đầu ra cho phép ta xem các version đang được tạo và bắt đầu trong thời gian thực.

Output from docker-compose scale
Creating and starting compose_web_2 ... done Creating and starting compose_web_3 ... done Creating and starting compose_web_4 ... done Creating and starting compose_web_5 ... done Creating and starting compose_web_6 ... done Creating and starting compose_web_7 ... done Creating and starting compose_web_8 ... done Creating and starting compose_web_9 ... done Creating and starting compose_web_10 ... done

Xác minh ứng dụng web được chia tỷ lệ thành 10 version bằng cách chạy docker ps .

  • docker ps

Lưu ý Docker đã chỉ định một cổng ngẫu nhiên để hiển thị từng containers web trên server . Bất kỳ cổng nào trong số này đều được dùng để truy cập ứng dụng.

Output from docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cec405db568d compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32788->3000/tcp compose_web_9 56adb12640bb compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32791->3000/tcp compose_web_10 4a1005d1356a compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32790->3000/tcp compose_web_7 869077de9cb1 compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32785->3000/tcp compose_web_8 eef86c56d16f compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32783->3000/tcp compose_web_4 26dbce7f6dab compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32786->3000/tcp compose_web_5 0b3abd8eee84 compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32784->3000/tcp compose_web_3 8f867f60d11d compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32789->3000/tcp compose_web_6 36b817c6110b compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32787->3000/tcp compose_web_2 6700761c0a1e compose_web "node app.js" 7 minutes ago Up 7 minutes 0.0.0.0:32782->3000/tcp compose_web_1 ad7656ef5db7 mongo:latest "docker-entrypoint..." 7 minutes ago Up 7 minutes 27017/tcp db

Bạn cũng có thể mở rộng containers web bằng lệnh tương tự.

  • docker-compose scale web=2

Lần này, ta thấy các trường hợp bổ sung được xóa trong thời gian thực.

Output from docker-compose
Stopping and removing compose_web_3 ... done Stopping and removing compose_web_4 ... done Stopping and removing compose_web_5 ... done Stopping and removing compose_web_6 ... done Stopping and removing compose_web_7 ... done Stopping and removing compose_web_8 ... done Stopping and removing compose_web_9 ... done Stopping and removing compose_web_10 ... done

Cuối cùng, kiểm tra lại các version .

  • docker ps

Kết quả xác nhận chỉ còn hai version .

Output from docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 36b817c6110b compose_web "node app.js" 3 minutes ago Up 3 minutes 0.0.0.0:32787->3000/tcp compose_web_2 6700761c0a1e compose_web "node app.js" 9 minutes ago Up 9 minutes 0.0.0.0:32782->3000/tcp compose_web_1 ad7656ef5db7 mongo:latest "docker-entrypoint..." 9 minutes ago Up 9 minutes 27017/tcp db

Đến đây bạn có thể dừng ứng dụng và giống như trước đây, bạn cũng có thể dọn dẹp tài nguyên để tránh xung đột tên.

  • docker-compose stop
  • docker-compose rm -f
  • docker network remove compose_todonet

Kết luận

Hướng dẫn này đã giới thiệu cho bạn về Dockerfiles và Docker Compose. Ta bắt đầu với Dockerfile làm cơ chế khai báo để xây dựng hình ảnh, sau đó ta khám phá những điều cơ bản về mạng Docker. Cuối cùng, ta đã mở rộng quy mô và quản lý các ứng dụng đa containers bằng Docker Compose.

Để mở rộng cài đặt mới của bạn , bạn có thể thêm reverse-proxy Nginx chạy bên trong một containers khác để định tuyến các yêu cầu đến một trong các containers ứng dụng web có sẵn. Hoặc, bạn có thể tận dụngBộ lưu trữ khốiCân bằng tải củaDigitalOcean để mang lại độ bền và khả năng mở rộng cho các ứng dụng được chứa trong container.


Tags:

Các tin liên quan