도커 엔진은 컨테이너를 실행하면서 새로운 프로세스를 만듭니다.
컨테이너는 리눅스 커널의 네임스페이스(Namespaces) 기능으로 인해 부모 프로세스로부터 독립되어 실행됩니다.
그 결과 컨테이너는 두 개의 프로세스 ID(PIDs)를 갖습니다. 첫 번째 PID는 컨테이너 내부에서 두 번째 PID는 호스트에서 사용됩니다.
이 프로젝트의 개발 환경
- CentOS Linux release 7.9.2009 (Core)
네임스페이스(Namespaces)와 unshare
네임스페이스는 프로세스 그룹에서 일부 리소스(PID 넘버 공간, 사용자, 네트워크 인터페이스 등)를 분리 할 수 있는 커널의 기능입니다.
각 리소스 유형에 상응하는 네임스페이스 유형은 8개입니다.
- Cgroup
- IPD
- Network
- Mount
- PID(Process ID)
- Time
- User
- UTS(Host names, Domain names, etc)
네임스페이스를 생성하려면 unshare 명령어를 사용합니다.
unshare 명령어는 새로운 네임스페이스를 생성하고 그 안에 주어진 프로그램을 실행합니다.
새로운 PID 네임스페이스에서 ps 명령어를 실행하는 자식 프로세스를 생성합니다.
$ sudo unshare --pid --mount-proc --fork ps ax
PID TTY STAT TIME COMMAND
1 pts/2 R+ 0:00 ps ax
라인 | 비고 | |
새로운 |
||
새로운 |
||
proc filesystem을 |
||
unshare로 생성된 모든 프로세스와 백그라운드 작업을 출력합니다. |
ps 실행 결과로 unshare 명령어를 사용해서 만든 하나의 프로세스만 출력하고 있습니다.
이 프로세스는 네임스페이스에서 PID 값이 1인 최초의 프로세스입니다.
--mount-proc 옵션을 추가되지 않으면 새로운 네임스페이스에서의 프로세스 외에도 호스트의 모든 프로세스가 표시됩니다.
네임스페이스 바깥(호스트의 기존 파일 시스템)에 해당하는 /proc 디렉토리를 스캔하기 때문입니다.
unshre 명령의 다른 옵션을 사용하여 예제를 확장하고 네임스페이스 유형을 추가 할 수 있습니다.
lsns 명령어로 새로 생성한 네임스페이스 확인
lsns 명령어는 접근 가능한 네임스페이스에 대한 목록을 표시합니다. 별도의 옵션을 지정하지 않으면 접근 가능한 모든 네임스페이스를 표시합니다.
-t 옵션을 사용하면 특정 네임스페이스 유형을 필터 할 수 있습니다.
$ sudo lsns -t pid
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 100 1 root /sbin/init
여기서는 루트 PID 네임스페이스를 표시합니다. 표시되는 첫 열은 inode 번호로 네임스페이스 식별자입니다.
예시에서 루트 PID 네임스페이스의 식별자는 NS: 4026531836입니다.
이번에는 unshare 명령어를 사용하여 새로운 PID 네임스페이스를 생성합니다.
$ sudo unshare --pid --mount-proc --fork sleep 1000 &
[1] 1835
자식 프로세스가 ps 명령어 대신 sleep을 실행합니다. 새로운 PID 네임스페이스는 sleep 명령어가 지속되는 동안 유지됩니다.
다시 lsns을 사용하여 네임스페이스 목록을 표시합니다.
$ sudo lsns -t pid
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 102 1 root /sbin/init
4026532149 pid 1 1837 root sleep 1000
이제 두 개의 PID 네임스페이스가 표시됩니다.
네임스페이스 식별자 NS: 4026531836은 루트 PID 네임스페이스이고, NS: 4026532149는 unshare 명령어로 만들어진 PID 네임스페이스입니다.
부모 네임스페이스와 자식 네임스페이스 관계
이전 섹션에서의 예시 NS: 4026532149는 루트 PID 네임스페이스의 자식 네임스페이스입니다.
핵심은 부모-상위 네임스페이스가 자식-하위 네임스페이스 및 프로세스에 엑세스 할 수 있다는 것입니다(이전 섹션에서 lsns 명령어를 사용해 자식 네임스페이스를 스캔하고 있습니다).
마찬가지로 ps 명령어를 사용하면 자식 네임스페이스에서 실행되는 프로세스를 표시 할 수 있습니다.
$ ps aux | grep sleep
1882 root sudo unshare --pid --mount-proc --fork sleep 1000
1883 root unshare --pid --mount-proc --fork sleep 1000
1884 root sleep 1000
자식 네임스페이스에서 실행되고 있는 PID: 1884 프로세스가 표시됩니다. 이 프로세스는 lsns 명령어에서 PID: 1837로 확인되는데 부모 네임스페이스에서 확인되는 PID: 1884와 다른 PID를 갖는 것을 알 수 있습니다.
결과적으로 네임스페이스에서 실행되는 프로세스는 두 개의 PID(하나는 자신의 네임스페이스에, 다른 하나는 부모 네임스페이스에서)를 갖게 됩니다.
Docker 컨테이너의 PID 확인
이제 도커에서 PID 네임스페이스가 어떻게 동작되는지 살펴봅니다. 실습을 위해서 Alpine Linux 컨테이너를 실행합니다.
$ sudo docker run -d alpine:latest sleep 1000
f0901c0b43329f6f997ec946597c3ab159c58a885cd081a8d0f855ae19c8188f
lsns 명령어를 실행하여 접근 가능한 PID 네임스페이스를 모두 표시합니다.
sudo lsns -t pid
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 115 1 root /sbin/init
4026532153 pid 1 2083 root sleep 1000
Docker 컨테이너는 NS: 4026532153의 새로운 PID 네임스페이스를 생성합니다. 그리고 네임스페이스에서 실행되는 PID: 2083입니다.
이는 부모 네임스페이스 상에서 ps 명령어를 사용하는 것으로도 확인 할 수 있습니다.
ps aux | grep sleep
2083 root sleep 1000
도커 컨테이너가 생성한 네임스페이스에서의 PID를 확인합니다. 아래는 컨테이너에서 ps 명령어를 실행하기 위한 구문입니다.
sudo docker container exec f0901 ps ax
PID USER TIME COMMAND
1 root 0:00 sleep 1000
6 root 0:00 ps ax
자식 네임스페이스에서 sleep 명령어를 실행중인 프로세스는 PID: 1입니다.
Docker 컨테이너가 실행되면 새로운 PID 네임스페이스를 구성합니다.
컨테이너에서 실행되는 프로세스는 루트의 자식 네임스페이스에서 동작하며 PID: 1번을 할당받습니다.
컨테이너에서 실행되는 프로세스는 현재 위치한 PID 네임스페이스에 따라서 다른 PID를 갖게 됩니다.
부모 네임스페이스에 있는 /proc 파일시스템 status 파일에서 프로세스 ID 매핑 정보를 확인 할 수 있습니다.
$ sudo cat /proc/2083/status | grep NSpid
NSpid: 2083 1
코드 | 비고 | |
정리 및 복습
- Docker 컨테이너를 실행할 때
새로운 PID 네임스페이스를 생성합니다. 이는 리눅스의 네임스페이스 생성 과정과 동일합니다. - 새로 생성된 PID 네임스페이스에서 실행되는 프로세스는 독립된 PID를 갖습니다.
- 부모 네임스페이스는 자식 네임스페이스 및 프로세스에 엑세스 할 수 있습니다. 부모 네임스페이스에서는 프로세스가 자식 네임스페이스에서 할당된 PID와 다른 PID를 갖습니다.
- 결론적으로 Docker 컨테이너에서 실행되는 프로세스는
PID: 1부터 시작하며호스트-부모 네임스페이스에서는 다른 PID로 표시됩니다.
'DevOps & Infra > Docker' 카테고리의 다른 글
Docker에서 MySQL 서버 실행하기 (0) | 2023.12.05 |
---|---|
Ubuntu 20.04 이미지 Pull하고 컨테이너 실행하기 (0) | 2023.11.09 |
[Infrastructure/Docker] CentOS에서 yum으로 Docker Engine, Docker Compose 설치/삭제 (0) | 2022.06.08 |
[Infrastructure/Docker] 로컬 및 원격에서 syslog 로깅 드라이버 구성하기, syslog 로그 파일 경로 (0) | 2022.04.13 |
[Infrastructure/Docker] 도커 컨테이너 로그 파일 경로, MacOS 환경에서 로그 파일을 찾을 수 없는 문제 (0) | 2022.04.13 |