Contents
Giới thiệu
Docker đã trở thành một công cụ quan trọng trong việc đóng gói và triển khai ứng dụng. Ubuntu 24.04 LTS (tên mã “Noble Numbat”) cung cấp nền tảng ổn định để chạy Docker cho cả mục đích học tập, phát triển lẫn triển khai production. Bài hướng dẫn này sẽ giúp bạn quản trị hệ thống Docker trên Ubuntu 24.04 từ A đến Z – bao gồm các thao tác quản lý container, image, volume, network; cách viết Dockerfile và docker-compose; thiết lập bảo mật cơ bản và những cách thự hành tốt (best practices) trong quản trị Docker.
Tổng quan các nội dung chính:
-
Quản lý container Docker: tạo, chạy, dừng, xóa container; xem log và thực thi lệnh trong container.
-
Quản lý image Docker: tải image (pull), xây dựng image từ Dockerfile (build), gắn thẻ (tag), xóa (remove), xem thông tin chi tiết (inspect).
-
Quản lý volume và network: tạo, gắn, liệt kê, xóa volumes và networks.
-
Hướng dẫn viết Dockerfile để tạo image tùy chỉnh.
-
Sử dụng file cấu hình docker-compose.yml để triển khai ứng dụng nhiều container.
-
Thiết lập bảo mật Docker cơ bản: thêm user vào nhóm
docker, giới hạn quyền truy cập, cấu hình tường lửa UFW bảo vệ Docker daemon và cổng container. -
Best practices trong quản trị Docker: tối ưu kích cỡ image, dọn dẹp tài nguyên không dùng, sao lưu volumes, cấu hình logging, và đặt tên cho các tài nguyên Docker một cách hợp lý.
Hãy cùng bắt đầu từ những bước cơ bản nhất.
Cài đặt Docker trên Ubuntu 24.04
Trước khi quản trị Docker, chúng ta cần cài đặt Docker Engine trên hệ thống Ubuntu 24.04. Bạn có thể cài Docker từ kho mặc định của Ubuntu bằng lệnh apt install docker.io, nhưng để có phiên bản Docker mới nhất, nên cài từ Docker chính thức. Dưới đây là tóm tắt các bước cài đặt Docker từ repository chính thức của Docker:
-
Cập nhật hệ thống và cài đặt gói phụ thuộc:
(Đảm bảo có
curlvà các chứng chỉ cần thiết cho kho Docker)
-
Thêm khóa GPG chính thức của Docker và kho phần mềm Docker:
Lệnh trên thêm kho Docker cho bản Ubuntu hiện tại (sử dụng mã phiên bản phân phối tự động). Sau đó cập nhật lại danh sách gói.

-
Cài đặt Docker Engine và các thành phần liên quan:
Gói
docker-celà Docker Engine,docker-ce-clilà công cụ dòng lệnh,containerd.iolà container runtime,docker-buildx-plugingiúp xây dựng image đa nền tảng, vàdocker-compose-plugincung cấp lệnhdocker compose(thay thế chodocker-composetruyền thống).
-
Kích hoạt Docker và kiểm tra dịch vụ: Sau khi cài đặt, Docker daemon thường tự khởi động. Kiểm tra trạng thái dịch vụ Docker bằng lệnh:
hoặc dùng lệnh sau:
để đảm bảo Docker đang chạy (active).

-
Kiểm tra Docker với container mẫu: Chạy container thử nghiệm
hello-world:Nếu Docker cài đặt thành công, lệnh trên sẽ tải image hello-world từ Docker Hub và chạy nó. Kết quả là một thông báo “Hello from Docker” được in ra, xác nhận mọi thứ hoạt động đúng.
(Lưu ý: bạn có thể cần dùng
sudotrước các lệnhdockernếu chưa thêm người dùng vào nhóm docker. Phần tiếp theo sẽ hướng dẫn cấu hình để chạy Docker không cần sudo.)
Thêm người dùng vào nhóm Docker (chạy Docker không cần sudo)
Mặc định, Docker daemon trên Linux tạo socket /var/run/docker.sock chỉ cho phép user root truy cập. Do đó, để chạy lệnh docker không cần sudo, chúng ta có thể thêm người dùng vào nhóm Unix đặc biệt có tên docker. Trên Ubuntu, nhóm docker có thể đã được tạo sẵn khi cài Docker; nếu chưa, chúng ta sẽ tạo nhóm này và thêm user:
-
Bước 1: Tạo nhóm
docker(nếu nhóm chưa tồn tại): -
Bước 2: Add user hiện tại vào nhóm
docker: -
Bước 3: Đăng xuất và đăng nhập lại (hoặc khởi động lại server) để thay đổi có hiệu lực. Sau đó chạy lệnh
docker run hello-worldkhông dùng sudo để xác minh. Nếu thành công, có nghĩa là user đã có quyền dùng Docker daemon mà không cần quyền root.
⚠️ Cảnh báo bảo mật: Cần lưu ý rằng nhóm docker tương đương với quyền root trên máy (vì có thể truy cập Docker socket). Việc thêm user vào nhóm này đồng nghĩa user đó có thể thực thi mọi lệnh root thông qua Docker daemon. Do đó chỉ thêm những người dùng tin cậy vào nhóm docker. Nếu cần mức an toàn cao hơn, Docker cung cấp chế độ “rootless” (chạy daemon Docker với user thường) hoặc các biện pháp hạn chế khác, nhưng đó là nội dung nâng cao ngoài phạm vi bài viết này.
Sau khi cài đặt xong và cấu hình quyền, chúng ta sẽ đi vào chi tiết quản trị Docker.

Quản lý Container Docker
Container là thực thể đang chạy được tạo ra từ image Docker. Dưới đây là những thao tác quản trị container cơ bản nhất: tạo và chạy container, liệt kê container đang chạy, dừng và khởi động lại, xem log, thực thi lệnh trong container, và xóa container.
✅ Kéo image ubuntu:24.04 từ Docker Hub
Sau vài giây bạn sẽ thấy:
Image đã được tải về local.

Tạo và chạy container (docker run, docker create)
Lệnh thông dụng nhất để tạo và chạy container là docker run. Cú pháp tổng quát:
Khi chạy docker run, Docker sẽ tạo một container mới từ image chỉ định, sau đó khởi chạy container đó (tương đương kết hợp các lệnh docker create + docker start). Ví dụ:
-
Chạy một container Ubuntu ở chế độ tương tác có shell Bash:
Tùy chọn
-itgộp của-i(interactive – giữ STDIN mở) và-t(allocate TTY) cho phép ta điều khiển shell bên trong container trực tiếp từ terminal. Cờ--name test-ubuntuđể đặt tên dễ nhớ cho container thay vì Docker tự sinh tên ngẫu nhiên.Mẹo: Việc đặt tên rõ ràng cho container giúp quản lý dễ dàng hơn. Hãy dùng các tên mô tả chức năng (ví dụ:
web-server,db-mysql) thay vì tên chung chung. Điều này đặc biệt hữu ích khi có nhiều container chạy song song.
-
Chạy một container Nginx và xuất cổng ra máy chủ:
Cờ
-d(detached) giúp container chạy nền (không chiếm terminal hiện tại).-p 8080:80ánh xạ cổng 80 trong container ra cổng 8080 trên server host. Sau lệnh này, truy cậphttp://<địa_chỉ_host>:8080sẽ thấy trang mặc định của Nginx.
Sau khi chạy lệnh docker run, chúng ta có thể kiểm tra container đang chạy bằng lệnh:
-
docker pshoặcdocker container ls: liệt kê các container đang chạy. Thêm-a(docker ps -a) để liệt kê tất cả container (kể cả container đã dừng chạy).


