Kiến thức Hữu ích 😍

Hướng Dẫn Chạy Flask Với Docker trên Ubuntu 20.04 | Chi Tiết, Đơn Giản


Bạn đang tìm cách triển khai ứng dụng Flask là gì một cách hiệu quả và nhất quán trên Ubuntu 20 04? Việc quản lý môi trường, dependencies và các phiên bản khác nhau có thể trở nên phức tạp, đặc biệt khi chuyển từ môi trường phát triển sang sản phẩm. Đây chính là lúc Docker là gì xuất hiện như một giải pháp cứu cánh. Công nghệ container là gì này giúp đóng gói ứng dụng Flask cùng với tất cả các thư viện cần thiết vào một “hộp” duy nhất, đảm bảo nó chạy ổn định ở bất cứ đâu.

Trong bài viết này, AZWEB sẽ hướng dẫn bạn chi tiết từng bước để chạy ứng dụng Flask bằng Docker trên hệ điều hành Ubuntu 20.04. Chúng ta sẽ cùng nhau đi từ việc chuẩn bị môi trường, viết Dockerfile, build image cho đến khi chạy container và kiểm thử ứng dụng. Hãy cùng khám phá cách tối ưu hóa quy trình làm việc của bạn ngay bây giờ!

Hình minh họa

Giới thiệu về Flask và ứng dụng web Python

Trước khi đi sâu vào kỹ thuật, hãy cùng tìm hiểu về những nhân vật chính của chúng ta: Flask là gì và vai trò của nó trong thế giới phát triển web bằng Python là gì.

Flask là gì?

Flask là một micro-framework dùng để xây dựng ứng dụng web bằng ngôn ngữ lập trình Python. Được gọi là “micro” không phải vì nó thiếu chức năng, mà vì cốt lõi của nó rất gọn nhẹ và có thể mở rộng. Flask cung cấp những công cụ cơ bản nhất để bạn bắt đầu, như định tuyến (routing) và quản lý request, nhưng lại không ép buộc bạn phải theo một cấu trúc dự án hay sử dụng những công cụ cụ thể nào.

Ưu điểm lớn nhất của Flask chính là sự đơn giản và linh hoạt. So với các framework là gì lớn hơn như Django, Flask cho phép lập trình viên toàn quyền quyết định về thư viện và kiến trúc mà họ muốn sử dụng. Điều này giúp việc học và bắt đầu một dự án mới trở nên cực kỳ nhanh chóng.

Vai trò của Flask trong phát triển ứng dụng web

Nhờ tính linh hoạt, Flask trở thành lựa chọn hàng đầu cho việc xây dựng các dịch vụ nhỏ, API RESTful, hoặc các sản phẩm khả dụng tối thiểu (MVP). Thay vì phải thiết lập một cấu trúc phức tạp, bạn có thể nhanh chóng tạo ra một ứng dụng web hoạt động chỉ với vài dòng code.

Sự phổ biến của Flask trong cộng đồng Python còn đến từ hệ sinh thái mở rộng phong phú của nó. Bạn có thể dễ dàng tích hợp các thư viện cho việc xác thực người dùng, tương tác với cơ sở dữ liệu, hay xử lý biểu mẫu. Điều này biến Flask thành một công cụ mạnh mẽ, đủ sức đáp ứng nhuệ cầu từ các dự án cá nhân nhỏ lẻ đến các hệ thống API phức tạp của doanh nghiệp.

Tổng quan về Docker và lợi ích khi sử dụng Docker cho phát triển ứng dụng

Bây giờ, hãy chuyển sang công nghệ sẽ giúp chúng ta đóng gói và vận hành ứng dụng Flask một cách kỳ diệu: Docker là gì.

Docker là gì?

Docker là một nền tảng mở giúp tự động hóa việc triển khai, mở rộng và quản lý ứng dụng bằng cách sử dụng công nghệ container. Hiểu đơn giản, một container là một gói phần mềm độc lập, chứa mọi thứ cần thiết để chạy một ứng dụng: mã nguồn, runtime, thư viện hệ thống, và các cài đặt. Container này đảm bảo ứng dụng của bạn sẽ chạy theo cùng một cách, bất kể môi trường triển khai là gì.

