Ngày 21 tháng 5 năm 2023 - Máy tính Bài viết trước “Tìm hiểu về container là gì” đã giới thiệu các khái niệm cơ bản của container. Bài viết này sẽ tiếp tục giới thiệu nền tảng container phổ biến nhất hiện nay là Docker và cách sử dụng cơ bản của nó.
1 Tổng quan về Docker
Docker là một nền tảng container mở giúp phát triển, phân phối và vận hành ứng dụng. Docker cho phép tách biệt ứng dụng khỏi hạ tầng để giao phần mềm nhanh chóng. Với Docker, chúng ta có thể quản lý hạ tầng như cách quản lý ứng dụng. Bằng cách tận dụng Docker để phát hành, kiểm thử và triển khai mã nguồn, chúng ta có thể nâng cao đáng kể hiệu quả trong việc viết mã và vận hành ứng dụng trong môi trường sản xuất.
1.1 Khả năng của nền tảng Docker
Docker cung cấp khả năng đóng gói và chạy ứng dụng trong môi trường container được cô lập nhẹ nhàng. Container rất nhẹ và chứa mọi thứ cần thiết để chạy ứng dụng, do đó không phụ thuộc vào nội dung đã cài đặt trên máy chủ hiện tại. Độ cô lập và bảo mật của Docker cho phép chạy nhiều container cùng lúc trên cùng một máy chủ. Chúng ta cũng có thể chia sẻ container trong công việc và đảm bảo rằng mọi người nhận được container đều hoạt động theo cùng một cách.
Docker cung cấp các công cụ và nền tảng để quản lý vòng đời của container, bao gồm:
- Phát triển ứng dụng và các thành phần hỗ trợ bằng cách sử dụng container.
- Sử dụng container làm đơn vị phân phối và kiểm thử ứng dụng.
- Triển khai ứng dụng dưới dạng container vào môi trường sản xuất, bất kể đó là trung tâm dữ liệu cục bộ, môi trường đám mây hay hybrid cloud.
1.2 Docker có thể làm gì?
-
Giao ứng dụng liên tục và nhanh chóng: Docker cung cấp môi trường chạy ứng dụng chuẩn cho các nhà phát triển, đơn giản hóa chu kỳ phát triển phần mềm. Container rất phù hợp với quy trình tích hợp và triển khai liên tục (CI/CD), đảm bảo giao ứng dụng nhanh chóng và ổn định.
-
Triển khai và mở rộng linh hoạt: Tính di động và nhẹ của Docker giúp quản lý tải công việc một cách động (theo nhu cầu kinh doanh gần như thời gian thực) dễ dàng hơn.
-
Chạy nhiều tải công việc hơn trên cùng một phần cứng: Docker nhẹ và nhanh, tiết kiệm tài nguyên hơn so với máy ảo, cho phép chạy nhiều tải công việc hơn trên cùng một phần cứng.
1.3 Kiến trúc Docker
Docker sử dụng kiến trúc Client-Server (C/S).

