Podman 은 컨테이너화된 애플리케이션을 관리하고 실행하기 위한 도구이다.
리눅스 컨테이너를 관리하기 위한 CLI 도구로 Docker 와 유사한 기능을 갖고 있다.
컨테이너는 소프트웨어 애플리케이션을 패키징하고 실행하기 위한 격리된 환경을 말한다.
1. 데몬(Daemon) 존재 여부
2. 루트리스(Rootless) 컨테이너 지원
3. 네트워크 모델
CNI(Container Network Interface):
컨테이너 오케스트레이션 시스템에서 네트워킹을 관리하기 위한 표준 인터페이스이다.
컨테이너화된 애플리케이션은 종종 다른 애플리케이션 또는 서비스와 통신해야 하는데,
이러한 네트워킹을 관리하고 제어하기 위한 표준화된 방법을 제공한다.
4. PID 네임스페이스 사용
기본적인 환경은 아래와 같다.
[root@jh-container-rocky86 ~]# hostnamectl
Static hostname: jh-container-rocky86.example.com
Icon name: computer-vm
Chassis: vm
Machine ID: d183b307543e46639a4c743afa866cb8
Boot ID: 6cade23a991f43619a0b1eafebe9c3d5
Virtualization: kvm
Operating System: Rocky Linux 8.6 (Green Obsidian)
CPE OS Name: cpe:/o:rocky:rocky:8:GA
Kernel: Linux 4.18.0-372.9.1.el8.x86_64
Architecture: x86-64
[root@jh-container-rocky86 ~]# ip -4 -o a | awk '{print $2" "$4}'
lo 127.0.0.1/8
enp1s0 10.65.121.86/20 # 외부로 통하는 Bridge 대역
cni-podman0 10.88.0.1/16 # Container 에서 사용되는 IP 대역(NAT)
Podman 은 Minimal Install 로 진행할 경우 기본적으로 설치되어 있지 않다.
따라서 ISO 이미지를 Local Repository 로 구성한 후, 설치를 진행한다.
[root@jh-container-rocky86 ~]# dnf repoinfo
Last metadata expiration check: 2:03:27 ago on Thu 01 Feb 2024 07:06:53 AM KST.
Repo-id : AppStream
Repo-name : AppStream
Repo-revision : 8.6
Repo-distro-tags : [cpe:/o:rocky:rocky:8]: , , 8, L, R, c, i, k, n, o, u, x, y
Repo-updated : Mon 16 May 2022 06:01:50 AM KST
Repo-pkgs : 6,549
Repo-available-pkgs: 5,339
Repo-size : 8.3 G
Repo-baseurl : file:///root/repo/AppStream
Repo-expire : 172,800 second(s) (last: Thu 01 Feb 2024 07:06:53 AM KST)
Repo-filename : /etc/yum.repos.d/local.repo
Repo-id : BaseOS
Repo-name : BaseOS
Repo-revision : 8.6
Repo-distro-tags : [cpe:/o:rocky:rocky:8]: , , 8, L, R, c, i, k, n, o, u, x, y
Repo-updated : Mon 16 May 2022 05:59:01 AM KST
Repo-pkgs : 1,716
Repo-available-pkgs: 1,714
Repo-size : 1.3 G
Repo-baseurl : file:///root/repo/BaseOS
Repo-expire : 172,800 second(s) (last: Thu 01 Feb 2024 07:06:53 AM KST)
Repo-filename : /etc/yum.repos.d/local.repo
Total packages: 8,265
[root@jh-container-rocky86 ~]# dnf install podman
Mariadb를 사용하여 테스트를 진행할 예정이므로 명령어 사용을 위해 Mariadb 를 설치한다.
[root@jh-container-rocky86 ~]# dnf install mariadb
외부에서 이미지를 다운로드 받기 위해서는 방화벽 및 DNS 설정이 필요하다.
[root@jh-container-rocky86 ~]# systemctl disable --now firewalld
[root@jh-container-rocky86 ~]# vim /etc/resolv.conf
# Generated by NetworkManager
search example.com
nameserver 8.8.8.8
[root@jh-container-rocky86 ~]# vim /etc/selinux/config
...
SELINUX=disabled
...
[root@jh-container-rocky86 ~]# reboot
# podman pull
명령어를 사용하며 <이미지 이름>:<태그>로 지정한다.[root@jh-container-rocky86 ~]# podman pull mariadb:latest
? Please select an image:
registry.fedoraproject.org/mariadb:latest
registry.access.redhat.com/mariadb:latest
registry.centos.org/mariadb:latest
▸ docker.io/library/mariadb:latest
✔ docker.io/library/mariadb:latest
Trying to pull docker.io/library/mariadb:latest...
Getting image source signatures
Copying blob d1db136ff347 done
Copying blob 56fc83f4f5a4 done
Copying blob 8e87ff28f1b5 done
Copying blob d35acfab0e41 done
Copying blob a3bf637726fe done
Copying blob 40fbc2d141b9 done
Copying blob 4db62f20d419 done
Copying blob 07943e317bab done
Copying config 2b54778e06 done
Writing manifest to image destination
Storing signatures
Loaded image(s): docker.io/library/mariadb:latest
[root@jh-container-rocky86 ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/mariadb latest 2b54778e06a3 2 months ago 411 MB
# podman run
명령어를 사용하여 컨테이너를 실행한다.[root@jh-container-rocky86 ~]# podman run -itd -p 13306:3306 -e MYSQL_ROOT_PASSWORD=1234 \
--restart always --name jh-mariadb01 mariadb:latest
9a2565811de67b54ca6fc1db6d41905be7ece6bccc4d88d44ddb4189669db655
-i > 컨테이너와 상호작용을 위해 표준입력(STDIN)을 유지
-t > TTY(터미널)을 할당
-d > 컨테이너를 백그라운드로 실행
-p 13306:3306 > 호스트의 포트 13306을 컨테이너 포트 3306에 매핑
이 옵션을 사용하면 호스트 시스템에서 컨테이너 내부의 MySQL 서버에 접속할 수 있다.-e MYSQL_ROOT_PASSWORD=1234 > 컨테이너 내에서 사용할 환경 변수 설정
--restart always > 컨테이너가 비정상적으로 종료될 경우 자동으로 다시 시작하도록 설정
-- name > 컨테이너에 이름 부여
mariadb:latest > 실행할 이미지를 지정
# podman ps
명령어로 실행중인 컨테이너를 확인할 수 있다.
[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9a2565811de6 docker.io/library/mariadb:latest mariadbd 21 minutes ago Up 21 minutes ago 0.0.0.0:13306->3306/tcp jh-mariadb01
# podman exec -it <container ID> bash
명령어를 사용하여 실행중인 컨테이너에 진입할 수 있다.[root@jh-container-rocky86 ~]# podman exec -it jh-mariadb01 bash
root@9a2565811de6:/#
root@9a2565811de6:/# mariadb -uroot -p
Enter password: <컨테이너 실행 시 설정한 root 유저 비밀번호>
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 6
Server version: 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
[root@jh-container-rocky86 ~]# ip -4 -o a
1: lo inet 127.0.0.1/8 scope host lo\ valid_lft forever preferred_lft forever
2: enp1s0 inet 10.65.121.86/20 brd 10.65.127.255 scope global noprefixroute enp1s0\ valid_lft forever preferred_lft forever
3: cni-podman0 inet 10.88.0.1/16 brd 10.88.255.255 scope global cni-podman0\ valid_lft forever preferred_lft forever
아래와 같이 컨테이너 내부에 접속한 후 IP를 확인해보면 cni-podman0 네트워크 대역대와 동일한 대역으로 IP가 할당된 것을 확인할 수 있다.
[root@jh-container-rocky86 ~]# podman exec -it jh-mariadb01 bash
root@9a2565811de6:/#
root@9a2565811de6:/# ip -4 -o a
1: lo inet 127.0.0.1/8 scope host lo\ valid_lft forever preferred_lft forever
2: eth0 inet 10.88.0.3/16 brd 10.88.255.255 scope global eth0\ valid_lft forever preferred_lft forever
-h 옵션을 사용하여 해당 IP로 접속을 시도한다.
[root@jh-container-rocky86 ~]# mysql -uroot -p -h 10.88.0.3
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 7
Server version: 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
# podman run
명령어를 사용할 때 -p 13306:3306
옵션을 사용한 것을 확인할 수 있는데, 외부망 접속 IP(예시에서는 10.65.121.86)의 13306 포트로 접속하면 호스트 OS에서 해당 요청을 인식하여 10.88.0.3 IP의 3306 포트로 요청을 Forwarding 한다.[root@jh-container-rocky86 ~]# firewall-cmd --zone=public --add-port=13306/tcp --permanent
success
[root@jh-container-rocky86 ~]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp1s0
sources:
services: cockpit dhcpv6-client ssh
ports: 13306/tcp
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules
다른 서버에서 접속을 시도한다.
[root@jh-up-test-rhel84 ~]# ip -4 -o a
1: lo inet 127.0.0.1/8 scope host lo\ valid_lft forever preferred_lft forever
2: enp1s0 inet 10.65.121.84/20 brd 10.65.127.255 scope global noprefixroute enp1s0\ valid_lft forever preferred_lft forever
[root@jh-up-test-rhel84 ~]# mysql -uroot -p -h 10.65.121.86 -P 13306
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 11.2.2-MariaDB-1:11.2.2+maria~ubu2204 mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
다운로드 받은 이미지를 파일로 저장할 수 있다.
[root@jh-container-rocky86 ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/mariadb latest 2b54778e06a3 2 months ago 411 MB
[root@jh-container-rocky86 ~]# podman save docker.io/library/mariadb:latest > jh-mariadb01.tar.gz
[root@jh-container-rocky86 ~]# ls
anaconda-ks.cfg jh-mariadb01.tar.gz
파일로 저장된 이미지를 불러올 수 있다.
[root@jh-container-rocky86 ~]# podman load < jh-mariadb01.tar.gz
Getting image source signatures
Copying blob d1db136ff347 done
Copying blob d35acfab0e41 done
Copying blob a3bf637726fe done
Copying blob 56fc83f4f5a4 done
Copying blob 8e87ff28f1b5 done
Copying blob 40fbc2d141b9 done
Copying blob 4db62f20d419 done
Copying blob 07943e317bab done
Copying config 2b54778e06 done
Writing manifest to image destination
Storing signatures
Loaded image(s): docker.io/library/mariadb:latest
실행중인 컨테이너의 이미지 정보를 확인할 때 # podman inspect
명령어를 사용한다.
아래 예시에는 컨테이너에 할당된 IP를 확인한다.
[root@jh-container-rocky86 ~]# clear
[root@jh-container-rocky86 ~]# podman inspect --format='{{.NetworkSettings.IPAddress}}' jh-mariadb01
10.88.0.4
[root@jh-container-rocky86 ~]# podman inspect jh-mariadb01
[
{
"Id": "43682ed58c14f6c53163412039f90c878d4c16a4d199ba0c17f5871f992fa19e",
"Created": "2024-02-06T08:54:51.522232562+09:00",
"Path": "docker-entrypoint.sh",
"Args": [
"mariadbd"
],
"State": {
"OciVersion": "1.0.2-dev",
...
# podman ps
이다.[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 8 minutes ago Up 8 minutes ago 0.0.0.0:13306->3306/tcp jh-mariadb01
# podman stop
이다.[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 17 minutes ago Up 7 minutes ago 0.0.0.0:13306->3306/tcp jh-mariadb01
6638de0a26f6 docker.io/library/mariadb:latest --port 23306 6 minutes ago Up 6 minutes ago jh-mariadb02
9a6f109f77ed docker.io/library/mariadb:latest --port 33306 6 minutes ago Up 6 minutes ago jh-mariadb03
[root@jh-container-rocky86 ~]# podman stop jh-mariadb01
jh-mariadb01
[root@jh-container-rocky86 ~]# podman stop -a
6638de0a26f681dde68485d4d1c995fef72bbc4f7c1122441757a6eb7be85c84
9a6f109f77edcdd8a3a4999ec7d07b24728085cf29918c4cb422be8e378b2495
43682ed58c14f6c53163412039f90c878d4c16a4d199ba0c17f5871f992fa19e
[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@jh-container-rocky86 ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 25 minutes ago Exited (0) 7 minutes ago 0.0.0.0:13306->3306/tcp jh-mariadb01
6638de0a26f6 docker.io/library/mariadb:latest --port 23306 14 minutes ago Exited (0) 7 minutes ago jh-mariadb02
9a6f109f77ed docker.io/library/mariadb:latest --port 33306 13 minutes ago Exited (0) 7 minutes ago jh-mariadb03
# podman start
이다.[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@jh-container-rocky86 ~]# podman start jh-mariadb01
jh-mariadb01
[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 27 minutes ago Up 5 seconds ago 0.0.0.0:13306->3306/tcp jh-mariadb01
[root@jh-container-rocky86 ~]# podman start --all
6638de0a26f681dde68485d4d1c995fef72bbc4f7c1122441757a6eb7be85c84
9a6f109f77edcdd8a3a4999ec7d07b24728085cf29918c4cb422be8e378b2495
[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 27 minutes ago Up 10 seconds ago 0.0.0.0:13306->3306/tcp jh-mariadb01
6638de0a26f6 docker.io/library/mariadb:latest --port 23306 16 minutes ago Up 2 seconds ago jh-mariadb02
9a6f109f77ed docker.io/library/mariadb:latest --port 33306 16 minutes ago Up 1 second ago jh-mariadb03
# podman rm
이며,# podman rmi
이다.[root@jh-container-rocky86 ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 33 minutes ago Up 6 minutes ago 0.0.0.0:13306->3306/tcp jh-mariadb01
6638de0a26f6 docker.io/library/mariadb:latest --port 23306 22 minutes ago Up 6 minutes ago jh-mariadb02
9a6f109f77ed docker.io/library/mariadb:latest --port 33306 22 minutes ago Up 6 minutes ago jh-mariadb03
[root@jh-container-rocky86 ~]# podman rm jh-mariadb03
Error: cannot remove container 9a6f109f77edcdd8a3a4999ec7d07b24728085cf29918c4cb422be8e378b2495 as it is running - running or paused containers cannot be removed without force: container state improper
<컨테이너 실행중 삭제를 시도할 때 발생하는 에러 메시지>
[root@jh-container-rocky86 ~]# podman stop jh-mariadb03
jh-mariadb03
[root@jh-container-rocky86 ~]# podman rm jh-mariadb03
9a6f109f77edcdd8a3a4999ec7d07b24728085cf29918c4cb422be8e378b2495
[root@jh-container-rocky86 ~]# podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
43682ed58c14 docker.io/library/mariadb:latest mariadbd 40 minutes ago Up 13 minutes ago 0.0.0.0:13306->3306/tcp jh-mariadb01
6638de0a26f6 docker.io/library/mariadb:latest --port 23306 29 minutes ago Up 12 minutes ago jh-mariadb02
아래 예시에서는 이미지를 삭제한다.
[root@jh-container-rocky86 ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/mariadb latest 2b54778e06a3 2 months ago 411 MB
[root@jh-container-rocky86 ~]# podman rmi 2b54778e06a3
Untagged: docker.io/library/mariadb:latest
Deleted: 2b54778e06a3050394a36e4dfcd153796f404397b84cb1737fd044b74c3bccbf
[root@jh-container-rocky86 ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE