Tăng cường độ linh hoạt với Conda và Docker

Sau nhiều lần thử nghiệm sử dụng Conda với Docker trong một dự án AI thì mình đã tìm ra cách làm hiệu quả nhất. Bài viết này sẽ chia sẻ những đúc kết của mình với minh họa bằng một đoạn code Python có ứng dụng OpenCV.

Gần đây, mình đã có cơ hội làm việc trong một dự án AI, hầu hết những AI component trong dự án đều được viết bằng ngôn ngữ Python và dùng Conda làm hệ thống package manager. Những component này được yêu cầu xây dựng thành Docker image để đảm bảo tính linh động. Vậy nên mình đã thử tìm hiểu về việc sử dụng Conda với Docker, sau nhiều lần thử nghiệm thì cũng đã tìm ra cách làm hiệu quả nhất.

Trong dự án, mình đã tạo Docker image cho nhiều component khác nhau. Nhìn chung, các component này làm những việc như:

  • Tải ảnh (dạng nhị phân) từ queue service (Nats Streaming)
  • Chuyển ảnh thành dạng phù hợp và nhận diện vật thể có trong ảnh (sử dụng TensorFlow Serving)
  • Xử lí đầu ra (output) và lưu dữ liệu vào Database (PostgresDB)

Hệ thống có thể hoạt động bằng việc sử dụng CPU hoặc GPU (nếu có).

Trong bài viết này, mình muốn chia sẻ cùng các bạn cách sử dụng Docker với Conda, được minh họa bằng một đoạn mã Python đơn giản có ứng dụng OpenCV. Tiếp theo là hướng dẫn từng bước một để có thể tạo Dockerfile cho dự án sử dụng Conda.

Tổng quan Docker và Conda

Ngày nay, Docker không còn là từ khóa xa lạ với các bạn lập trình viên. Docker đang ngày càng trở nên thịnh hành với vai trò là nền tảng xây dựng container (containerization platform) dùng trong phát triển và triển khai hệ thống. Rất nhiều nền tảng đám mây hỗ trợ Docker như Azure, AWS, GCP… Chúng ta có thể thảo luận về Docker trên nền tảng đám mây trong một bài viết khác.

Docker là một nền tảng mở, là công cụ thông dụng cho phép chúng xây dựng, phát triển và triển khai hệ thống một cách nhanh chóng và đơn giản qua việc sử dụng container. Sử dụng Docker đem đến nhiều lợi ích như tính linh động, tính cô lập (isolation) và khả năng mở rộng (scalable). Nếu bạn muốn tìm hiểu về Docker thì có thể xem qua các tài liệu bên dưới:

Conda là hệ thống quản lí gói độc lập nền tảng (platform-independent package manager) rất phổ biến với những người có chuyên môn về phân tích dữ liệu và khoa học máy tính. Nếu bạn là một Python newbie và gặp khó khăn trong việc thiết lập môi trường cho nhiều dự án, Conda có thể là một sự lựa chọn tốt cho bạn.

Conda là hệ thống quản lí gói mã nguồn mở (open-source package) giúp chúng ta tạo và quản lí nhiều môi trường riêng biệt cho nhiều ứng dụng khác nhau. Conda cung cấp khả năng tạo “môi trường ảo” (virtual environment), nên chúng ta có thể tránh được các xung đột phiên bản thư viện (library version) thường thấy trong các dự án Python. Bạn có thể tìm hiểu thêm về Conda tại link này.

Thử tạo dự án bằng cách sử dụng Conda với Docker

Bước 1: Chuẩn bị

Trong dự án này, chúng ta sẽ chuẩn bị những tập tin như bên dưới:

- Python script đơn giản trong file “run.py” thực thi việc grayscale một bức ảnh và hiển thị kết quả. Chúng ta sẽ sử dụng OpenCV trong đoạn script này. Chúng ta cũng sẽ sử dụng một bức ảnh “sample.jpg” để chạy thử.

import cv2 
  
# The second argument is zero specifies that 
# image is to be read in grayscale mode. 
img = cv2.imread('sample.jpg', 0)   

cv2.imshow('Grayscale', img) 
cv2.waitKey(3000)
  
cv2.destroyAllWindows() 

- Tập tin môi trường conda “environment.yml” được sử dụng để tạo môi trường Conda và những thư viện cần thiết (dependencies)

name: my_env
channels:
  - miniconda
  - conda-forge
  - defaults
dependencies:
  - pip=20.0.2=py37_1
  - pip:
    - opencv-python==4.2.0.32

- Tập tin Docker “Dockerfile” được dùng để tạo Docker image.

FROM continuumio/miniconda:latest

WORKDIR /home/docker_conda_template

COPY . .

# Create conda environment
RUN conda env create -f environment.yml

# Activate conda environment
ENV PATH /opt/conda/envs/my_env/bin:$PATH
RUN /bin/bash -c "source activate my_env"

# Run python script
CMD ["python", "run.py"]

