Hoàn thành bài "Từ Prototype đến Production: Tư duy Triển khai" trước để mở khoá bài này.Đến bài trước

Giới thiệu

Khi bạn build một web app do AI tạo ra trên laptop, nó chạy được là vì Python đã được cài đặt, các dependency đặt đúng chỗ, và biến môi trường được thiết lập vừa đủ. Chuyển ứng dụng đó lên một server, máy của đồng nghiệp, hay nền tảng cloud, và bỗng nhiên không thứ gì chạy đúng cả. Docker giải quyết vấn đề này bằng cách đóng gói ứng dụng của bạn cùng mọi thứ nó cần vào một đơn vị duy nhất có thể mang theo được, gọi là container.

Trong bài học này, bạn sẽ viết một Dockerfile cho một web app Python điển hình, build nó thành một image, và dùng Docker Compose để chạy ứng dụng cùng với các dịch vụ mà nó phụ thuộc (như database hay Redis). Trọng tâm là tính thực tiễn: đến cuối bài, bạn có thể tự tin đóng gói một web app nhỏ do AI tạo ra thành container.

Viết Dockerfile đầu tiên của bạn

Dockerfile là một file văn bản chứa các chỉ thị mà Docker đọc để dựng nên một image. Hãy coi nó như một công thức nấu ăn: mỗi dòng thêm một layer. Đối với một web app do AI tạo ra, thiết lập phổ biến nhất là app FastAPI hoặc Flask được phục vụ bởi Uvicorn.

Dưới đây là một Dockerfile tối thiểu cho một web app Python:

dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Hãy phân tích từng dòng. `FROM python:3.11-slim` bắt đầu từ một image Python chính thức, gọn nhẹ. `WORKDIR /app` đặt thư mục làm việc bên trong container để các lệnh tiếp theo chạy tại đó. `COPY requirements.txt .` chỉ copy file dependency trước, điều này cho phép Docker cache lại bước `pip install` và bỏ qua nó khi chỉ có code của bạn thay đổi. `COPY . .` sau đó mới copy source code của bạn. `EXPOSE 8000` ghi chú cổng mà ứng dụng lắng nghe. `CMD` định nghĩa lệnh chạy khi container khởi động.

Một lỗi thường gặp là copy mọi thứ trước khi cài dependency. Điều đó buộc Docker phải build lại layer `pip install` nặng nề mỗi khi bạn chỉnh sửa một file Python duy nhất. Thứ tự các bước rất quan trọng để đảm bảo tốc độ.

sơ đồ các layer của Docker image khi build Dockerfile ở trên, từ base image python:3.11-slim đến application code

Xây dựng và Chạy Image

Khi đã có Dockerfile, hai lệnh sẽ biến nó thành một container đang chạy. Đầu tiên, build image và gắn tag cho nó bằng một cái tên:

bash
docker build -t my-ai-app:1.0 .

Dấu `.` cho Docker biết nơi tìm Dockerfile (thư mục hiện tại). Cờ `-t` gán tên và tag phiên bản, giúp dễ tham chiếu image sau này. Sau đó chạy nó:

bash
docker run -p 8000:8000 my-ai-app:1.0

Cờ `-p 8000:8000` ánh xạ cổng 8000 trên máy host sang cổng 8000 bên trong container. Nếu không có cờ này,ứng dụng vẫn chạy nhưng bạn không thể truy cập từ trình duyệt. Truy cập `http://localhost:8000` và bạn sẽ thấy ứng dụng phản hồi.

Để xác minh image đã được build đúng cách, liệt kê tất cả các image:

bash
docker images

Để xem các container đang chạy, dùng `docker ps`. Thêm `-a` để bao gồm cả các container đã dừng.

Sử dụng Docker Compose cho các ứng dụng đa dịch vụ

Hầu hết các AI web app không chạy đơn lẻ. Chúng thường cần một cơ sở dữ liệu (PostgreSQL), một bộ nhớ đệm (Redis), hoặc cả hai. Việc quản lý từng thành phần bằng các lệnh `docker run` riêng biệt sẽ nhanh chóng trở nên lộn xộn. Docker Compose cho phép bạn khai báo tất cả các dịch vụ trong một file YAML và khởi chạy chúng cùng nhau.

Tạo một file tên là `docker-compose.yml`:

yaml
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:16
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:

Chú ý cách service `web` tham chiếu đến `db` bằng hostname. Docker Compose tạo một mạng riêng nơi các service liên lạc với nhau qua tên service. Chỉ thị `depends_on` bảo Docker khởi động cơ sở dữ liệu trước web app. Named volume `pgdata` giữ an toàn cho dữ liệu cơ sở dữ liệu ngay cả khi container bị xóa.

Để khởi chạy toàn bộ:

bash
docker compose up --build

Thêm `-d` để chạy ở chế độ nền. Để dừng và xóa các container:

bash
docker compose down

Những lỗi thường gặp và cách tránh

Quên file `.dockerignore` là một thiếu sót phổ biến. Hãy tạo một file `.dockerignore` cùng với Dockerfile của bạn:

bash
echo -e "__pycache__\n.git\n.env\n*.pyc" > .dockerignore

Nếu không có file đó, image của bạn sẽ chứa những file không cần thiết, làm chậm quá trình build và có nguy cơ lộ các bí mật như file `.env` chứa API key.

Một lỗi khác là hardcode bí mật bên trong image. Tuyệt đối không đặt API key hay mật khẩu database trực tiếp trong Dockerfile. Hãy sử dụng biến môi trường hoặc mount file chứa bí mật khi runtime.

Cuối cùng, chạy container với quyền root theo mặc định là rủi ro bảo mật cho môi trường production. Hãy thêm một user không phải root vào Dockerfile khi bạn sẵn sàng triển khai nghiêm túc.

Tóm tắt

Dockerfile mô tả cách đóng gói ứng dụng của bạn thành một image. Docker Compose điều phối nhiều container cùng nhau thông qua một file YAML duy nhất. Đối với một web app được tạo bởi AI, quy trình thông thường là: viết Dockerfile sao chép dependencies trước, build image bằng `docker build`, chạy nó bằng `docker run -p`, và mở rộng sang Compose khi bạn thêm các service như database. Nắm vững bốn lệnh này và một cấu trúc YAML sẽ đưa bạn đến 90% con đường có một ứng dụng container hóa sẵn sàng cho mọi nền tảng cloud.

Luyện tập sau buổi học

Bài kiểm tra cuối bài

Ôn lại kiến thức, thử sức và nhận góp ý cho bài làm.

0/1
Đã trả lời · 0/1
Đóng gói ứng dụng của bạn với Docker