1. Introduction

Vấn đề: Một dự án sẽ có nhiều người thực hiện trên các thiết bị khác nhau về hệ điều hành và kiến trúc CPU. Làm sao để có thể đồng bộ môi trường?

Conda: quản lý package của python. Tuy nhiên khi chạy dự án thì không chỉ có python mà còn có các framework khác và hệ điều hành khác

Hơn nữa khi chúng ta deploy trên máy chủ (thường là Linux) thì làm sao để đồng bộ giữa máy của dev với máy trên cloud?

Vấn đề đồng bộ giữa Frontend, Backend và Database?

Giải pháp: Đóng gói thành một package bằng Docker.

Vậy trước khi có công nghệ này thì hồi trước chúng ta có các cách xử lý nào?

  1. Chạy tất cả mọi thứ trên cùng một máy. (như chạy tất cả trên local)
  2. Tạo các máy ảo và chạy từng máy ảo trên đó Tuy nhiên cần tài nguyên rất lớn và khó scale.

Apple container: https://github.com/apple/container

Khi chúng ta đã có container rồi thì cần có container runtime

Platform Docker dùng là containerD

Khi deploy trên các nền tảng cloud thì họ cũng cung cấp các container runtime có sẵn.

2. Docker

  • Docker is an open platform for developing, shipping, and running applications.
  • Significantly reduce the delay between writing code and running it in production.

Lợi ích của docker trong quá trình phát triển:

  • Dev A đóng container đẩy qua Dev B và Dev B chỉ cần chạy trên Container runtime chứ không cần set up môi trường lại

Docker Architecture

Có thể thiểu Client là bên gửi yêu cầu (request) để sử dụng dịch vụ do bên Server cung cấp.

Tiêu chíClientServer
Vai tròGửi requestXử lý & trả response
Chủ độngKhông
Chạy ở đâuMáy người dùngMáy chủ
Ví dụBrowserDjango / FastAPI
Docker daemon:

Registry: Lưu trữ các tài nguyên

Installation

CLI (Command Line Interface)giao diện dòng lệnh, cho phép người dùng tương tác với máy tính hoặc hệ thống bằng cách gõ lệnh dạng văn bản, thay vì thao tác bằng chuột và giao diện đồ họa.

Docker Daemon

Nơi quản lý 4 nhóm API chính của Docker

Docker Engine

Container

Khi chúng ta đóng gói xong sản phẩm thì cần Runtime để chạy ứng dụng đó.

Build container

Thường sẽ dùng hệ điều hành Linux, sau đó là cài các thư viện, framework cần thiết lên trên (do Linux nhẹ). Vậy lúc build container chúng ta cũng cần có quy tắc để làm sao cho tối ưu, gọn nhất, chứa được nhiều nhất có thể.

Quá trình đóng gọi được thực hiện trên Docker file

Quy trình cài ở đây giống như quy trình ta cài các thư viện về ở một notebook mới.

Image

Ghost Win: là chúng ta cài win 7, sau đó cài các ứng dụng như Word, Excel,… Sau đó chúng ta save checkpoint đó gọi là ghost win. Nếu sau này cần thì chỉ cài lại sẽ có được trạng thái đó.

Vậy build Docker Image cũng giống vậy.

Vậy docker Container phải nhẹ và độc lập chỉ cần đợi đến nơi để bung ra thành ứng dụng.

Registry

Là nơi phân tán docker image

Networking

Làm sao để kết nối các container với nhau. Ví dụ như một container chứa Frondend và một container chứa Backend

Dùng network

Docker Volumes

Tmpfs: Tạo một vùng nhớ tạm, dùng xong thì xóa Giống RAM Volume: Tạo một vùng nhớ trên ứng dụng Docker Bind volume: Tạm một vùng nhớ trên máy local

Instruction

Instruction cơ bản để cài Docker file

workdir: giống như cd expose: mở port (network) để container có thể giao tiếp với nhau cmd: câu lệnh cuối để start app. Vd: gradio run py

Docker Build

Từ Dockerfile (kịch bản đóng gói) chúng ta đã chạy

docker build -t <name>:<tag> <build context> <name>: tên image <tag>: versioning cho image <build context: vị trí chúng ta build container

Ví dụ:

Ở đây chúng ta đóng gói Folder backend như sau:

  • FROM python:3.11.9-slim: cài đặt Python
  • WORKDIR /src: nơi làm việc là /src
  • COPY ./requirements.txt /src/requirements.txt: Copy file requirements vào folder /src trong docker
  • RUN pip install ...: chạy file requirements.txt đã copy
  • : sau đó là copy file của /app
  • : mở port 8000
  • : chạy server backend trên port 8000

Sau đó quá trình build sẽ diễn ra.

Sau đó vào Docker hoặc Docker extension VScode ta có thể thấy Image đã được build.

Export layer

Tiến trình cài đặt container (dở hàng ra)

Tại sao cần tách ra các layers

  • Tăng tốc quá trình build: không cần build lại những gì đã có

Ví dụ ở đây chỉ thay đổi code thì rõ ràng ta chỉ cần build từ dòng 18 (là copy source code mới) trở đi.

ENV: biến môi trường cần định nghĩa. Với ví dụ trên, lúc này ta có thể truyền lại giá trị mới. Khi chạy docker run -e PORT=9000 -p 9000:9000 backend ta truyền giá trị mới cho PORT, khi đó container sẽ chạy trên port 9000 thay vì 8000 như đã định sẵn.

Secrets

Chúng ta cũng có thể gửi API key ở đây

Multi-stage

Chúng ta có thể chia ra nhiều giai đoạn