Một điểm khác biệt quan trọng là Docker container chia sẻ nhân (kernel) của hệ điều hành máy chủ, thay vì phải ảo hóa toàn bộ một hệ điều hành như máy ảo (VM) truyền thống. Điều này giúp container nhẹ hơn, khởi động nhanh hơn và sử dụng tài nguyên hiệu quả hơn rất nhiều.

Hình minh họa

Lợi ích khi dùng Docker cho Flask trên Ubuntu

Sử dụng Docker để triển khai ứng dụng Flask trên Ubuntu mang lại nhiều lợi ích vượt trội, giúp quy trình làm việc của bạn trở nên chuyên nghiệp và hiệu quả hơn.

  • Tính nhất quán môi trường: Docker giải quyết triệt để vấn đề “Nó chạy trên máy của tôi mà!”. Ứng dụng Flask của bạn được đóng gói cùng với môi trường chính xác mà nó cần, từ phiên bản Python đến các thư viện phụ thuộc. Điều này đảm bảo tính nhất quán tuyệt đối giữa môi trường phát triển, kiểm thử và sản phẩm.
  • Dễ dàng đóng gói và vận chuyển: Một khi bạn đã tạo ra một Docker image cho ứng dụng của mình, bạn có thể dễ dàng chia sẻ và chạy nó trên bất kỳ máy nào đã cài đặt Docker. Quá trình triển khai trở nên đơn giản chỉ bằng một vài câu lệnh.
  • Tiết kiệm tài nguyên và tăng hiệu suất: Vì container nhẹ hơn máy ảo, bạn có thể chạy nhiều container ứng dụng trên cùng một máy chủ, giúp tận dụng tối đa tài nguyên phần cứng. Việc khởi động và dừng container cũng diễn ra gần như tức thời, giúp tăng tốc độ phát triển và triển khai.
  • Khả năng mở rộng linh hoạt: Khi ứng dụng của bạn cần xử lý nhiều lưu lượng truy cập hơn, bạn có thể dễ dàng tạo thêm các bản sao của container để cân bằng tải, giúp hệ thống hoạt động ổn định và đáp ứng tốt hơn.

Chuẩn bị môi trường Ubuntu 20.04 cho Docker và Flask

Để bắt đầu, chúng ta cần đảm bảo rằng máy chủ Ubuntu 20.04 của bạn đã được trang bị đầy đủ các công cụ cần thiết.

Cài đặt Docker trên Ubuntu 20.04

Việc cài đặt Docker Engine trên Ubuntu khá đơn giản. Bạn chỉ cần thực hiện lần lượt các lệnh sau trong terminal.

Đầu tiên, cập nhật danh sách package của bạn:
sudo apt update

Tiếp theo, cài đặt các package cần thiết để apt có thể sử dụng repository qua HTTPS:
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y

Thêm khóa GPG chính thức của Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Thêm Docker repository vào apt sources:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"

Cuối cùng, cài đặt Docker Engine:
sudo apt update
sudo apt install docker-ce -y

Để kiểm tra Docker đã được cài đặt thành công hay chưa, bạn hãy chạy lệnh sau. Nếu thấy phiên bản Docker được hiển thị, bạn đã sẵn sàng cho bước tiếp theo.
docker --version

Hình minh họa

Thiết lập môi trường Flask cơ bản

Bây giờ, hãy tạo một ứng dụng Flask đơn giản để chúng ta có thứ để “Docker hóa”.

Đầu tiên, hãy tạo một thư mục cho dự án của bạn:
mkdir flask_app
cd flask_app

Tiếp theo, chúng ta sẽ tạo một file ứng dụng Python tên là app.py. Bạn có thể dùng nano hoặc bất kỳ trình soạn thảo văn bản nào.
nano app.py

Bên trong file app.py, hãy thêm đoạn mã sau:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, AZWEB! This is a Flask app running in a Docker container.'

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