Bây giờ hãy cùng xem qua tập tin Docker:

  • 3 dòng đầu tiên, chúng ta khai báo image gốc và workdir, sau đó sao chép nội dung từ thư mục mục tiêu vào image (như những file docker thường thấy)
  • Tiếp theo, chúng ta tạo môi trường conda mới từ tập tin “environment.yml” (như câu lệnh chúng ta dùng để tạo môi trường conda mới trên máy local)
  • Tiếp theo, chúng ta sẽ kích hoạt môi trường conda (activate conda environment) bằng việc sử dụng lệnh RUN. Sử dụng RUN sẽ thực thi lệnh kích hoạt môi trường conda trên image hiện thời và giữ lại kết quả (commit the results). Điều đó sẽ giúp những câu lệnh kế tiếp được thực thi trên môi trường Conda đã được kích hoạt.
  • Cuối cùng, thực thi đoạn python script bằng cách sử dụng lệnh CMD.

Bước 2: Thực thi

Tạo docker image bằng cách sử dụng câu lệnh:

docker build -f Dockerfile -t <image_name> .

(Có thể mất một vài phút tùy theo các dependencies chúng ta cấu hình)

Chạy Docker image bằng câu lệnh:

xhost +
sudo docker run --rm --net=host --ipc=host -e DISPLAY=$DISPLAY <image_name>

Vì chúng ta cần hiển thị hình ảnh từ Docker container, nên cần cấu hình thêm cho lệnh docker run.

xhost + : cấp quyền truy cập X server (để hiển thị hình ảnh)

Dưới đây là một vài chú thích:

--rm: Tự động xóa bỏ container sau khi thoát

--net: Kết nối container vào mạng lưới network

--net=host cho phép container có thể dùng port trên máy local

--ipc: Chế độ IPC được sử dụng

--ipc=host cho phép máy local truy cập vào vùng nhớ được chia sẻ của container

-e: Thiết đặt biến môi trường. Trong câu lệnh trên, chúng ta sẽ đặt biến môi trường DISPLAY cho container giống với giá trị của biến môi trường DISPLAY trên máy local.

Tóm lại, câu lệnh cho phép container truy cập vào X server trên máy local để hiển thị kết quả. Nếu bạn muốn tìm hiểu thêm về cấu hình cho lệnh “run” thì có thể đọc bài viết này.

Sau đó, chúng ta có thể xem kết quả hiển thị:

Sử dụng Conda với Docker trong dự án AI: Vấn đề và cách giải quyết

Trong phần trên, bạn đã có đủ “nguyên liệu” để tự tạo Docker với Conda cho mình. Tuy nhiên, để có thể tìm được cách làm hiệu quả nhất thì bản thân mình cũng đã thử đi thử lại nhiều lần với nhiều cách khác nhau. Trong quá trình thử nghiệm đó, mình đã có những trải nghiệm như bên dưới, hy vọng sẽ giúp ích cho bạn.

Tốn nhiều thời gian để tạo docker image

Vì tạo một môi trường Conda hoàn toàn mới cần cài rất nhiều thư viện, đặc biệt khi bạn sử dụng những thư viện nặng nề, việc phải tạo lại docker image nhiều lần trong quá trình phát triển ứng dụng sẽ tốn rất nhiều thời gian. Để tránh việc này, chúng ta có thể chia Dockerfile thành 2 phần.

Trong phần đầu, chúng ta sẽ xây dựng docker image từ image gốc, sao chép tập tin environment.yml, và tạo môi trường Conda. Chúng ta sẽ gọi image này là “base Conda image”

Trong phần sau, chúng ta sẽ xây dựng docker image từ base Conda image, sao chép source code và những nội dung cần thiết khác vào image và gọi những câu lệnh cần thiết còn lại.

Ví dụ nhưng trong dự án bên trên, chúng ta có thể chia Dockerfile thành 2 phần như bên dưới:

Phần A tạo base Conda image:

FROM continuumio/miniconda:latest

WORKDIR /home/docker_conda_template

COPY ./environment.yml .

RUN conda env create -f environment.yml

ENV PATH /opt/conda/envs/my_env/bin:$PATH

RUN /bin/bash -c "source activate my_env"

Phần B tạo image cho ứng dụng:

FROM <base_conda_image_name>

WORKDIR /home/docker_conda_template

COPY . .

CMD ["python", "run.py"]

Từ lúc này, mỗi khi cần phải cập nhật source code, chúng ta chỉ cần tạo lại image cho ứng dụng bằng cách sử dụng tập tin Docker thứ 2. Chúng ta không cần phải thực thi lại toàn bộ quá trình từ đầu để tạo một môi trường Conda mới.

Logging

Sử dụng câu lệnh bên dưới để chạy tập tin python trên môi trường conda cũng có thể giúp chúng ta dùng Conda trong Docker. Tuy nhiên chúng ta sẽ không thấy log của ứng dụng trên màn hình.

ENTRYPOINT ["conda", "run", "-n", " my_env", "python", "run.py"]

Thay vào đó, kích hoạt môi trường Conda bằng lệnh RUN và chạy Python script sau đó (như trong tập tin mẫu) sẽ có thể in log của ứng dụng khi docker container thực thi.

Thông qua bài viết, mình hy vọng bạn đã có đủ những điều mình cần để sử dụng Conda với Docker. Với Docker, việc phát triển và triển khai có thể nhanh chóng, hiệu quả và linh hoạt hơn. Nếu bạn đang làm trong một dự án AI, hy vọng nội dung bài viết này có thể giúp ích cho hành trình của bạn.

Atekco - Home for Authentic Technical Consultants