Mục tiêu học tập
Hiểu về Containers
Nắm vững khái niệm container, sự khác biệt với virtual machine và vai trò của Linux namespaces trong việc cô lập container.
Linux Namespaces & Cgroups
Hiểu cách namespaces (PID, network, mount, UTS, IPC) và control groups cô lập tài nguyên cho container.
Container Registries
Sử dụng Docker Hub (docker.io), Quay.io và Red Hat Container Catalog để pull và push container images.
Podman & Docker Commands
Thành thạo các lệnh podman/docker: pull, run, ps, stop, rm, rmi, build, exec để quản lý containers.
Containerfile/Dockerfile
Xây dựng container images tùy chỉnh sử dụng Containerfile (Podman) hoặc Dockerfile (Docker) với các chỉ thị FROM, RUN, COPY, CMD.
Rootless Containers
Chạy containers không cần quyền root với Podman, hiểu về user namespace mapping và bảo mật container.
Lý thuyết: Clouds và Containers
1. Container là gì?
Container là một đơn vị phần mềm đóng gói ứng dụng cùng tất cả dependencies của nó. Khác với Virtual Machine, container chia sẻ kernel của host OS nhưng cô lập namespace và filesystem riêng.
Container vs Virtual Machine:
Container
- • Chia sẻ OS kernel của host
- • Khởi động trong vài giây
- • Nhẹ (MB), hiệu năng cao
- • Cô lập qua namespaces
Virtual Machine
- • Có OS riêng, hypervisor riêng
- • Khởi động trong vài phút
- • Nặng (GB), overhead cao
- • Cô lập phần cứng ảo
2. Linux Namespaces
Linux namespaces là nền tảng cho container isolation. Mỗi namespace cô lập một loại tài nguyên hệ thống:
PID Namespace
Container có bảng process riêng. PID 1 trong container là ứng dụng chính (không phải systemd).
Network Namespace
Container có interface eth0 riêng với IP address riêng. Cần port mapping để expose ra ngoài.
Mount Namespace
Container có filesystem riêng, không thấy root filesystem của host. Bind mount để chia sẻ dữ liệu.
User Namespace
UID trong container được map với UID trên host. Cho phép chạy root trong container nhưng không có quyền trên host.
3. Cài đặt Podman và Docker
$ sudo dnf install podman -y
Last metadata expiration check: 0:02:15 ago on Tue 01 Apr 2025.
Dependencies resolved.
Installing: podman-5.2.3-1.fc42.x86_64
Complete!
$ podman --version
podman version 5.2.3
$ sudo dnf install docker -y
$ sudo systemctl start docker
$ sudo systemctl enable docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service
4. Pull và Run Container
# Pull image từ registry
$ sudo podman pull public.ecr.aws/docker/library/fedora:40
40: Pulling from docker/library/fedora
fc4518b6c5f9: Pull complete
Status: Downloaded newer image for public.ecr.aws/docker/library/fedora:40
$ sudo podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
public.ecr.aws/docker/library/fedora 40 b368d29df3b5 2 months ago 226MB
# Chạy shell trong container (-i interactive, -t terminal)
$ sudo podman run -it b368d29df3b5 bash
[root@50bec06ad25f /]# cat /etc/os-release | grep NAME
NAME="Fedora Linux"
[root@50bec06ad25f /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 17:44 pts/0 00:00:00 bash
root 40 1 0 17:45 pts/0 00:00:00 ps -ef
[root@50bec06ad25f /]# exit
# Xem containers đang chạy
$ sudo podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# Xem TẤT CẢ containers (kể cả stopped)
$ sudo podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS
50bec06ad25f b368d29df3b5 bash 1 hour ago Exited (0)
# Xóa container đã dừng
$ sudo podman rm 50bec06ad25f
# Xóa image
$ sudo podman rmi b368d29df3b5
5. Chạy Service Container (vsftpd)
# Chạy vsftpd container với port mapping và volume mount
$ sudo podman run -d \
-p 20:20 -p 21:21 \
-p 21100-21110:21100-21110 \
-v /etc/vsftpd/:/etc/vsftpd/ \
-v /var/ftp/pub:/var/ftp/pub \
--name vsftpd vsftpd
3a5d094dd4b5c7892...
$ sudo podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3a5d094dd4b5 vsftpd:latest /usr/local 9 seconds ago Up 10 seconds ago 0.0.0.0:20-21->20-21/tcp vsftpd
Các options quan trọng:
-d— Detached mode (background)-p HOST:CONTAINER— Port mapping-v HOST:CONTAINER— Volume bind mount--name— Đặt tên container--rm— Tự xóa khi container dừng
6. Xây dựng Container Images
# Containerfile cho vsftpd
FROM
fedora:40LABEL
maintainer="[email protected]"RUN
dnf install -y vsftpd \&& dnf clean all
COPY
vsftpd.conf /etc/vsftpd/vsftpd.confEXPOSE
20 21 21100-21110CMD
["/usr/sbin/vsftpd", "/etc/vsftpd/vsftpd.conf"]$ sudo podman build -t vsftpd:latest .
STEP 1/6: FROM fedora:40
STEP 2/6: LABEL maintainer="[email protected]"
STEP 3/6: RUN dnf install -y vsftpd && dnf clean all
STEP 4/6: COPY vsftpd.conf /etc/vsftpd/vsftpd.conf
STEP 5/6: EXPOSE 20 21 21100-21110
STEP 6/6: CMD ["/usr/sbin/vsftpd", "/etc/vsftpd/vsftpd.conf"]
Successfully tagged localhost/vsftpd:latest
$ sudo podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/vsftpd latest 487d0db26098 5 seconds ago 208 MB
Lab Thực Hành
Triển khai web server Nginx trong container Podman với volume mount và port forwarding trên Fedora Linux.
Cài đặt Podman
Cài đặt Podman trên hệ thống Fedora/RHEL:
$ sudo dnf install podman -y
$ podman --version
podman version 5.2.3
Pull Nginx Image
Tải Nginx image từ Docker Hub:
$ sudo podman pull docker.io/library/nginx:latest
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
Copying blob sha256:abc123... done
Status: Downloaded newer image for docker.io/library/nginx:latest
Tạo thư mục web content
Tạo thư mục trên host để chứa nội dung web:
$ mkdir -p ~/webroot
$ echo "<h1>Hello from Podman Container!</h1>" > ~/webroot/index.html
Chạy Nginx Container
Chạy Nginx với port mapping 8080→80 và volume mount:
$ sudo podman run -d \
--name mynginx \
-p 8080:80 \
-v ~/webroot:/usr/share/nginx/html:ro \
nginx:latest
a7f4d8b1c2e9...
$ sudo podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7f4d8b1c2e9 nginx:latest nginx -g 3 seconds ago Up 2 secs 0.0.0.0:8080->80/tcp mynginx
Kiểm tra và mở firewall
Kiểm tra web server và mở port trên firewall:
$ curl http://localhost:8080
<h1>Hello from Podman Container!</h1>
$ sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
success
$ sudo firewall-cmd --reload
success
Tạo Custom Image với Containerfile
Build image tùy chỉnh từ Containerfile:
FROM
nginx:latestCOPY
webroot/ /usr/share/nginx/html/EXPOSE
80$ sudo podman build -t my-nginx:v1.0 .
Successfully tagged localhost/my-nginx:v1.0
Dọn dẹp Containers và Images
Dừng, xóa container và image:
$ sudo podman stop mynginx
mynginx
$ sudo podman rm mynginx
a7f4d8b1c2e9...
$ sudo podman rmi nginx:latest my-nginx:v1.0
Untagged: docker.io/library/nginx:latest
Deleted: sha256:abc123...
Câu hỏi ôn tập
Container khác Virtual Machine như thế nào?
Linux namespace nào cho phép container có PID riêng?
Lệnh nào dùng để xem tất cả containers (kể cả đã dừng)?
podman ps --all hoặc podman ps -a. Không có --all, chỉ hiện containers đang chạy. Tương tự với docker ps -a.
Sự khác biệt giữa Podman và Docker là gì?
Giải thích tùy chọn -p 8080:80 trong lệnh podman run?
-p HOST_PORT:CONTAINER_PORT — Map port 8080 của host đến port 80 của container. Khi truy cập http://host:8080, traffic được chuyển đến container port 80. Mặc định container ports không được expose ra ngoài host.
Container registry là gì? Cho ví dụ các registry phổ biến.
podman pull <registry>/image:tag để tải image.
Chỉ thị FROM trong Containerfile có ý nghĩa gì?
FROM image:tag chỉ định base image để xây dựng. Ví dụ FROM fedora:40 dùng Fedora 40 làm nền. Mọi lệnh RUN, COPY sau đó được thực hiện trên base image này. Có thể dùng FROM scratch để tạo image từ đầu.
Volume bind mount trong container là gì và tại sao quan trọng?
-v /host/path:/container/path) gắn thư mục host vào container. Quan trọng vì container là ephemeral (dữ liệu mất khi xóa container). Bind mount cho phép: (1) persistent data storage, (2) chia sẻ config files từ host, (3) inject code vào container mà không cần rebuild image.