Lưu ý quan trọng: Tham số host='0.0.0.0' rất cần thiết. Nó yêu cầu Flask lắng nghe các kết nối từ tất cả các địa chỉ IP, cho phép chúng ta truy cập ứng dụng từ bên ngoài container. Nếu không có tham số này, ứng dụng sẽ chỉ chạy trên localhost bên trong container và bạn sẽ không thể kết nối tới nó.

Cuối cùng, tạo file requirements.txt để quản lý các thư viện Python.
nano requirements.txt

Thêm dòng sau vào file:
Flask==2.0.1

Vậy là chúng ta đã có một ứng dụng Flask cơ bản và sẵn sàng để đóng gói bằng Docker.

Hình minh họa

Hướng dẫn viết Dockerfile để đóng gói ứng dụng Flask

Dockerfile là một tệp văn bản chứa các chỉ dẫn để Docker tự động build một image. Nó giống như một bản kế hoạch chi tiết cho môi trường ứng dụng của bạn.

Cấu trúc Dockerfile chuẩn cho Flask

Một Dockerfile cho ứng dụng Flask thường bao gồm các bước chính sau:

  • FROM: Chọn một base image (image nền) để bắt đầu. Đây là nền tảng của container. Đối với ứng dụng Python, một lựa chọn phổ biến và nhẹ nhàng là python:3.8-slim.
  • WORKDIR: Thiết lập thư mục làm việc bên trong container. Mọi lệnh sau đó sẽ được thực thi trong thư mục này.
  • COPY: Sao chép các tệp từ máy của bạn vào bên trong container. Chúng ta sẽ sao chép file requirements.txt trước để tận dụng cơ chế cache của Docker.
  • RUN: Thực thi các lệnh bên trong container. Lệnh này thường được dùng để cài đặt các dependencies từ requirements.txt.
  • COPY . .: Sao chép toàn bộ mã nguồn của dự án vào thư mục làm việc trong container.
  • EXPOSE: Thông báo cho Docker biết container sẽ lắng nghe trên một port cụ thể nào đó.
  • CMD: Cung cấp lệnh mặc định sẽ được thực thi khi container khởi chạy.

Ví dụ Dockerfile hoàn chỉnh

Trong thư mục flask_app của bạn, hãy tạo một file mới tên là Dockerfile.
nano Dockerfile

Thêm nội dung sau vào file, kèm theo các chú thích giải thích từng bước:

# Bước 1: Chọn base image là phiên bản Python 3.8-slim
FROM python:3.8-slim

# Bước 2: Thiết lập thư mục làm việc bên trong container là /app
WORKDIR /app

# Bước 3: Sao chép file requirements.txt vào thư mục làm việc
# Sao chép file này trước để tận dụng Docker cache. Nếu file không thay đổi,
# Docker sẽ không cần chạy lại bước cài đặt dependencies, giúp build nhanh hơn.
COPY requirements.txt .

# Bước 4: Cài đặt các thư viện Python cần thiết
RUN pip install --no-cache-dir -r requirements.txt

# Bước 5: Sao chép toàn bộ mã nguồn từ thư mục hiện tại vào container
COPY . .

# Bước 6: Thông báo rằng container sẽ lắng nghe trên port 5000
EXPOSE 5000

# Bước 7: Lệnh để chạy ứng dụng khi container khởi động
CMD ["python", "app.py"]

Mỗi dòng lệnh trong Dockerfile này đều đóng một vai trò quan trọng trong việc tạo ra một môi trường cô lập và có thể tái tạo hoàn hảo cho ứng dụng Flask của bạn.

Hình minh họa

Cách build Docker image cho ứng dụng Flask

Sau khi đã có Dockerfile, bước tiếp theo là sử dụng nó để build một Docker image. Image này chính là khuôn mẫu chứa ứng dụng và môi trường của bạn.

Lệnh build image đơn giản

Để build image, hãy mở terminal trong thư mục dự án (flask_app) và chạy lệnh docker build.

docker build -t flask-app-azweb:latest .

