0
0
Lập trình
Hưng Nguyễn Xuân 1
Hưng Nguyễn Xuân 1xuanhungptithcm

Triển Khai Ứng Dụng Bầu Cử Tideman Trên AWS EC2 Với Docker

Đăng vào 7 tháng trước

• 7 phút đọc

Giới thiệu

Gần đây, tôi đã đưa ứng dụng Tideman từ máy tính cá nhân lên đám mây, và việc đưa nó trực tuyến trên AWS EC2 với Docker thực sự đơn giản hơn tôi nghĩ.

Mục tiêu bài viết

Trong bài viết này, tôi sẽ hướng dẫn bạn cách triển khai ứng dụng bầu cử Tideman sử dụng Docker trên EC2. Chúng ta sẽ đi qua từng bước, từ việc thiết lập EC2 đến cấu hình Docker và chạy ứng dụng Flask.

Tạo phiên bản EC2

Bước 1: Khởi tạo EC2

Trước tiên, tôi đã khởi tạo một AWS EC2 instance với hệ điều hành Ubuntu. Tôi chọn một phiên bản nhỏ (đủ điều kiện miễn phí) vì ứng dụng của tôi không quá nặng nề.

Bước 2: Cấu hình Security Group

Sau khi khởi tạo, tôi cấu hình Security Group của instance để cho phép các cổng thích hợp:

  • Cổng 22 (SSH) cho phép kết nối tới terminal của server.
  • Cổng 80 (HTTP) để ứng dụng web có thể truy cập qua trình duyệt.

Bước 3: Cài đặt Docker

Tiếp theo, tôi đã cài đặt Docker và sao chép mã nguồn vào EC2 instance:

bash Copy
# Trên instance EC2
sudo apt-get update
sudo apt-get install -y docker.io git

# (Tùy chọn) sao chép repo và chuyển vào thư mục
git clone <đường-dẫn-repo>
cd <thư-mục-repo>

Viết Dockerfile với Multi-Stage

Giờ đây, chúng ta sẽ container hóa ứng dụng với Docker.

Bước 4: Tạo Dockerfile

Tôi đã tạo một file có tên Dockerfile trong thư mục dự án. Vì ứng dụng của tôi có hai thành phần (C++ và Python), tôi đã sử dụng multi-stage Docker build để giữ cho hình ảnh cuối cùng gọn nhẹ. Dưới đây là cách tôi thiết lập:

Giai đoạn 1: Biên dịch chương trình C++

Trong giai đoạn đầu tiên, tôi đã sử dụng một hình ảnh Docker với trình biên dịch C++ để biên dịch thuật toán:

dockerfile Copy
# Giai đoạn 1: Biên dịch mã C++
FROM gcc:latest AS builder       # Sử dụng hình ảnh trình biên dịch GCC
WORKDIR /app

# Sao chép mã nguồn C++ và biên dịch
COPY my_algorithm.cpp /app/my_algorithm.cpp
RUN g++ my_algorithm.cpp -o my_algorithm

Giai đoạn 2: Thiết lập Python + Flask

Trong giai đoạn thứ hai, tôi muốn một môi trường Python nhẹ để chạy Flask và nhị phân đã biên dịch. Tôi đã chọn một hình ảnh Python nhỏ gọn:

dockerfile Copy
# Giai đoạn 2: Chạy ứng dụng Flask với Gunicorn
FROM python:3.10-slim AS final   # Sử dụng hình ảnh Python nhỏ
WORKDIR /app

# Sao chép nhị phân C++ đã biên dịch từ giai đoạn builder
COPY --from=builder /app/my_algorithm /app/my_algorithm

# Sao chép mã ứng dụng Flask và các file khác
COPY app.py /app/app.py
COPY index.html /app/index.html
COPY requirements.txt /app/requirements.txt

# Cài đặt Flask (và Gunicorn) qua requirements
RUN pip install -r requirements.txt

# Mở cổng 5000 và khởi động ứng dụng bằng Gunicorn
EXPOSE 5000
CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app"]

Phân tích giai đoạn 2

  • Chúng ta chuyển sang hình ảnh Python 3 slim (nhỏ hơn nhiều so với hình ảnh Ubuntu hoặc GCC đầy đủ).
  • Sao chép nhị phân C++ đã biên dịch từ giai đoạn 1 vào hình ảnh mới này. Bằng cách này, container Python có thể sử dụng chương trình C++ mà không cần trình biên dịch.
  • Sao chép mã ứng dụng Flask (app.py), index.html, và requirements.txt liệt kê các phụ thuộc Python.
  • Cài đặt các phụ thuộc: Tôi đã bao gồm Flask (và Gunicorn cho server) trong requirements.txt, do đó pip install -r requirements.txt sẽ kéo chúng vào container.
  • Cuối cùng, thiết lập container lắng nghe trên cổng 5000 và định nghĩa lệnh khởi động: tôi sử dụng Gunicorn để chạy ứng dụng Flask.

Phương pháp multi-stage giúp hình ảnh cuối cùng (giai đoạn 2) không bao gồm tất cả các công cụ xây dựng cồng kềnh từ giai đoạn 1. Chúng ta chỉ mang theo nhị phân đã biên dịch và các file cần thiết. Điều này làm cho hình ảnh Docker cuối cùng nhỏ hơn và sạch hơn, rất tốt cho hiệu suất và bảo mật.

Xây dựng và chạy container Docker