Dừng, khởi động và tạm dừng container
Để dừng container đang chạy, dùng lệnh:
Lệnh trên sẽ gửi tín hiệu SIGTERM (mặc định) để yêu cầu ứng dụng trong container thoát an toàn, sau một khoảng thời gian (mặc định 10 giây) nếu chưa dừng sẽ gửi SIGKILL. Bạn có thể điều chỉnh thời gian chờ bằng tùy chọn -t.
Ví dụ: Lệnh docker stop webserver sẽ dừng container tên webserver (ví dụ Nginx ở trên).
Để khởi động lại container đã dừng, dùng lệnh:
Container sẽ chạy lại với cùng cấu hình (image, cổng, volume…) như khi tạo.
Để khởi động lại nhanh (restart) container (dừng rồi chạy lại trong một lệnh):
Lệnh này hữu ích khi muốn reload nhanh ứng dụng trong container.
Tạm dừng container: Docker cung cấp lệnh docker pause <container> để tạm ngưng tất cả tiến trình trong container (dùng tín hiệu SIGSTOP), và docker unpause <container> để tiếp tục (SIGCONT). Tính năng này ít dùng hơn, thường chỉ áp dụng khi cần freeze container tạm thời.

Xem log của container (docker logs)
Docker lưu trữ log (dòng xuất ra STDOUT và STDERR) của container để hỗ trợ cho việc debug. Để xem log, dùng lệnh:
Mặc định, docker logs sẽ hiển thị toàn bộ log container đã lưu (từ khi container bắt đầu chạy). Một số tùy chọn phổ biến:
-
-fhoặc--follow: theo dõi log trực tiếp (giốngtail -f), có nghĩa là in thêm log mới trong thời gian thực. -
--tail <n>: chỉ xem n dòng log cuối. -
-t: hiển thị timestamp cho mỗi dòng log.
Log container chính là những gì ứng dụng trong container ghi ra STDOUT/STDERR. Theo mặc định, lệnh docker logs sẽ hiển thị các thông tin container ghi ra STDOUT và STDERR, tương tự như khi bạn chạy lệnh đó trực tiếp trong terminal. Điều này có nghĩa là ứng dụng trong container cần ghi log ra console (STDOUT/ERR) thì docker logs mới thấy được. Nhiều ứng dụng (ví dụ Nginx, Apache) ban đầu ghi log vào file trong container, nhưng các image chính thức thường được cấu hình lại để chuyển log ra STDOUT/STDERR (vd: symlink file log tới /dev/stdout) nhằm tương thích với docker logs.
Ví dụ:
Thực thi lệnh bên trong container (docker exec)
Khi container đang chạy, bạn có thể “chui vào” bên trong hoặc thực thi thêm lệnh trong container thông qua docker exec. Lệnh này cho phép chạy một tiến trình mới bên trong container đang chạy (với đầy đủ môi trường, filesystem của container đó).
Cú pháp:
Một số ví dụ thường gặp:
-
Mở shell tương tác trong container:
Lệnh trên mở một phiên bash trong container tên webserver. Cờ
-it(interactive + TTY) giúp bạn điều khiển bash như một terminal thông thường. -
Thực thi nhanh một lệnh trong container:
Lệnh này sẽ gửi lệnh reload (Nginx) bên trong container webserver. Không dùng
-i -tnghĩa là lệnh sẽ thực thi không có giao diện tương tác và kết thúc sau khi chạy xong.
Lưu ý: docker exec chỉ hoạt động khi container đang chạy (container phải ở trạng thái Up). Nếu container đã tắt, bạn không thể exec vào; thay vào đó có thể cân nhắc docker run một container mới hoặc docker start lại container.

Xóa container (docker rm)
Khi một container không còn cần thiết, bạn có thể xóa nó bằng lệnh:
Lệnh này yêu cầu container phải ở trạng thái dừng (Stopped). Nếu container đang chạy, bạn cần dừng nó trước (docker stop) hoặc sử dụng docker rm -f (force remove) để Docker gửi SIGKILL và xóa container ngay.
-
Xóa container kèm các volume ẩn (anonymous volumes): sử dụng thêm cờ
-vhoặc--volumesđể xóa luôn các volume liên kết ẩn danh với container đó. Lưu ý: các volume được đặt tên (named volumes) sẽ không bị xóa ngay cả khi dùng-v.
Ví dụ: docker rm -v webserver sẽ xóa container webserver và các volume không tên gắn kèm nó (nếu có). Volume nào được mount có tên riêng sẽ được giữ lại để tránh mất dữ liệu.
-
Xóa nhiều container cùng lúc: bạn có thể chỉ định nhiều tên/ID sau
docker rm, hoặc dùng sub-command tiện ích:Lệnh trên sẽ xóa tất cả container đã dừng trong hệ thống, giải phóng không gian. Hãy cẩn thận khi dùng lệnh này để tránh xóa nhầm container cần thiết.
-
Tạo container tự động xóa sau khi kết thúc: Nếu bạn chỉ chạy container tạm thời, có thể sử dụng tùy chọn
--rmtrongdocker run. Khi container kết thúc, Docker sẽ tự xóa container đó (và các volume ẩn danh gắn kèm) mà không cầndocker rmthủ công.
Tóm lại, quản lý vòng đời container gồm tạo/khởi chạy (run), tạm dừng/tái sử dụng (stop/start/restart), và kết thúc vòng đời (rm). Nắm vững các lệnh này sẽ giúp bạn chủ động kiểm soát ứng dụng chạy dưới dạng container.

