✔️ 컨테이너에서 (추가)애플리케이션 실행
docker exec <CONTAINER> <COMMAND>
docker exec -it a8 bash
docker exec a8 cat conf/httpd.conf
exec
명령을 일반적으로 가장 많이 사용하는 형태이다.
어떤 어플리케이션을 띄워놓고 확인하고 변경이 필요할 때 bash를 띄워 접근한다.
아니면 단순히 명령어를 확인해보고 싶은 경우에도 이 방식을 사용한다.
✔️ attach vs exec
docker attach
docker exec
두 명령어의 사용법을 비교해보자.
app이 정상 작동하는지 검사 해보거나 컨테이너 내부로 진입하고 싶을 때 다음과 같이 -it
옵션을 붙여 실행한다.
vagrant@docker ~ docker run -it httpd bash
root@cf6769cb699d:/usr/local/apache2# %
bash: fg: %: no such job
root@cf6769cb699d:/usr/local/apache2#
exit
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29d4ce3916b7 httpd "httpd-foreground" About a minute ago Up About a minute 80/tcp youthful_jang
vagrant@docker ~ docker top 29
UID PID PPID C STIME TTY TIME CMD
root 18698 18675 0 05:09 ? 00:00:00 httpd -DFOREGROUND
www-data 18748 18698 0 05:09 ? 00:00:00 httpd -DFOREGROUND
www-data 18749 18698 0 05:09 ? 00:00:00 httpd -DFOREGROUND
www-data 18750 18698 0 05:09 ? 00:00:00 httpd -DFOREGROUND
watch -n1 -d docker top b8
UID PID PPID C STIME
TTY TIME CMD
root 34430 34408 0 07:43
? 00:00:00 httpd -DFOREGROUND
www-data 34475 34430 0 07:43
? 00:00:00 httpd -DFOREGROUND
www-data 34476 34430 0 07:43
? 00:00:00 httpd -DFOREGROUND
www-data 34477 34430 0 07:43
? 00:00:00 httpd -DFOREGROUND
httpd -DFOREGROUND
watch
명령을 통해 현재 실행 중인 프로세스의 리스트를 볼 수 있으며 현재 4개의 프로세스가 실행되고 있다.
exec
명령을 사용하면 기존의 컨테이너에서 우리가 추가로 실행하고자 하는 app을 실행할 수 있다.
vagrant@docker ~ docker exec b8 hostname
b89484219e87
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b89484219e87 httpd "httpd-foreground" 3 minutes ago Up 3 minutes 80/tcp sweet_shtern
exec
를 사용하여 hostname 명령을 실행했다. 컨테이너 목록을 확인하면 아직 b89484219e87이 살아있는 것을 확인할 수 있다.
hostname 명령을 실행했다가 해당 명령을 실행한 프로세스만 종료하는 것을 알 수 있다.
이것을 조금 더 응용해보면 다음과 같이 실행할 수 있는데
vagrant@docker ~ docker exec -it b8 bash
root@b89484219e87:/usr/local/apache2#
UID PID PPID C STIME
TTY TIME CMD
root 34430 34408 0 07:43
? 00:00:00 httpd -DFOREGROUND
www-data 34475 34430 0 07:43
? 00:00:00 httpd -DFOREGROUND
www-data 34476 34430 0 07:43
? 00:00:00 httpd -DFOREGROUND
www-data 34477 34430 0 07:43
? 00:00:00 httpd -DFOREGROUND
httpd -DFOREGROUND
root 38224 34408 0 07:49
pts/0 00:00:00 bash
기존의 프로세스 4개는 그대로 실행 중이며 최하단에 새로운 bash가 생긴 것을 확인할 수 있다.
여기서 exec
의 중요한 점은 bash로 작업을 하고 exit해도 기존의 컨테이너가 종료되지 않는다는 것이다.
vagrant@docker ~ docker exec -it b8 bash
root@b89484219e87:/usr/local/apache2# exit
exit
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b89484219e87 httpd "httpd-foreground" 7 minutes ago Up 7 minutes 80/tcp sweet_shtern
하지만 attach를 이용하면 새롭게 추가한 app에 접근할 수 없다.
attach를 이용하면 기존에 docker run -d httpd
으로 실행한 original 프로세스에 접근한다.
vagrant@docker ~ docker attach b8
^C[Wed May 04 07:53:46.531758 2022] [mpm_event:notice] [pid 1:tid 139919974047040] AH00491: caught SIGTERM, shutting down
vagrant@docker ~
ctrl + c 하면 컨테이너 자체가 중단된다.
✔️ 컨테이너에서 실행하는 프로세스
✘ vagrant@docker ~ docker exec -it b1 bash
root@b15cc9114bcb:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:02 pts/0 00:00:00 bash
root 33 0 0 08:10 pts/1 00:00:00 bash
root 42 33 0 08:10 pts/1 00:00:00 ps -ef ## 제외
컨테이너 내부로 들어와서 ps 명령어를 실행하였다.
ps - ef 는 자기 자신이 실행한 것이므로 제외하면 하나의 bash 는 PID가 1번이고 다른 하나는 33번이다.
그리고 ppid가 동일하게 0이다. (부모 프로세스가 같다는 뜻이다.)
Every 1.0s: docker top b1 docker: Wed May 4 08:11:31 2022
UID PID PPID C STIME
TTY TIME CMD
root 48959 48937 0 08:02
pts/0 00:00:00 bash
root 55957 48937 0 08:10
pts/1 00:00:00 bash
그리고 이것은 ubuntu(VM)에서 top 명령어로 프로세스를 본 것이다.
방금 컨테이너 내부에서 확인한 것과는 다르게 2개의 프로세스만을 확인할 수 있다.
컨테이너 내부에서 ps를 하면 컨테이너 내부의 프로세스만 보이게 된다.
그런데 VM에서 확인한 PID는 다르다.
vagrant@docker ~ ps -ef | grep bash
vagrant 1856 1855 0 01:57 ? 00:00:00 bash
root 48959 48937 0 08:02 pts/0 00:00:00 bash
vagrant 55939 22911 0 08:10 pts/0 00:00:00 docker exec -it b1 bash
root 55957 48937 0 08:10 pts/1 00:00:00 bash
vagrant 58613 32858 0 08:13 pts/1 00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox bash
이 ps 명령은 ubuntu 가상 머신(도커 호스트)에서 실행한 것이다.
도커 호스트 입장에서는 HW가 있고 OS가 있다. OS가 지금 도커 호스트(도커 엔진)이다.
수많은 프로세스들이 위에 있고 그 중에 하나가 이 컨테이너 인 것인데 이 안에 bash가 2개 떠있는 상태이다.
방금 실행한 ps 명령을 통해 본 프로세스들은 OS 입장에서는 컨테이너던 아니던 그냥 프로세스로 보이는 것이다.
그리고 컨테이너 내부에서 실행한 ps 프로세스는 격리되어 있으므로 다른 프로세스에서는 볼 수 없는 것이다.
다시 말하면 도커 엔진 입장에서 바라 볼 때는 컨테이너 내의 프로세스던 아니던 다 같은 프로세스이다.
✔️ 컨테이너 리소스 사용량 확인
docker stats
vagrant@docker ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
81cac4c00bda confident_johnson 0.00% 1.633MiB / 3.84GiB 0.04% 1.23kB / 0B 2.12MB / 0B 1
사용하는 리소스의 양을 볼 수 있다. (CPU, Memory, Network, Disk)
그냥 top
명령어 처럼 1초에 한번씩 새로고침이 된다.--no-stream
: 현재 시점에 한번만 정보가 나온다.
우리가 만든 컨테이너는 리소스 양에 제한이 걸려있지 않다.
결국은 하드웨어가 있고 운영체제가 있고 수많은 프로세스들이 있고 그 중에 컨테이너가 있고 또 컨테이너 내부에도 프로세스가 있을 때 프로세스들은 기본적으로 별도의 제한을 걸지 않는 한 운영체제가 가지고 있는 모든 HW 자원들 다 사용할 수 있다.
문제는 그렇게 되면 다른 컨테이너들이 리소스를 사용해야 하는데 리소스가 모자르게 되고 리소스 요청을 거부 당하면 성능이 매우 떨어지게 된다.
컨테이너 리소스 제한과 관련한 간단한 테스트를 해보자
vagrant@docker ~ docker run -it ubuntu
root@4907d9f07201:/# sha256sum /dev/zero &
[1] 9
root@4907d9f07201:/# %
vagrant@docker ~ docker top 49
UID PID PPID C STIME TTY TIME CMD
root 60209 60183 0 08:34 pts/0 00:00:00 bash
root 60261 60209 98 08:34 pts/0 00:00:17 sha256sum /dev/zero
vagrant@docker ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
4907d9f07201 zen_zhukovsky 121.86% 1.559MiB / 3.84GiB 0.04% 796B / 0B 0B / 0B 2
b15cc9114bcb unruffled_williams 0.00% 1.535MiB / 3.84GiB 0.04% 1.15kB / 0B 0B / 0B 1
953713dc4546 happy_khayyam 0.01% 6.84MiB / 3.84GiB 0.17% 1.37kB / 0B 0B / 0B 82
vagrant@docker ~
ubuntu 컨테이너를 실행한 뒤 cpu 부하를 걸어보자
제한없이 cpu를 다 쓰고 있음을 확인할 수 있다.
호스트에서 top으로 확인해도 같다.
이제 cpu 제한을 걸어보자
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
81cac4c00bda ubuntu "bash" 30 minutes ago Up 30 minutes confident_johnson
vagrant@docker ~ docker run --cpus 0.1 -d ubuntu sha256sum /dev/zero
50bebbaba2fadebcca2164c9f0f53dae11baada035dbb887cf932b2bf21ff689
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
50bebbaba2fa ubuntu "sha256sum /dev/zero" 4 seconds ago Up 2 seconds friendly_pasteur
81cac4c00bda ubuntu "bash" 31 minutes ago Up 31 minutes confident_johnson
vagrant@docker ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
50bebbaba2fa friendly_pasteur 11.17% 744KiB / 3.84GiB 0.02% 796B / 0B 0B / 0B 1
81cac4c00bda confident_johnson 0.00% 1.633MiB / 3.84GiB 0.04% 1.3kB / 0B 2.12MB / 0B 1
hypervisor 처럼 완벽하게 리소스를 제한하지는 않지만 지정한 10% 이하의 값을 유지하려고 한다.
vagrant@docker ~ docker run -d --cpus 0.1 --memory 100m ubuntu sha256sum /dev/zero
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
80e687e8fcbbb6408b72dc0d1477530ec483c5bf5e5d7b6e7d0da75d64251256
vagrant@docker ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
80e687e8fcbb fervent_sammet 0.00% 748KiB / 100MiB 0.73% 516B / 0B 0B / 0B 1
cpu 제한량을 변경할 수 있다.
vagrant@docker ~ docker update --cpus 0.2 80
80
vagrant@docker ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
80e687e8fcbb fervent_sammet 20.36% 748KiB / 100MiB 0.73% 1.08kB / 0B 0B / 0B 1
50bebbaba2fa friendly_pasteur 8.46% 744KiB / 3.84GiB 0.02% 1.08kB / 0B 0B / 0B 1
81cac4c00bda confident_johnson 0.00% 1.633MiB / 3.84GiB 0.04% 1.37kB / 0B 2.12MB / 0B 1
vagrant@docker ~ docker update --memory 200m 80
80
Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
vagrant@docker ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
80e687e8fcbb fervent_sammet 6.71% 748KiB / 200MiB 0.37% 1.08kB / 0B 0B / 0B 1
50bebbaba2fa friendly_pasteur 0.00% 744KiB / 3.84GiB 0.02% 1.08kB / 0B 0B / 0B 1
81cac4c00bda confident_johnson 0.00% 1.633MiB / 3.84GiB 0.04% 1.37kB / 0B 2.12MB / 0B 1
✔️ 컨테이너 로그(stdout/stderr) 확인
/var/lib/docker/container/<ID>/<ID>-json.log
docker logs <CONTAINER>
컨테이너를 삭제하면 로그도 삭제됨
vagrant@docker ~ docker run -d httpd
14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a
vagrant@docker ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
14be11b50281 httpd "httpd-foreground" 5 seconds ago Up 3 seconds 80/tcp funny_kare
vagrant@docker ~ docker exec -it 14 bash
root@14be11b50281:/usr/local/apache2# ls
bin build cgi-bin conf error htdocs icons include logs modules
root@14be11b50281:/usr/local/apache2# cd logs/
root@14be11b50281:/usr/local/apache2/logs# ls
httpd.pid
root@14be11b50281:/usr/local/apache2/logs# cat httpd.pid
1
컨테이너는 LifeCycle이 매우 짧다. 수 분 ~ 수 시간에 만들어져서 종료되는 경우가 대부분이다.
Immutable Image
기본적으로 컨테이너는 불변의 인프라에 맞게 설계된 가상화 기술이다.
반대로 VM을 생각해보면 VM은 mutable structure를 지원하게 위해 만들어 졌다.
VM을 구축해서 app을 실행하거나 운영체제를 업데이트하는 것은 시점이 지남에 따라 시스템의 상태가 변한다.
이러한 Mutable 의 문제점은 Base Image 위에 app 가동 환경을 구축을 할 때 시스템이 변하게 되며 최신 버전을 반영해서 자주 이미지를 만들어줘야 한다는 것이다.
하지만 컨테이너는 운영체제도 없고 app을 업데이트 하는 것보다 새로운 이미지로 교체하여 컨테이너로 실행하기 때문에 컨테이너 내에 뭔가를 새롭게 기록한다는 것은 위험성이 있다.
로그에는 컨테이너 내의 표준 출력, 표준 오류를 기록한다. 하지만 컨테이너를 삭제하면 로그 또한 삭제되는 것이므로 다른 어딘가에 로그를 기록해두어야 한다.
또한 실제로 서비스되는 인프라를 운영 할 때는 법적으로 로그를 기록해 놓아야 한다.
그래서 기본적으로 컨테이너의 로그는 로컬에 저장하지 않는다. (로컬은 컨테이너 내부를 말한다.)
그렇다면 로그는 어디에 있을까 ?
root@14be11b50281:/usr/local/apache2/logs# read escape sequence
✘ vagrant@docker ~ sudo -i
root@docker:/# cd /var/lib/docker/containers/
root@docker:/var/lib/docker/containers# ls
14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a
컨테이너 아이디로 된 디렉토리로 들어가면 컨테이너 아이디-json.log 라는 파일이 있다.
우리가 앞서 httpd를 실행할 때 detach 옵션을 통해 로그를 출력 화면에서 떼어냈기 때문에 저 파일에다가 기록을 하는 것이다.
root@docker:/var/lib/docker/containers# cd 14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a/
root@docker:/var/lib/docker/containers/14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a# ls
14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a-json.log hostconfig.json mounts
checkpoints hostname resolv.conf
config.v2.json hosts resolv.conf.hash
root@docker:/var/lib/docker/containers/14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a# cat 14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a-json.log
{"log":"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message\n","stream":"stderr","time":"2022-05-04T06:14:53.500226557Z"}
{"log":"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message\n","stream":"stderr","time":"2022-05-04T06:14:53.514555375Z"}
{"log":"[Wed May 04 06:14:53.511648 2022] [mpm_event:notice] [pid 1:tid 139925046549824] AH00489: Apache/2.4.53 (Unix) configured -- resuming normal operations\n","stream":"stderr","time":"2022-05-04T06:14:53.514576983Z"}
{"log":"[Wed May 04 06:14:53.511742 2022] [core:notice] [pid 1:tid 139925046549824] AH00094: Command line: 'httpd -D FOREGROUND'\n","stream":"stderr","time":"2022-05-04T06:14:53.514579682Z"}
root@docker:/var/lib/docker/containers/14be11b50281038a634cc793157b5472b3dbe46de63f8ff35cb79455e369e56a#
컨테이너가 실행 중이며 표준 출력할 때 컨테이너의 로그를 확인하면 출력 내용이 같은 것을 확인할 수 있다.
'DevOps > Docker' 카테고리의 다른 글
[Docker] Docker Volume (볼륨) (0) | 2022.05.09 |
---|---|
[Docker] Docker 컨테이너 관리 명령어 (3) (0) | 2022.05.07 |
[Docker] Docker 컨테이너 관리 명령어 (1) (0) | 2022.05.07 |
[Docker] Docker 이미지 관리 명령어 (0) | 2022.05.07 |
[Docker] Docker LifeCycle과 자주 사용하는 옵션 (0) | 2022.05.07 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!