Hãy phân tích lệnh này:

  • docker build: Là lệnh chính để bắt đầu quá trình build.
  • -t flask-app-azweb:latest: Tham số -t (viết tắt của --tag) dùng để đặt tên và thẻ cho image. Ở đây, chúng ta đặt tên là flask-app-azweb và thẻ là latest. Việc đặt tên giúp bạn dễ dàng quản lý và nhận diện image sau này.
  • .: Dấu chấm ở cuối cùng chỉ định ngữ cảnh build (build context) là thư mục hiện tại. Docker sẽ tìm Dockerfile trong thư mục này và sử dụng các tệp trong đó để build image.

Sau khi lệnh chạy xong, bạn có thể kiểm tra image vừa được tạo bằng cách liệt kê tất cả các image trên máy của bạn:
docker images

Bạn sẽ thấy image flask-app-azweb với thẻ latest xuất hiện trong danh sách.

Hình minh họa

Tối ưu hóa image Docker

Mặc dù image của chúng ta đã hoạt động, trong các dự án thực tế, việc tối ưu hóa image là rất quan trọng để giảm dung lượng và tăng cường bảo mật.

  • Sử dụng .dockerignore: Tương tự như .gitignore, file .dockerignore cho phép bạn loại bỏ các tệp và thư mục không cần thiết ra khỏi quá trình build (ví dụ: __pycache__, .venv, các file log). Điều này giúp giảm kích thước image và tăng tốc độ build.
  • Giảm dung lượng image: Chọn các base image nhẹ như python:3.8-slim hoặc alpine thay vì các phiên bản đầy đủ. Sử dụng pip install --no-cache-dir như trong ví dụ cũng giúp loại bỏ cache không cần thiết.
  • Sử dụng multi-stage build: Đối với các ứng dụng phức tạp hơn cần các công cụ build, bạn có thể sử dụng multi-stage build. Kỹ thuật này cho phép bạn dùng một image lớn để biên dịch và build, sau đó chỉ sao chép các tệp thực thi cần thiết sang một image nền nhỏ hơn để chạy, giúp giảm đáng kể dung lượng image cuối cùng.

Chạy container Docker chứa ứng dụng Flask trên Ubuntu

Bây giờ chúng ta đã có image, đã đến lúc khởi chạy nó như một container đang hoạt động.

Lệnh chạy container cơ bản

Sử dụng lệnh docker run để tạo và khởi động một container từ image flask-app-azweb mà chúng ta vừa build.

docker run -d -p 5000:5000 --name flask-container flask-app-azweb:latest

Hãy cùng xem xét các tham số trong lệnh này:

  • docker run: Lệnh để chạy một container.
  • -d: Chạy container ở chế độ detached (chạy ngầm). Terminal của bạn sẽ được giải phóng ngay sau khi container khởi động.
  • -p 5000:5000: Đây là phần quan trọng nhất – port mapping. Nó ánh xạ port 5000 của máy chủ (host) vào port 5000 của container. Điều này cho phép chúng ta truy cập ứng dụng đang chạy bên trong container thông qua port của máy chủ.
  • --name flask-container: Đặt một cái tên cụ thể cho container là flask-container để dễ quản lý.
  • flask-app-azweb:latest: Tên của image mà chúng ta muốn chạy.

Kiểm tra ứng dụng chạy trong container

Sau khi chạy lệnh trên, container của bạn đã được khởi động. Để kiểm tra, hãy mở trình duyệt web và truy cập vào địa chỉ:
http://<ĐỊA_CHỈ_IP_SERVER_CỦA_BẠN>:5000

Nếu mọi thứ hoạt động chính xác, bạn sẽ thấy dòng chữ: “Hello, AZWEB! This is a Flask app running in a Docker container.”

Để xem container nào đang chạy, bạn có thể dùng lệnh:
docker ps

Nếu bạn cần xem log của ứng dụng để gỡ lỗi, hãy sử dụng lệnh docker logs với tên container:
docker logs flask-container

Lệnh này rất hữu ích để kiểm tra các lỗi hoặc output từ ứng dụng Flask của bạn.