Quản lý Image Docker
Image Docker là khuôn mẫu để tạo ra container. Việc quản trị image bao gồm: tải image có sẵn từ registry (Docker Hub hoặc registry nội bộ), tự xây dựng image mới từ Dockerfile, gắn thẻ (tag) cho image, xem thông tin chi tiết và xóa các image không còn cần thiết.
Tải image từ Docker Hub (docker pull)
Docker Hub là registry mặc định của Docker, chứa tất cả các images chính thức (official) và images do người dùng khắp nơi đóng góp. Để tải một image từ Docker Hub về máy, sử dụng lệnh:
-
<image_name>có thể bao gồm cả tên tài khoản (namespace) nếu là image tùy chỉnh (ví dụ:myuser/myimage). Với image chính thức, bạn chỉ cần tên (ví dụ:ubuntu,nginx); Docker tự hiểu namespace ngầm định làlibrary/. -
<tag>chỉ định nhãn phiên bản của image (ví dụ:ubuntu:24.04). Nếu bỏ tag, Docker mặc định dùng:latest.
Ví dụ:
Lệnh trên sẽ tải về phiên bản mới nhất của image Ubuntu 24.04 từ Docker Hub. Nếu đã có sẵn image này local nhưng không phải phiên bản mới nhất, Docker sẽ kiểm tra và cập nhật.
Bạn có thể xem danh sách image đã tải về (local images) bằng lệnh docker images (tương đương docker image ls). Mỗi image sẽ hiển thị REPOSITORY, TAG, IMAGE ID, SIZE. Lưu ý rằng một image ID có thể có nhiều tag khác nhau trỏ tới (ví dụ ubuntu:24.04 và ubuntu:latest có thể là cùng IMAGE ID nếu 24.04 hiện là phiên bản stable mới nhất).
Một số mẹo với docker pull:
-
Để tải tất cả các tag của một repository (thường không cần thiết và tốn dung lượng), có thể dùng
docker pull -a <image_name>(--all-tags). -
Có thể tải image từ registry khác bằng cách chỉ rõ địa chỉ registry trong tên image. Ví dụ:
docker pull myregistry.local:5000/test-image:1.0sẽ kéo image từ registry nội bộ chạy trên cổng 5000. -
Sau khi kéo image, nếu không còn cần thiết nữa, có thể xóa bằng
docker rmi(xem phần xóa image bên dưới).
Xây dựng image từ Dockerfile (docker build)
Một trong những sức mạnh của Docker là khả năng tự tạo image tùy chỉnh bằng cách viết Dockerfile. Dockerfile là tệp văn bản khai báo các bước cài đặt để “đóng gói” ứng dụng vào image.
Mục tiêu:
-
Tạo ứng dụng Flask đơn giản hiển thị “Hello from Docker Flask!”.
-
Viết
requirements.txtchứa thư viện cần cài (Flask). -
Tạo Dockerfile để build image.
-
Chạy container trên cổng
5000.
Cấu trúc thư mục
Giả sử bạn tạo một thư mục tên flask-docker-demo:
✍️ 1. Tạo file requirements.txt
Bạn có thể thêm các thư viện khác nếu muốn mở rộng sau này.
✍️ 2. Tạo file app.py
host='0.0.0.0'là bắt buộc khi chạy Flask trong container, để server chấp nhận các kết nối từ bên ngoài vào.
3. Dockerfile
Ví dụ Dockerfile cơ bản: Tạo image chạy ứng dụng web Flask (Python):
Trong Dockerfile trên:
-
FROMchọn base image (ở đây dùng Python Alpine để có dung lượng nhỏ). -
WORKDIRthiết lập thư mục hiện hành bên trong image. -
COPY(hoặcADD) sao chép file từ máy host vào image. -
RUNthực thi lệnh trong quá trình build (cài đặt phụ thuộc). -
EXPOSEchỉ mang tính chất tài liệu, khai báo cổng ứng dụng sẽ sử dụng (5000). Docker sẽ không tự mở cổng này trừ khi bạn dùng-pkhi chạy container, nhưng EXPOSE giúp người đọc hiểu container nghe ở cổng nào. -
CMDchỉ định lệnh mặc định khi container chạy (có thể bị override bởi tham sốdocker run).

Xây dựng image: Dùng lệnh docker build trong thư mục chứa Dockerfile:
Trong đó, -t my-flask-app:1.0 gán tên và tag cho image mới (tên tùy chọn, thường bao gồm cả tag phiên bản). Dấu . (dấu chấm) cuối lệnh chỉ ngữ cảnh build (build context) là thư mục hiện tại – Docker sẽ gửi toàn bộ nội dung thư mục này (trừ file/thư mục được liệt kê trong .dockerignore nếu có) vào cho Docker daemon để build.
Khi chạy, Docker build sẽ tuần tự thực hiện các chỉ dẫn trong Dockerfile để tạo ra image. Mỗi lệnh (FROM, RUN, COPY, …) tạo thành một layer trong image. Docker tận dụng cơ chế cache: nếu bạn chạy lại build mà không thay đổi Dockerfile hoặc nội dung liên quan, các bước trước đó có thể dùng lại từ cache để tăng tốc độ build.

Sử dụng image vừa tạo: Sau khi build thành công, bạn sẽ thấy image my-flask-app:1.0 trong docker images. Bây giờ có thể tạo container từ image này:
Container sẽ chạy ứng dụng Flask trên cổng 5000, được ánh xạ ra ngoài. (Bạn có thể truy cập thử http://localhost:5000 để xem kết quả).

Best Practices khi viết Dockerfile: Để tối ưu image và tránh lỗi:
-
Chọn base image phù hợp: Luôn bắt đầu FROM một image phù hợp nhu cầu (ví dụ Alpine Linux để giảm kích thước, hoặc bản chính thức ngôn ngữ runtime bạn cần). Tránh dùng base image quá nặng nếu không cần.
-
Sử dụng nhiều stage (multi-stage build) nếu cần build/compile rồi đóng gói sản phẩm cuối. Multi-stage giúp loại bỏ các phần không cần thiết (dev dependencies) khỏi image cuối, giảm đáng kể dung lượng.
-
Tận dụng caching: Sắp xếp các lệnh sao cho những phần ít thay đổi (cài đặt hệ thống, cài thư viện) nằm trước, phần thường xuyên thay đổi (copy mã nguồn ứng dụng) nằm sau, để Docker cache được các layer đầu. Ví dụ: cài đặt dependencies trước rồi mới COPY code, thay vì copy code trước sẽ làm invalid cache mỗi khi code thay đổi.
-
Dọn dẹp trong Dockerfile: Khi cài đặt phần mềm (apt, npm, pip…), hãy xóa cache hoặc file tạm không cần thiết sau khi cài. Ví dụ:
apt-get install -y ... && apt-get clean && rm -rf /var/lib/apt/lists/*để image sạch gọn gàng hơn. -
Sử dụng
.dockerignore: Tương tự.gitignore, file.dockerignoretrong context build giúp loại trừ những file/thư mục không cần thiết gửi vào context (ví dụ thư mụcnode_moduleslocal, file cấu hình bí mật,…) – tránh làm tăng kích thước context và image. -
Đảm bảo lệnh CMD/ENTRYPOINT hợp lý: CMD nên để chạy ứng dụng chính. Nếu cần container luôn chạy một tiến trình chính diện (PID 1) và xử lý tín hiệu tốt, có thể dùng câu lệnh dạng
exec(vd:CMD ["python", "app.py"]như trên). Tránh dùngCMD myapp &(chạy nền thủ công) dẫn đến container thoát ngay.
Việc xây dựng image tùy chỉnh cho phép đóng gói ứng dụng kèm môi trường chạy một cách tái lập. Sau khi có image, chúng ta cũng nên biết cách quản lý chúng: gắn tag, push lên registry, hay xóa khi không dùng.

Gắn thẻ (tag) cho image
Tag một image tương tự như đặt bí danh thêm cho image đó. Mỗi image có định danh duy nhất (IMAGE ID), và có thể có nhiều tag trỏ tới cùng ID (ví dụ ubuntu:24.04 và ubuntu:latest có thể là một). Khi build bạn đã thấy tùy chọn -t name:tag để gán tag. Nếu quên gán tag khi build hoặc muốn gán thêm tag mới, dùng lệnh:
Ví dụ:
Lệnh này tạo tag myrepo/my-flask-app:latest trỏ đến image ID của my-flask-app:1.0 hiện có. Việc này thường dùng trước khi push image lên một registry nào đó (ví dụ đổi tên bao gồm namespace của bạn, hoặc thêm tag phiên bản). Lưu ý Docker tag không tạo bản sao image, nó chỉ thêm một tham chiếu tên mới tới image hiện có, do đó không tốn thêm dung lượng.
Bạn có thể kiểm tra các tag bằng docker images sau khi gắn tag.

Xem thông tin chi tiết image (docker inspect)
Để xem metadata của một image (hoặc container), Docker cung cấp lệnh docker inspect. Lệnh này trả về một cấu trúc JSON chứa rất nhiều thông tin, ví dụ: ID, kích thước, cấu hình (ENV, CMD mặc định, các port expose, volumes mặc định…), lịch sử layer, v.v.
Cú pháp:
Để inspect image, bạn có thể dùng tên:tag của image hoặc IMAGE ID. Ví dụ:
Kết quả sẽ là JSON (rất dài). Bạn có thể kết hợp với công cụ jq hoặc sử dụng --format để trích xuất thông tin cụ thể, ví dụ:
(sẽ in ra các biến môi trường mặc định trong image Ubuntu 24.04).
Một số thông tin hữu ích từ docker inspect image:
-
RepoTags: những tên:tag gắn với image. -
Size: Dung lượng image. -
Config: thông tin cấu hình mặc định (entrypoint, cmd, env, exposed ports, volumes…). -
RootFSvàGraphDriver: thông tin về các layer, thường dùng cho mục đích debug layer.
Trong ngữ cảnh sử dụng hàng ngày, docker inspect thường dùng để kiểm tra nhanh cấu hình container (ví dụ container đang mount những volume nào, IP nội bộ container, thông tin network…).

Xóa image không dùng (docker rmi)
Khi image trở nên không cần thiết (ví dụ image test cũ, image tạm), chúng ta có thể xóa để giải phóng dung lượng bằng lệnh:
Một số lưu ý:
-
Nếu có container (đang chạy hoặc đã dừng) đang sử dụng image đó, bạn phải xóa container trước khi xóa image, nếu không lệnh sẽ báo lỗi “image is being used by running/stopped container”.

-
Bạn có thể xóa nhiều image cùng lúc liệt kê trong một lệnh, hoặc dùng các subcommand:
-
docker image prune: xóa tất cả image dangling (không có tag nào gắn, thường là layer trung gian thừa). -
docker image prune -a: xóa tất cả image không được container nào sử dụng. Cẩn thận với tùy chọn-avì nó sẽ xóa cả image có tag nếu chúng không gắn với container nào – dễ dẫn đến phải tải lại nếu cần dùng lại.
-
-
docker system prune: lệnh “dọn dẹp” tổng quát, sẽ xóa các container đã dừng, các image không dùng, các mạng không dùng, v.v. Đây là lệnh mạnh tay, nhưng tiện để làm sạch hệ thống Docker trong môi trường dev. Mặc địnhdocker system prunekhông xóa volumes trừ khi thêm cờ--volumes.
Ví dụ:
Sau khi xóa, dùng docker images để kiểm tra lại danh sách image còn lại.
Tóm lại, việc quản lý image đòi hỏi bạn theo dõi những image nào đang có, phiên bản nào, dọn dẹp image thừa và gắn tag rõ ràng. Trong môi trường production, bạn cũng nên có quy trình cập nhật image thường xuyên (pull image mới khi có bản vá bảo mật) hoặc dùng digest để cố định phiên bản (pin image by digest) nếu muốn đảm bảo tính bất biến.

Quản lý Volume và Network trong Docker
Volumes và Networks là hai thành phần quan trọng giúp container có thể lưu trữ dữ liệu lâu bền và giao tiếp với nhau hoặc với thế giới bên ngoài.
-
Volume cho phép lưu trữ dữ liệu trên host (bên ngoài container), dữ liệu này không bị mất khi container xóa. Thích hợp cho database, lưu trữ file cho người dùng, logs, v.v.
-
Network Docker (bridge network) tạo môi trường mạng ảo cho các container giao tiếp nội bộ với nhau, hoặc gắn container vào mạng host, mạng overlay (nếu dùng Swarm), v.v. Hiểu và quản lý network giúp cấu hình cổng an toàn và linh hoạt khi có nhiều container.
Quản lý Volume Docker
Tạo volume: Để tạo một volume mới, dùng lệnh:
Nếu không đặt tên, Docker sẽ tạo tên ngẫu nhiên. Volume sẽ được Docker lưu trữ tại một đường dẫn trên host (thường dưới /var/lib/docker/volumes/). Ví dụ:
Lệnh trên tạo volume tên mydata. Bạn có thể xem danh sách volume bằng lệnh docker volume ls.
Sử dụng volume khi chạy container: Có hai cách gắn volume vào container:
-
Dùng option
-v(đơn giản và quen thuộc) hoặc -
Dùng cú pháp mới
--mount(cú pháp rõ ràng hơn, khuyến nghị dùng trong các script phức tạp).
Ví dụ dùng -v:
✅ Kéo image mariadb:latest từ Docker Hub
docker pull mariadb:latest
Lệnh trên chạy container Mariadb thư mục dữ liệu mặc định /var/lib/mysql bên trong container sẽ được lưu ra volume mydata trên host. Nếu mydata không tồn tại Docker sẽ tự tạo volume mới (trường hợp này ta đã tạo sẵn rồi).
Cú pháp -v <volume_name>:<container_path> sẽ mount volume vào container tại đường dẫn chỉ định. Dữ liệu ghi tại <container_path> trong container sẽ đi vào volume, tồn tại độc lập với vòng đời container. Nếu container bị xóa, dữ liệu volume sẽ vẫn còn để gắn vào container khác nếu muốn.
Bạn cũng có thể mount bind mount (thư mục/file host) thay vì volume, nhưng volume có ưu điểm quản lý dễ hơn và tách biệt môi trường host.
Kiểm tra lại volume có dữ liệu chưa:

Liệt kê và kiểm tra volume:
-
docker volume ls– liệt kê các volume hiện có. -
docker volume inspect <volume_name>– xem chi tiết volume (ví dụ đường dẫn host, driver, dung lượng sử dụng, v.v).

Xóa volume: Để xóa một volume, đảm bảo không có container nào đang sử dụng nó, sau đó dùng:
Nếu volume đang được gắn vào container (kể cả container đã dừng), bạn phải xóa container trước hoặc dùng docker rm -v khi xóa container để volume trở thành “dangling” rồi mới docker volume rm.
Để xóa tất cả volume không còn container sử dụng, dùng lệnh:
(sẽ có cảnh báo và yêu cầu xác nhận trước khi xóa).
Backup và phục hồi volume: Volume thường dùng để lưu dữ liệu quan trọng, do đó nhu cầu backup là phổ biến. Cách đơn giản: chạy một container tạm để tar (nén) nội dung volume, ví dụ:
Giải thích từng phần:
| Thành phần | Ý nghĩa |
|---|---|
docker run |
Tạo và chạy một container tạm thời |
--rm |
Xóa container tạm sau khi thực thi xong |
--volumes-from db |
Gắn tất cả volume của container db vào container mới |
-v $(pwd):/backup |
Mount thư mục hiện tại trên host vào /backup trong container |
ubuntu |
Dùng image Ubuntu để chạy các lệnh Linux |
tar cvf /backup/mydata_backup.tar /var/lib/mysql |
Lệnh nén dữ liệu MySQL trong volume (ở /var/lib/mysql) thành file .tar lưu vào /backup (tức thư mục hiện tại trên host) |

Tương tự, để khôi phục dữ liệu database từ bản backup, bạn có thể chạy container tạm, mount volume trống và mount thư mục chứa file backup, rồi giải nén tar vào volume.
Ví dụ về khôi phục database:
Bước 1: Giả sử sau khi container cũ đã bị xóa hoặc không còn sử dụng volume đó, chúng ta
Dừng container đang dùng volume và Xóa container để release volume sử dụng 2 lệnh sau:
docker stop db
docker rm db
Tiếp theo để khôi phục dữ liệu mysql của container vào volume, chỉ cần chạy lệnh:
--strip 1giúp loại bỏ thư mục gốc/var/lib/mysqltrong tar.
Bước 2: Chạy lại container Mariadb để sử dụng volume
mydatađã được khôi phục:Lần này, Mariadb sẽ khởi động và sử dụng dữ liệu đã khôi phục thay vì tạo mới.
Tạo lại container MariaDB như sau:
Kiểm tra container đã hoạt động:
→ Sẽ thấy container
dbđang Up.Đăng nhập vào database container:
Sau đó xem databases:
Việc backup/restore này có thể kịch bản hóa hoặc sử dụng các công cụ hỗ trợ, nhưng về bản chất vẫn là mount volume và sao chép dữ liệu ra/vào.

Khi nào nên dùng volume?: Nếu dữ liệu bạn cần persist (không muốn mất khi container xóa), hãy dùng volume (hoặc bind mount nếu cần truy cập trực tiếp từ host). Docker volume có lợi thế quản lý độc lập, dễ backup, chia sẻ giữa container, và hiệu năng tốt hơn ghi vào layer của container. Tránh lưu dữ liệu quan trọng chỉ bên trong container (layer container) vì khi container xóa sẽ mất toàn bộ dữ liệu.
Quản lý Network Docker
Docker Engine khi cài đặt sẽ tạo sẵn một network mặc định kiểu cầu nối (bridge) tên là bridge (còn gọi là docker0). Mặc định, container tạo bằng docker run nếu không chỉ định network sẽ nối vào network bridge này. Các container trong cùng network bridge có thể giao tiếp với nhau qua IP nội bộ.
Tuy nhiên, để có cách ly tốt hơn hoặc tạo nhóm container riêng, bạn có thể tạo mạng người dùng (user-defined network).
Tạo network mới:
Mặc định lệnh trên tạo network driver bridge. Ví dụ:
sẽ tạo một bridge network tên myapp-net. Mỗi network do người dùng tạo sẽ có một dải IP riêng (Docker tự chọn, thường /16 hoặc /24). Container trên cùng network có thể liên lạc với nhau bằng tên container (Docker DNS nội bộ).
Chạy container gắn vào network tùy chỉnh: Dùng option --network khi docker run:
Hai container trên cùng nối vào myapp-net. Bây giờ, container web có thể truy cập mariadb thông qua hostname db (vì Docker DNS sẽ phân giải tên container sang IP nội bộ). Việc này rất tiện khi triển khai các dịch vụ cần liên kết với nhau.
Kết nối network cho container đang chạy: Nếu bạn quên hoặc muốn thay đổi, có lệnh:
Lưu ý container có thể gắn vào nhiều network cùng lúc (đa số trường hợp không cần, trừ phi bạn có network làm DMZ, network backend riêng…). Container có thể ngắt khỏi network nếu cần tách biệt.
Liệt kê và xem chi tiết network:
-
docker network ls– liệt kê các network (sẽ thấy các network mặc định nhưbridge,host,nonevà các network do người dùng tạo). -
docker network inspect <network_name>– xem thông tin network (phạm vi, driver, các container đang gắn vào network, dải IP, gateway…).
Xóa network:
Chỉ xóa được network không có container nào đang kết nối. Nếu network đang có container (kể cả container đã dừng nhưng vẫn gắn), bạn phải disconnect hoặc xóa container trước.
Network mặc định đặc biệt:
-
bridge: Mạng cầu nối mặc định. Tất cả container không chỉ định network sẽ vào đây. Các Containers trong bridge có thể giao tiếp với nhau qua IP, nhưng không có DNS name resolution tự động (bạn phải link hoặc tự tìm IP qua inspect). -
host: Network host – container dùng chung network stack với host (không tách biệt cổng). Thích hợp khi bạn muốn container truy cập tài nguyên mạng host trực tiếp hoặc chạy dịch vụ cần hiệu xuất mạng cao. -
none: Container không nối mạng gì (network stack biệt lập, không có kết nối ra ngoài). Dùng cho container tuyệt đối không cần mạng để tăng bảo mật.
Port mapping (cổng): Dù container ở network nào, để người dùng bên ngoài truy cập dịch vụ trong container, bạn cần xuất cổng (publish port) ra host bằng -p. Với network bridge, Docker sử dụng NAT để ánh xạ cổng host->container. Nếu container ở network host thì container dùng trực tiếp cổng host (không cần -p). Còn network khác (overlay trong Swarm) thì phức tạp hơn (có load-balancing…), chúng ta không nói đến trong phạm vi bài viết này.
Tóm lại: sử dụng network user-defined giúp bạn dàn xếp kiến trúc các container của mình dễ hơn, và Docker Compose thường tận dụng tính năng này tự động (mỗi ứng dụng Compose có network riêng). Hãy tạo các network riêng cho từng nhóm dịch vụ microservice, để chúng liên lạc nội bộ, và chỉ expose/publish những cổng cần thiết ra ngoài.
Ví dụ cụ thể:
Chú ý: Trước khi thực hiện ví dụ này bạn hãy đảm bảo cần phải stop và xóa tất cả các containers mà có thể bạn đã tạo từ phần trước (ví dụ như đã xóa container Mariadb tên là db, đã tạo trong phần trước).
Chạy các lệnh CLI sau:
db sẽ chạy MariaDB trên port nội bộ 3306, và các container trong cùng network có thể truy cập qua tên db- Cổng
8081của máy chủ (host) sẽ ánh xạ đến cổng80của containerphpadmin. Truy cập từ localhost hoặc http://ip của host:8080 từ PC của bạn sẽ truy cập được phpadmin.
- Cổng
8080của máy chủ (host) sẽ ánh xạ đến cổng80của containernginx. Truy cập từ localhost hoặc http://ip của host:8080 từ PC của bạn sẽ truy cập được nginx.

Sau khi chạy xong các lệnh trên, chúng ta có thể truy cập từ máy tính vào phpadmin và nginx container qua các cổng 8080 và 8081:


Triển khai multi-container với Docker Compose
Khi ứng dụng của bạn gồm nhiều containers cần phối hợp với nhau (ví dụ web server + database + cache), việc chạy từng lệnh docker run và quản lý thủ công sẽ rất phức tạp. Docker Compose giúp định nghĩa và chạy nhiều containers một cách thuận tiện bằng cách sử dụng một file cấu hình YAML (thường là docker-compose.yml hoặc compose.yaml).
Viết file docker-compose.yml
Một file Compose liệt kê các services (mỗi service tương ứng một container hoặc một nhóm containers cùng cấu hình). Bạn định nghĩa image hoặc build, các cổng, volume, networks, biến môi trường… trong file này.
Ví dụ một docker-compose.yml đơn giản cho ứng dụng web + Redis cache:
Giải thích ví dụ trên:
-
Service web: Sẽ build image từ Dockerfile hiện tại (giả sử Dockerfile thiết lập ứng dụng Flask trên cổng 5000 như ví dụ trước). Nó publish cổng 5000 ra host 8000 để người dùng truy cập.
depends_onkhai báo phụ thuộc – web đợi redis tạo xong (Compose đảm bảo thứ tự khởi động, nhưng không đảm bảo redis đã “sẵn sàng” về ứng dụng, điều này ứng dụng phải tự xử lý hoặc dùng healthcheck). Service web và redis mặc định sẽ cùng nằm trong một network do Compose tạo (thường tên theo thư mục + “_default”). -
Service redis: Sử dụng image có sẵn từ Docker Hub, không mở cổng ra ngoài (vì web sẽ truy cập nội bộ). Redis sẽ khả dụng trong mạng nội bộ với hostname
redis(trùng tên service).
Compose file trên định nghĩa hai services web và redis. Web build từ Dockerfile, redis kéo image public. Compose sẽ tự tạo một network bridge riêng, web và redis nằm trong đó, do đó web có thể truy cập redis qua tên host “redis”. Cổng 8000:5000 xuất ra để người dùng từ ngoài truy cập vào web.
Bạn có thể mở rộng Compose file với các phần như volumes (nếu cần database lưu trữ), environment (biến môi trường), restart policy, healthcheck, v.v. Compose phiên bản 3.x rất linh hoạt.

Chạy ứng dụng bằng Docker Compose
Với Docker Compose plugin (đã cài ở bước đầu hoặc cài riêng), bạn có thể dùng lệnh docker compose (hoặc docker-compose nếu dùng bản cài độc lập trước đây) để quản lý.
Trong thư mục chứa docker-compose.yml, chạy, trước khi chạy lệnh dưới bạn phải đảm bảo file docker-compose.yml trong cùng thư mục với các files là app.py và dockerfile mà chúng ta đã tạo trong phần “Xây dựng image từ Docker file” ở trên, để nó tìm file Dockerfile ngay trong thư mục hiện tại :
Lệnh này sẽ:
-
Tạo network mặc định (nếu chưa có).
-
Build image cho service nào cần build.
-
Kéo image từ registry cho service nào cần pull.
-
Tạo và khởi động các container theo định nghĩa, trong đúng network, gắn volume (nếu có), ánh xạ cổng…
-
Nếu dùng
-d, các container sẽ chạy dưới dạng detached (nền). Bỏ-dđể xem log trực tiếp.
Kết quả, với ví dụ trên, Compose sẽ tạo container myfolder_web_1 và myfolder_redis_1 (tên ghép từ thưc mục + service + số), cổng 8000 trên host được mở, và hai container chạy nền. Bạn có thể kiểm tra bằng docker ps sẽ thấy chúng.

Kiểm tra ứng dụng: Mở trình duyệt truy cập http://localhost:8000 hoặc IP của server host sẽ thấy ứng dụng web chạy (ví dụ Flask “Hello from Docker Flask” tăng dần số lần truy cập nếu có sử dụng Redis đếm).

Xem log và quản lý:
-
Dùng
docker compose logs -fđể xem log tất cả các container trong Compose app (có prefix tên service). -
Dùng
docker compose psđể liệt kê container trong Compose app. -
Dùng
docker compose downđể dừng và xóa tất cả container, network (mặc địnhdownsẽ không xóa volume đặt tên, trừ khi thêm-v). -
Dùng
docker compose restart <service>để khởi động lại service cụ thể.
Compose giúp bạn quản lý multi-container dễ dàng hơn nhiều. Bạn cũng có thể có nhiều file Compose (ví dụ docker-compose.prod.yml) cho cấu hình production và dùng override. Compose phiên bản mới (v2+) còn cho phép scale (nhiều container cho một service) bằng docker compose up --scale web=3 chẳng hạn.
Lưu ý: Docker Compose plugin hiện tích hợp sẵn vào Docker CLI (docker compose ... thay vì lệnh docker-compose ngày xưa). Chức năng tương tự, có bổ sung một số tính năng mới.
Compose rất hữu ích trong phát triển, kiểm thử, cũng như triển khai các dịch vụ nhỏ lẻ. Với các hệ thống lớn cần clustering, bạn có thể cần Docker Swarm hoặc Kubernetes, nhưng trong phạm vi bài viết này không đề cập đến.

Thiết lập bảo mật cơ bản cho Docker
Chạy container cũng cần quan tâm tới bảo mật, cả ở cấp độ host lẫn bên trong container. Dưới đây là một số cấu hình bảo mật cơ bản khi quản trị Docker trên Ubuntu:
Quyền truy cập Docker daemon và tài nguyên
-
Hạn chế người dùng có quyền Docker: Như đã đề cập, thành viên nhóm
dockercó quyền như root trên host. Vì vậy, chỉ thêm những users thật sự cần thiết vào nhóm này. Kiểm soát chặt chẽ quyền SSH/shell tới máy chủ Docker, tránh để kẻ lạ có tài khoản rồi dùng Docker chiếm quyền. -
Chạy container với quyền hạn chế (nếu có thể): Mặc định, tiến trình trong container chạy với user root (trừ khi image có user mặc định khác, hoặc được chỉ định
USERtrong Dockerfile). Nếu ứng dụng cho phép, bạn nên tạo user thường trong image và dùngUSERđể container chạy không phải root, giảm rủi ro nếu container bị xâm nhập thì kẻ tấn công cũng không có quyền root trên container (dù vẫn có khả năng thoát sandbox nếu có lỗ hổng). Ngoài ra có thể sử dụng User Namespaces để map root trong container thành user thường trên host, nhưng cấu hình này phức tạp hơn một chút. -
Không chạy Docker daemon mở cổng TCP nếu không cần: Docker daemon có thể cấu hình để nghe trên cổng TCP (REST API), nhưng không nên mở trừ khi bạn có nhu cầu thật sự (ví dụ chạy Docker từ xa). Nếu mở, hãy bắt buộc dùng TLS và firewall chặn IP không mong muốn. Mặc định Docker Ubuntu dùng Unix socket (docker.sock) an toàn hơn.
Cấu hình tường lửa UFW cho Docker
Vấn đề Docker bypass UFW: Trên Ubuntu, nhiều người dùng kích hoạt UFW (tường lửa đơn giản) để chặn/cho phép cổng. Tuy nhiên, Docker có cơ chế iptables riêng: khi publish cổng (-p), Docker sẽ thêm rule iptables trực tiếp để DNAT traffic vào container, và các rule UFW trên chuỗi INPUT/OUTPUT có thể bị bỏ qua do Docker xử lý ở chuỗi nat trước. Kết quả là cổng container có thể truy cập từ ngoài dù UFW có chặn – điều này là hành vi mặc định Docker chứ không phải lỗi. Do đó, nếu bạn chỉ dựa vào UFW mặc định, container của bạn có thể bị phơi ra internet ngoài ý muốn.
Có một số giải pháp bảo vệ Docker với UFW:
-
Giới hạn cổng khi publish: Cách đơn giản và an toàn nhất là ngay từ khi chạy container, hãy chỉ định rõ IP lắng nghe. Ví dụ thay vì
-p 8080:80(mở cho mọi IP), dùng-p 127.0.0.1:8080:80để chỉ cho phép truy cập từ localhost. Khi đó, cổng 8080 container không lộ ra ngoài internet, chỉ máy chủ host truy cập được. Tương tự trong docker-compose, có thể viếtports: - "127.0.0.1:8080:80". -
Dùng UFW-docker script: Có một tiện ích cộng đồng tên là ufw-docker giúp bổ sung các rule UFW phù hợp để chặn cổng Docker. Bạn cài script này và chạy
ufw-docker install, nó sẽ tự động cấu hình UFW (chỉnh trong/etc/ufw/after.rules) để Docker không bypass các rule UFW. Đây là cách khá thuận tiện nếu muốn tiếp tục dùng UFW như bình thường. -
Tắt iptables trong Docker và tự cấu hình firewall: Cách này nâng cao hơn – thêm
"iptables": falsetrong/etc/docker/daemon.jsonđể Docker ngừng can thiệp iptables, khi đó UFW kiểm soát hoàn toàn. Tuy nhiên bạn phải tự thêm các rule để cho phép traffic container nếu cần (ví dụ cho phép forward, cho phép cổng,…). Đồng thời Docker khi đó cũng mất khả năng tự NAT mạng, bạn phải thêm rule forward thích hợp. Chỉ làm điều này nếu bạn hiểu rõ iptables/UFW, và thường kết hợp với kỹ thuật ở trên (bind cổng cục bộ, cho UFW rule forward). -
Sử dụng chuỗi DOCKER-USER: Docker tạo chain
DOCKER-USERmà nó sẽ nhảy qua trước khi cho phép traffic vào container. Bạn có thể thêm các iptables rule vào chain này để lọc. Ví dụ, để chặn mọi IP ngoài trừ một IP truy cập container, bạn có thể thêm rule DROP vàoDOCKER-USERnhư tài liệu Docker gợi ý. Tuy nhiên việc can thiệp iptables thủ công hơi phức tạp; nếu dùng UFW, bạn có thể thêm rule vào/etc/ufw/after.rulestrong chainDOCKER-USER. Cách này tương tự dùng ufw-docker script nhưng tự làm thủ công.
Tóm lại: trong môi trường production, hãy hạn chế tối đa port container lộ ra. Chỉ mở những gì cần và dùng firewall để giới hạn IP. Ví dụ, nếu chạy database trong container và chỉ ứng dụng web trên cùng server cần truy cập, không publish cổng DB ra 0.0.0.0; hoặc nếu có, hãy firewall chặn toàn bộ từ ngoài.
Các thông số bảo mật khác
-
Cập nhật image thường xuyên: Luôn kéo các bản cập nhật image (đặc biệt image chính thức) để nhận bản vá bảo mật. Nếu dùng image custom, thường xuyên rebuild base image mới (ví dụ base Ubuntu, Alpine).
-
Sử dụng user namespace, Seccomp, AppArmor: Docker hỗ trợ tích hợp cấu hình Seccomp profile (mặc định Docker dùng một profile khá chặt chẽ giảm bề mặt tấn công kernel), AppArmor profile (trên Ubuntu có sẵn profile Docker). Bạn nên giữ các cấu hình mặc định này trừ khi có lý do đặc biệt cần bỏ.
-
Không chạy container –privileged trừ khi cần thiết:
--privilegedcấp quyền rất cao cho container (toàn quyền host devices, có thể ảnh hưởng host). Tương tự, hạn chế gắn volume nhạy cảm của host vào container (như/var/run/docker.sockhay thư mục hệ thống) nếu không thực sự cần, vì có thể bị xâm nhập. -
Đặt resource limit: Dùng các tùy chọn
-m(memory),--cpusđể giới hạn tài nguyên container, tránh container bị tấn công dùng hết tài nguyên host. Đây cũng là một khía cạnh bảo mật (tránh tấn công DoS từ bên trong container).
Cuối cùng, luôn coi container chỉ là một process cô lập – không phải máy ảo hoàn toàn. Vì vậy, áp dụng nguyên tắc bảo mật cơ bản: hạn chế quyền, cập nhật thường xuyên, và giám sát.
Best Practices trong Quản trị Docker
Phần này tóm tắt những thông lệ tốt giúp bạn quản trị Docker hiệu quả và sạch sẽ hơn, đặc biệt hữu ích trong môi trường production:
Tối ưu hóa Image Docker
-
Giữ image nhỏ gọn: Image dung lượng nhỏ sẽ tải nhanh hơn, khởi tạo container nhanh hơn và giảm thiểu bề mặt tấn công. Sử dụng base image tối giản (như Alpine, Distroless khi có thể) hoặc xóa các phần không cần thiết. Ví dụ, nếu chỉ cần chạy binary Go, dùng image scratch hoặc distroless thay vì Ubuntu đầy đủ.
-
Multi-stage build: Tận dụng multi-stage trong Dockerfile để loại bỏ các build tool, file tạm. Ví dụ build ứng dụng trong stage đầu, stage sau chỉ copy file nhị phân kết quả.
-
Không lưu bí mật trong image: Các secret như mật khẩu, khóa API không nên bake cứng trong Dockerfile. Sử dụng biến môi trường hoặc secret store bên ngoài (Docker Swarm Secrets, Kubernetes Secrets, …) khi chạy container.
-
Cập nhật image định kỳ: Kiểm tra các image base để rebuild nếu có bản mới, đảm bảo nhận bản vá bảo mật. Có thể dùng các tool phụ trợ (như Docker Scout) để scan lỗ hổng trong image.
Dọn dẹp tài nguyên Docker định kỳ
Khi làm việc lâu dài, Docker host có thể tích tụ nhiều container stopped, image cũ, dangling volumes/networks. Hãy định kỳ dọn dẹp để tránh lãng phí ổ đĩa:
-
Sử dụng
docker system pruneđể xóa tất cả đối tượng không sử dụng (container dừng, image không gắn tag hoặc không gắn với container, network không có container). Có thể chạy lệnh này hàng tuần/tháng tùy tần suất sử dụng. Thêm--volumesnếu muốn xóa cả volumes không dùng (cẩn thận với dữ liệu!). -
Xóa log container cũ: Docker lưu log container trong
json-filetheo mặc định. Qua thời gian log có thể chiếm nhiều dung lượng. Bạn có thể thiết lập log rotation cho Docker daemon – ví dụ giới hạn mỗi container log 50MB và rotate 3 file. Cách làm: chỉnh cấu hình daemon hoặc dùng--log-optkhi chạy container. (Tham khảo tài liệu Docker logging để bậtmax-sizevàmax-filecho driver json-file). -
Hạn chế container dư thừa: Thỉnh thoảng kiểm tra
docker ps -axem có container nào Exited lâu ngày không, dùngdocker rmxóa bớt. Tương tự,docker volume ls -f dangling=truexem có volumes “mồ côi” không.
Sao lưu dữ liệu quan trọng
Như đã trình bày ở phần volumes, đừng quên backup dữ liệu trong volumes quan trọng (CSDL, file upload, v.v). Có thể dùng các job cron chạy lệnh tar volume định kỳ, hoặc sử dụng giải pháp backup trên chính ứng dụng (ví dụ MySQL container có thể dump data ra file rồi backup file đó).
Ngoài ra, backup cấu hình Docker (như docker-compose.yml, Dockerfile, v.v) bằng Git hoặc tài liệu, để khi cần có thể phục hồi môi trường nhanh chóng.
Quản lý log và giám sát
Logging: Docker cung cấp log mặc định, nhưng trong production, bạn nên chuyển log sang một hệ thống tập trung:
-
Có thể sử dụng các logging driver như
syslog,fluentd,gelfđể gửi log container tới server tập trung. -
Hoặc chạy các container log forwarder (ví dụ EFK stack: Elasticsearch + Fluentd + Kibana) để thu thập log.
-
Ít nhất, hãy bật log rotation cho driver
json-fileđể tránh đầy đĩa do log.
Giám sát: Sử dụng các tool giám sát container (cAdvisor, Prometheus + Grafana) để theo dõi tài nguyên container, phát hiện sớm nếu container dùng quá nhiều CPU, RAM hoặc bị restart liên tục do lỗi.
Đặt tên và gắn nhãn cho tài nguyên
Khi số lượng container, image tăng, việc đặt tên và gắn nhãn hợp lý giúp quản trị dễ dàng:
-
Container name: đặt theo chức năng, môi trường. VD:
web-prod,db-stage,redis-cache… thay vì để tên mặc định. Tên có thể bao gồm thành phần môi trường (prod/dev) nếu chạy chung một host để phân biệt. -
Image tag: không nên dùng tag
latesttrong production – hãy dùng tag phiên bản rõ ràng (v1.4.2chẳng hạn) để triển khai có kiểm soát. “latest” có thể trỏ tới image khác sau mỗi lần pull gây khó kiểm soát phiên bản. -
Docker labels: Docker cho phép gắn label (cặp key-value) cho container và image (
--labelkhi docker run/build). Sử dụng label để lưu thông tin như chủ sở hữu, phiên bản git, modul… sẽ hữu ích khi tích hợp với các hệ thống quản lý sau này.
Triển khai an toàn và hiệu quả
-
Sử dụng docker-compose hoặc orchestrator: Đối với nhiều container, nên dùng Compose (như hướng dẫn trên) hoặc các công cụ dàn xếp (Swarm, Kubernetes) thay vì chạy tay từng cái. Điều này đảm bảo tính nhất quán và dễ quản lý, nâng cấp.
-
Kiểm tra cấu hình trước khi lên production: Ví dụ, liệu bạn đã giới hạn bộ nhớ container chưa? Đã cấu hình restart policy hợp lý chưa? Trong Docker Compose có thể đặt
restart: alwayscho container quan trọng để Docker tự khởi động lại nếu container lỗi hoặc khi host reboot. -
Phân quyền truy cập Docker host: Nếu có nhiều người trong nhóm cùng quản trị Docker host, cân nhắc dùng Docker Context và Docker Bench for Security để audit, cũng như hạn chế dùng chung user root.
Tóm lại, quản trị Docker hiệu quả đòi hỏi kết hợp cả kỹ thuật (lệnh, cấu hình) và quy tắc quản lý (quy trình cập nhật, backup, giám sát). Hãy luôn cập nhật kiến thức Docker vì công nghệ container liên tục phát triển. Hi vọng hướng dẫn từ A đến Z này giúp bạn nắm vững nền tảng để tự tin triển khai Docker trên Ubuntu 24.04, cho dù bạn đang học tập, phát triển ứng dụng, hay vận hành hệ thống trong môi trường sản xuất!
Chúc bạn thành công với Docker!
#DevOps #SysAdmin #Containerization #DockerTutorial #DockerGuide#Docker #Ubuntu2404 #DockerOnUbuntu #DockerAdmin #LinuxServer#LearnDocker #ITTraining #LinuxForBeginners #DockerFromAToZ#OpenSource #CloudComputing #ITCommunity #TechGuide #ServerManagement