Client Docker và Daemon Docker (có trách nhiệm xây dựng, chạy và phân phối container Docker) giao tiếp thông qua REST API trên UNIX sockets hoặc giao diện mạng. Client Docker và Daemon Docker có thể nằm trên cùng một hệ thống hoặc khác hệ thống (Client Docker có thể kết nối với Daemon Docker từ xa). Docker Compose cũng là một loại client Docker, cho phép xử lý ứng dụng bao gồm nhiều container.
-
Daemon Docker: Daemon Docker (
dockerd
) chịu trách nhiệm lắng nghe yêu cầu API Docker và quản lý các đối tượng Docker (image, container, mạng và volume, v.v.). Daemon Docker cũng có thể giao tiếp với các daemon khác để quản lý dịch vụ Docker. -
Client Docker: Client Docker (
docker
) là cách chính để tương tác với Docker. Khi sử dụng các lệnh nhưdocker run
, client Docker sẽ gọi API Docker đến daemondockerd
, và daemondockerd
sẽ xử lý các lệnh này. Client Docker có thể giao tiếp với nhiều daemon. -
Docker Desktop: Docker Desktop là một gói cài tại vin777 đặt toàn diện, bao gồm client Docker, daemon Docker, Docker Compose, Kubernetes và công cụ quản lý chứng chỉ.
-
Docker Registry: Docker Registry dùng để lưu trữ image Docker. Docker Hub là registry mà tất cả mọi người đều có thể sử dụng và là kho lưu trữ mặc định của Docker.
-
Đối tượng Docker: Khi sử dụng Docker, chúng ta chủ yếu làm việc với các đối tượng như image, container, mạng, volume hoặc plugin. Dưới đây sẽ giới thiệu ngắn gọn về image và container.
-
Image: Image Docker là một mẫu chỉ đọc chứa các lệnh để tạo ra container Docker. Thông thường, một image dựa trên một image khác và có thêm một số tùy chỉnh.
-
Container: Container là phiên bản đang chạy của image. Chúng ta có thể tạo, khởi động, dừng, di chuyển hoặc xóa container bằng cách sử dụng client Docker hoặc gọi API Docker. Có thể kết nối mạng cho container, thêm lưu trữ cho container, thậm chí tạo một image mới dựa trên trạng thái hiện tại của container. Mặc định, container được cô lập chặt chẽ với các container khác và máy chủ. Tuy nhiên, mức độ cô lập của mạng và lưu trữ của container có thể được điều chỉnh.
-
Lưu ý bổ sung: Docker được viết bằng ngôn ngữ Go và tận dụng các đặc điểm của nhân Linux. Docker sử dụng công nghệ namespace để cung cấp sự cô lập giữa các container.
2 Cài đặt Docker
Phương pháp cài đặt Docker nhanh chóng và trực tiếp nhất là cài đặt Docker Desktop. Hệ điều hành được sử dụng trong bài viết này là MacOS, hãy tải phiên bản mới nhất của “Docker Desktop for Mac”, double-click và chọn “Accept” để cài đặt.
3 Sử dụng Docker Cơ Bản
3.1 Container hóa ứng dụng
Sau đây, chúng ta sẽ sử dụng một ứng dụng mẫu “To-do List” được viết bằng Node.js để minh họa cách sử dụng Docker.
Trước tiên, hãy clone mã nguồn:
git clone
Tiếp theo, bạn sẽ thấy thư mục getting-started/app
chứa hai thư mục con src
và spec
, cũng như một file package.json
.
getting-started
├─ app
│ ├─ src/
| ├─ spec/
│ └─ package.json
└─ ...
Tạo một file Dockerfile
trong thư mục getting-started/app
và thêm nội dung sau:
# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000
Xây dựng image bằng cách chạy lệnh sau trong thư mục getting-started/app
:
docker build -t getting-started .
Sau khi xây dựng image xong, chạy container bằng lệnh:
docker run -dp 3000:3000 getting-started
Như vậy, bạn có thể truy cập ứng dụng qua trình duyệt.
Ngoài ra, bạn có thể sử dụng lệnh docker ps
để xem trạng thái container, lệnh docker stop
để dừng container và lệnh docker rm
để xóa container đã dừng.
3.2 Đẩy và chia sẻ image
Thử đẩy image lên Docker Hub.
Trước hết, bạn cần đăng ký một tài khoản Docker Hub, ví dụ tên tài khoản của tôi là olzhy.
Tiếp theo, đăng nhập vào Docker Hub bằng lệnh:
docker login
Đổi tên image getting-started
bằng lệnh:
docker tag getting-started olzhy/getting-started
Cuối cùng, đẩy image lên Docker Hub:
docker push olzhy/getting-started
Bây giờ, bất kỳ ai cũng có thể sử dụng image vừa đẩy trên máy có cài Docker:
docker run -dp 3000:3000 olzhy/getting-started
3.3 Lưu trữ dữ liệu bền vững
Ứng dụng “To-do List” hiện tại mất dữ liệu khi khởi động lại vì chưa thực hiện lưu trữ dữ liệu. Dưới đây là cách lưu trữ dữ liệu bằng Volume.
Volume cung cấp khả năng ánh xạ đường dẫn cụ thể của container đến máy chủ.
Ứng dụng “To-do List” sử dụng SQLite và lưu trữ dữ liệu trong file /etc/todos/todo.db
.
Tạo một volume bằng lệnh:
docker volume create todo-db
Chỉ định volume và chạy container:
docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
Sau khi thêm dữ liệu, dù có dừng và xóa container cũ đi thì dữ liệu vẫn tồn tại khi chạy container mới.
Kiểm tra nơi dữ liệu được lưu bằng lệnh:
docker volume inspect todo-db
Ngoài volume, bạn cũng có thể sử dụng Bind Mounts để ánh xạ bất kỳ file hoặc thư mục nào trên máy chủ vào container.
Lệnh chạy container với Bind Mounts:
docker run -dp 3000:3000 --mount type=bind,src=/tmp/todos,target=/etc/todos getting-started
hoặc rút gọn bằng -v
:
docker run -dp 3000:3000 -v /tmp/todos:/etc/todos getting-started
3.4 Ứng dụng đa container
Tạo một container MySQL và kết nối ứng dụng “To-do List” với database này.
Hai container cần giao tiếp qua mạng, trước tiên tạo mạng:
docker network create todo-app
Chạy container MySQL:
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:8.0
Kết nối vào container và kiểm tra database:
docker exec -it <mysql-container-id> mysql -u root -p
Bạn sẽ thấy database todos
đã được tạo.
Khởi động ứng dụng “To-do List”:
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:18-alpine \
sh -c "yarn install && yarn run dev"
Truy cập ứng dụng và thêm vài mục.
Kiểm tra database, bạn sẽ thấy dữ liệu đã được ghi vào bảng:
docker exec -it <mysql-container-id> mysql -p todos
mysql> select * from todo_items;
+--------------------------------------+--------------------+-----------+
| id | name | completed |
+--------------------------------------+--------------------+-----------+
| c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! | 0 |
| 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome! | 0 |
+--------------------------------------+--------------------+-----------+
3.5 Sử dụng Docker Compose
Khởi động nhiều container với các bước phức tạp như tạo mạng, chạy container, phơi cổng và chỉ định biến môi trường có thể được đơn giản hóa bằng Docker Compose.
Tạo file docker-compose.yml
trong thư mục getting-started/app
và thêm nội dung sau:
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
Khởi động container:
docker compose up -d
Xem nhật ký:
docker compose logs -f
Xóa container sau khi hoàn thành:
docker compose down --volumes
3.6 Thực hành tốt khi xây dựng image
- Tận dụng cache layer để tăng tốc độ xây dựng: Mỗi lần một layer thay đổi, các bước sau đó đều phải được xây dựng lại.
Cải thiện Dockerfile
bằng cách:
- Thêm file
.dockerignore
để bỏ qua thư mụcnode_modules
. - Điều chỉnh thứ tự các lệnh để giảm thiểu tái xây dựng.
# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]
- Sử dụng multi-stage builds để giảm kích thước image: Multi-stage builds giúp tách biệt các phụ thuộc trong quá trình xây dựng và trong quá trình vận hành.
Ví dụ với ứng dụng Maven/Tomcat:
# syntax=docker/dockerfile:1
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
Với ứng dụng React:
# syntax=docker/dockerfile:1
FROM node:18 AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
Tóm lại, bài viết đã khám phá cơ bản về Docker, bao gồm khái niệm, khả năng, kiến trúc và cách sử dụng.
[1] Get started | Docker Documentation - docs.docker.com