Hình minh họa

Kiểm thử và triển khai ứng dụng Flask trong môi trường Docker

Việc chạy container chỉ là bước khởi đầu. Trong môi trường thực tế, bạn cần kiểm thử và có một kế hoạch triển khai rõ ràng.

Kiểm thử chức năng trong container

Khi ứng dụng của bạn đã chạy trong container, bạn có thể sử dụng các công cụ như Postman là gì hoặc curl để kiểm tra các API endpoint. Ví dụ, từ terminal của máy chủ Ubuntu, bạn có thể chạy lệnh:
curl http://localhost:5000

Lệnh này sẽ trả về nội dung trang chủ của ứng dụng Flask, xác nhận rằng nó đang hoạt động đúng cách.

Để giám sát trạng thái và tài nguyên mà container đang sử dụng (CPU, RAM), bạn có thể dùng lệnh docker stats:
docker stats flask-container

Việc này giúp bạn đánh giá hiệu suất của ứng dụng trong môi trường được cô lập.

Triển khai ứng dụng lên môi trường thực tế

Đối với việc triển khai trên server thực tế, bạn sẽ cần một quy trình mạnh mẽ hơn.

  • Deploy đơn giản: Cách đơn giản nhất là cài đặt Docker trên server production, sao chép image của bạn lên đó (hoặc pull từ một registry như Docker Hub), và dùng lệnh docker run tương tự như khi phát triển.
  • Sử dụng Docker Compose: Khi ứng dụng của bạn phức tạp hơn, ví dụ cần một database (như PostgreSQL) và một web server (như Nginx) chạy cùng, Ci Cd là gì là công cụ không thể thiếu. Nó cho phép bạn định nghĩa và quản lý một ứng dụng đa container bằng một file YAML duy nhất, giúp đơn giản hóa việc khởi chạy và kết nối các dịch vụ với nhau.
  • Sử dụng Portainer: Nếu bạn ưa thích giao diện đồ họa, Portainer là một công cụ quản lý Docker mạnh mẽ. Nó cung cấp một dashboard web để bạn dễ dàng xem, quản lý, và triển khai các container, image, network và volume mà không cần dùng dòng lệnh.

Hình minh họa

Mẹo và lưu ý khi sử dụng Docker với Flask trên Ubuntu

Để làm việc hiệu quả và an toàn hơn, hãy ghi nhớ một vài mẹo và lưu ý quan trọng sau.

Mẹo tối ưu hiệu suất Docker cho Flask

  • Quản lý volumes: Trong quá trình phát triển, để không phải build lại image mỗi khi thay đổi mã nguồn, bạn có thể sử dụng volume binding. Lệnh docker run -v $(pwd):/app sẽ ánh xạ thư mục dự án hiện tại trên máy của bạn vào thư mục /app trong container. Mọi thay đổi trong code sẽ được phản ánh ngay lập tức.
  • Quản lý network: Docker cung cấp các chế độ network khác nhau. Đối với ứng dụng đa container (ví dụ: web và database), hãy tạo một bridge network riêng để các container có thể giao tiếp với nhau một cách an toàn và dễ dàng thông qua tên dịch vụ.

Lưu ý bảo mật và bảo trì

  • Tránh lộ thông tin nhạy cảm: Tuyệt đối không hardcode các thông tin nhạy cảm như mật khẩu database, API key vào trong Dockerfile hoặc mã nguồn. Thay vào đó, hãy sử dụng biến môi trường (environment variables) để truyền các thông tin này vào container khi chạy.
  • Cập nhật định kỳ: Luôn đảm bảo base image và các dependencies trong requirements.txt được cập nhật lên các phiên bản mới nhất để vá các lỗ hổng bảo mật đã biết.
  • Quét lỗ hổng bảo mật: Sử dụng các công cụ như Docker Scout hoặc DevOps là gì hay Snyk để tự động quét image của bạn và phát hiện các lỗ hổng bảo mật tiềm ẩn.

Common Issues/Troubleshooting