Với Dockerfile đã được viết, tôi tiến hành xây dựng hình ảnh trên EC2 instance:

bash Copy
sudo docker build -t myflaskcpp .

Chạy container

Tiếp theo, tôi đã chạy container. Đây là lúc cấu hình cổng rất quan trọng. Ứng dụng Flask của tôi (thông qua Gunicorn) được thiết lập chạy trên cổng 5000 bên trong container. Nhưng tôi muốn mọi người truy cập nó thông qua cổng HTTP chuẩn cổng 80 trên instance EC2. Vì vậy, tôi đã sử dụng ánh xạ cổng:

bash Copy
sudo docker run -d -p 80:5000 myflaskcpp

Ở đây, -p 80:5000 ánh xạ cổng 80 trên máy chủ (EC2 instance) tới cổng 5000 bên trong container. Giờ đây, bất kỳ yêu cầu nào đến IP công cộng của EC2 trên cổng 80 sẽ được chuyển tiếp đến ứng dụng Flask trong container. Tôi đã chạy container ở chế độ tách biệt (-d) để nó chạy trong nền.

Lưu ý: Đảm bảo bạn đã mở cổng 80 trong security group của EC2. Nếu không, bạn sẽ không thể truy cập ứng dụng từ trình duyệt.

Tại sao sử dụng Gunicorn thay vì máy chủ phát triển của Flask?

Bạn có thể tự hỏi tại sao tôi lại sử dụng Gunicorn trong Dockerfile, thay vì chỉ chạy máy chủ phát triển:

bash Copy
python app.py

Lý do là máy chủ tích hợp của Flask (máy chủ bạn nhận được với app.run()) chỉ được thiết kế cho phát triển. Nó là đơn luồng theo mặc định và không được tối ưu hóa cho nhiều người dùng hoặc độ ổn định trong sản xuất.

Gunicorn, mặt khác, là một máy chủ WSGI sẵn sàng cho sản xuất. Nó có thể xử lý nhiều yêu cầu cùng một lúc bằng cách chạy nhiều tiến trình công nhân. Điều này có nghĩa là nếu một người dùng đang thực hiện một yêu cầu chậm, những người dùng khác vẫn có thể được phục vụ song song. Gunicorn cũng được thử nghiệm tốt cho việc triển khai, làm cho ứng dụng của bạn trở nên mạnh mẽ hơn dưới lưu lượng thực tế. Tóm lại, việc sử dụng Gunicorn đảm bảo ứng dụng Flask của chúng ta có thể xử lý nhiều người cùng một lúc và không bị sập ngay khi có dấu hiệu căng thẳng.

Kết luận

Bây giờ hãy lấy IP công cộng của instance EC2 và kiểm tra xem nó có hoạt động không.

Và đó là tất cả! Chúng ta đã triển khai thành công một thuật toán C++ và một giao diện web Flask trên AWS sử dụng Docker. Là một người mới kết hợp các công nghệ này, tôi thật sự cảm thấy tuyệt vời khi thấy nó chạy trực tiếp.

Những điểm chính cần ghi nhớ

  • Sử dụng security groups của EC2 để mở các cổng bạn cần (SSH và HTTP trong trường hợp này).
  • Docker multi-stage builds có thể kết hợp nhiều ngôn ngữ (biên dịch trong một giai đoạn, chạy trong giai đoạn khác) để giữ mọi thứ hiệu quả.
  • Ánh xạ các cổng nội bộ của container tới các cổng của server để thế giới có thể truy cập ứng dụng của bạn.
  • Gunicorn là người bạn đồng hành cho việc phục vụ Flask trong môi trường sản xuất.

Chúc bạn triển khai thành công! 🚀

Các thực tiễn tốt nhất

  • Luôn kiểm tra các cổng trong security group trước khi triển khai.
  • Sử dụng các hình ảnh Docker nhỏ gọn để tiết kiệm tài nguyên.
  • Đảm bảo xử lý lỗi trong mã nguồn để ứng dụng hoạt động ổn định.

Những cạm bẫy phổ biến

  • Không mở cổng HTTP dẫn đến việc không truy cập được ứng dụng.
  • Sử dụng máy chủ phát triển Flask trong môi trường sản xuất.

Mẹo hiệu suất

  • Tối ưu hóa Dockerfile để giảm kích thước hình ảnh.
  • Sử dụng caching cho các phụ thuộc Python khi xây dựng hình ảnh.

Giải quyết sự cố

Nếu bạn gặp sự cố khi truy cập ứng dụng:

  • Kiểm tra xem container có đang chạy không bằng lệnh sudo docker ps.
  • Đảm bảo rằng IP công cộng của bạn là chính xác và không có vấn đề gì về mạng.

Câu hỏi thường gặp

1. Tôi cần cài đặt gì trên EC2 trước khi chạy ứng dụng?

Bạn cần cài đặt Docker và Git trên EC2 để có thể triển khai ứng dụng.

2. Tại sao lại sử dụng multi-stage builds?

Multi-stage builds giúp giảm kích thước hình ảnh Docker cuối cùng bằng cách chỉ giữ lại những file cần thiết.

3. Gunicorn có dễ sử dụng không?

Có, Gunicorn rất dễ cấu hình và cung cấp hiệu suất tốt hơn cho ứng dụng Flask của bạn.

Tài nguyên tham khảo

Hy vọng rằng bài viết này sẽ giúp bạn triển khai ứng dụng của mình một cách dễ dàng nhất!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào