hoatranlab.io.vn Zalo: 0917516878 Hotline: 0917516878 [email protected]
HoaTranLab Logo HoaTranLab
Linux Bible 11th Edition • Chapter 27

Shifting to Clouds and Containers

Khám phá công nghệ container với Podman/Docker, Linux namespaces, container registries và cách xây dựng container images cho môi trường cloud hiện đại.

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

Terminal - Cài đặt Podman (Fedora/RHEL)

$ 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

Terminal - Cài đặt Docker

$ 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

Terminal - Pull và chạy Fedora 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

Terminal - Quản lý containers

# 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)

Terminal - Chạy FTP server trong container

# 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 / Dockerfile

# Containerfile cho vsftpd

FROM

fedora:40

LABEL

maintainer="[email protected]"

RUN

dnf install -y vsftpd \

&& dnf clean all

COPY

vsftpd.conf /etc/vsftpd/vsftpd.conf

EXPOSE

20 21 21100-21110

CMD

["/usr/sbin/vsftpd", "/etc/vsftpd/vsftpd.conf"]
Terminal - Build image

$ 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.

1

Cài đặt Podman

Cài đặt Podman trên hệ thống Fedora/RHEL:

Terminal

$ sudo dnf install podman -y

$ podman --version

podman version 5.2.3

2

Pull Nginx Image

Tải Nginx image từ Docker Hub:

Terminal

$ 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

3

Tạo thư mục web content

Tạo thư mục trên host để chứa nội dung web:

Terminal

$ mkdir -p ~/webroot

$ echo "<h1>Hello from Podman Container!</h1>" > ~/webroot/index.html

4

Chạy Nginx Container

Chạy Nginx với port mapping 8080→80 và volume mount:

Terminal

$ 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

5

Kiểm tra và mở firewall

Kiểm tra web server và mở port trên firewall:

Terminal

$ 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

6

Tạo Custom Image với Containerfile

Build image tùy chỉnh từ Containerfile:

Containerfile

FROM

nginx:latest

COPY

webroot/ /usr/share/nginx/html/

EXPOSE

80
Terminal

$ sudo podman build -t my-nginx:v1.0 .

Successfully tagged localhost/my-nginx:v1.0

7

Dọn dẹp Containers và Images

Dừng, xóa container và image:

Terminal

$ 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

1

Container khác Virtual Machine như thế nào?

Container chia sẻ kernel của host OS, khởi động trong vài giây, nhẹ (MB). VM có OS riêng, hypervisor riêng, khởi động trong vài phút, nặng (GB). Container cô lập qua namespaces; VM cô lập ở mức phần cứng ảo.
2

Linux namespace nào cho phép container có PID riêng?

PID Namespace. Container có bảng tiến trình riêng — PID 1 trong container là ứng dụng chính (ví dụ nginx, bash), không phải systemd như trên host. Container không thể nhìn thấy các tiến trình của host.
3

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.
4

Sự khác biệt giữa Podman và Docker là gì?

Podman không cần daemon chạy nền (daemonless), hỗ trợ rootless containers mặc định, tương thích với hầu hết lệnh Docker. Docker cần docker daemon (dockerd) chạy với quyền root. Podman dùng Containerfile thay vì Dockerfile (nhưng cũng hỗ trợ Dockerfile).
5

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.
6

Container registry là gì? Cho ví dụ các registry phổ biến.

Registry là kho lưu trữ container images. Phổ biến: docker.io (Docker Hub), quay.io (Red Hat Quay), registry.access.redhat.com (Red Hat), public.ecr.aws (Amazon ECR). Dùng podman pull <registry>/image:tag để tải image.
7

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.
8

Volume bind mount trong container là gì và tại sao quan trọng?

Bind mount (-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.