Trong quá trình làm việc, bạn có thể gặp phải một số lỗi phổ biến. Dưới đây là cách xử lý chúng.

Lỗi failed to connect Flask app trong container

Đây là lỗi thường gặp nhất. Nguyên nhân phổ biến bao gồm:

  • Sai port binding: Kiểm tra lại lệnh docker run và chắc chắn rằng bạn đã ánh xạ đúng port. Ví dụ, -p 80:5000 sẽ ánh xạ port 80 của host vào port 5000 của container.
  • Flask không chạy trên 0.0.0.0: Như đã đề cập, ứng dụng Flask bên trong container phải được chạy với host='0.0.0.0'. Nếu nó chỉ chạy trên 127.0.0.1 (localhost), nó sẽ không chấp nhận kết nối từ bên ngoài container, kể cả khi port đã được mapping.
  • Tường lửa: Kiểm tra xem tường lửa trên máy chủ Ubuntu (ví dụ ufw) có đang chặn port bạn đang cố truy cập hay không.

Hình minh họa

Lỗi Docker build không thành công do dependency

Lỗi này thường xảy ra ở bước RUN pip install -r requirements.txt.

  • Kiểm tra log build: Docker sẽ hiển thị chi tiết lỗi trong quá trình build. Hãy đọc kỹ log để xác định package nào đang gây ra vấn đề.
  • Thiếu build-essentials: Một số package Python cần các công cụ biên dịch của hệ thống để cài đặt. Bạn có thể cần thêm RUN apt-get update && apt-get install -y build-essential vào Dockerfile trước bước pip install.
  • Vấn đề phiên bản: Đôi khi, một phiên bản package cụ thể không tương thích với base image hoặc các package khác. Hãy thử chỉ định các phiên bản tương thích trong file requirements.txt.

Best Practices

Để quy trình làm việc của bạn chuyên nghiệp và dễ bảo trì, hãy tuân thủ các thực hành tốt nhất sau:

  • Luôn dùng requirements.txt: Quản lý tất cả các thư viện Python trong một file requirements.txt. Điều này đảm bảo môi trường của bạn luôn có thể tái tạo một cách chính xác.
  • Sử dụng biến môi trường (ENV): Dùng biến môi trường để cấu hình ứng dụng (ví dụ: FLASK_ENV, DATABASE_URL) thay vì hardcode giá trị. Điều này giúp image của bạn linh hoạt hơn và có thể tái sử dụng trong các môi trường khác nhau.
  • Không chạy container với quyền root: Mặc định, các tiến trình trong container chạy với quyền root. Đây là một rủi ro bảo mật. Hãy tạo một người dùng không có quyền root trong Dockerfile và sử dụng nó để chạy ứng dụng của bạn.
  • Định kỳ dọn dẹp: Docker có thể chiếm rất nhiều dung lượng đĩa với các image, container, và volume không còn sử dụng. Hãy thường xuyên chạy lệnh docker system prune để dọn dẹp hệ thống.

Conclusion

Qua bài viết này, chúng ta đã cùng nhau đi qua một hành trình chi tiết từ việc chuẩn bị môi trường Ubuntu 20.04, tạo một ứng dụng Flask đơn giản, viết Dockerfile để đóng gói nó, cho đến việc build image, chạy container và kiểm thử. Việc sử dụng Docker không chỉ giúp giải quyết các vấn đề về tính nhất quán môi trường mà còn tối ưu hóa toàn bộ quy trình phát triển, triển khai và mở rộng ứng dụng của bạn.

Bằng cách áp dụng Docker, bạn đã trang bị cho dự án Flask của mình một nền tảng vững chắc, linh hoạt và hiệu quả hơn. AZWEB hy vọng rằng hướng dẫn này sẽ là bước đệm vững chắc để bạn tự tin áp dụng công nghệ container hóa vào các dự án Python của mình trong tương lai. Hãy tiếp tục thực hành và khám phá sâu hơn về hệ sinh thái Docker để nâng cao kỹ năng phát triển của mình.

Hình minh họa

Đánh giá