소개
Docker 는 애플리케이션을 컨테이너화하는 강력한 도구이며, 컨테이너 기능을 관리하는 방법을 이해하는 것은 보안 및 성능 최적화에 매우 중요합니다. 이 튜토리얼에서는 Docker 명령을 사용하여 기능을 추가하고 제거하는 과정을 안내하여 특정 요구 사항에 맞게 컨테이너 환경을 조정할 수 있도록 돕습니다.
이 랩에서는 Docker 기능이 무엇인지, 컨테이너 보안을 어떻게 향상시키는지, 그리고 이를 효과적으로 관리하는 방법을 배우게 됩니다. 이 튜토리얼을 마치면 Docker 컨테이너에서 기능을 자신 있게 추가하고 제거할 수 있게 됩니다.
Docker 기능 이해
Docker 기능은 컨테이너에 특정 Linux 커널 권한을 부여하거나 취소할 수 있는 보안 기능입니다. 기능을 실험하기 전에, 그것이 무엇이며 왜 중요한지 이해해 봅시다.
Docker 기능이란 무엇인가?
Docker 의 기능은 Linux 커널의 기능 시스템을 기반으로 하며, 이는 전통적으로 root 사용자와 관련된 권한을 별개의 단위로 나눕니다. 이 접근 방식은 전통적인 전부 또는 전무 (all-or-nothing) root 권한 모델보다 더 안전합니다.
기본적으로 Docker 컨테이너는 제한된 기능 세트로 실행되어 기능과 보안 사이에서 적절한 균형을 제공합니다. 그러나 애플리케이션 요구 사항에 따라 기능을 추가하거나 제거해야 할 수 있습니다.
Docker 컨테이너의 기본 기능을 살펴보겠습니다. 다음 명령을 실행하여 컨테이너를 시작하고 해당 기능을 확인하십시오.
docker run --rm -it ubuntu:22.04 capsh --print
다음과 유사한 출력을 볼 수 있습니다.
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Ambient set =
Current IAB: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
secure-no-ambient-raise: no (unlocked)
uid=0(root) gid=0(root) groups=0(root)
이 출력은 기본적으로 컨테이너에 부여된 기능을 보여줍니다. 이러한 기능은 컨테이너가 시스템 내에서 수행할 수 있는 작업을 제어합니다.
기능이 중요한 이유
Docker 기능을 적절하게 관리하는 것은 다음을 위해 중요합니다.
- 향상된 보안: 기능을 제한함으로써 컨테이너가 손상될 경우 발생할 수 있는 잠재적 피해를 줄입니다.
- 세분화된 제어: 전체 root 액세스를 부여하지 않고도 특정 권한 있는 작업을 허용할 수 있습니다.
- 최소 권한 원칙: 컨테이너는 제대로 작동하는 데 필요한 기능만 가져야 합니다.
다음으로, Docker 컨테이너에 기능을 추가하는 방법을 살펴보겠습니다.
Docker 컨테이너에 기능 추가하기
이 단계에서는 --cap-add 플래그를 사용하여 Docker 컨테이너에 특정 기능을 추가하는 방법을 배우겠습니다. 이는 애플리케이션에 기본 세트에 포함되지 않은 특정 권한이 필요한 경우 유용합니다.
기능 추가를 위한 기본 구문
Docker 컨테이너에 기능을 추가하기 위한 기본 구문은 다음과 같습니다.
docker run --cap-add=<CAPABILITY> <IMAGE> <COMMAND>
컨테이너가 다양한 네트워크 관련 작업을 수행할 수 있도록 하는 NET_ADMIN 기능을 추가해 보겠습니다.
docker run --rm -it --cap-add=NET_ADMIN ubuntu:22.04 capsh --print
출력은 NET_ADMIN 기능이 컨테이너에 추가되었음을 보여줍니다.
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap,cap_net_admin=ep
기능 목록의 끝에 cap_net_admin이 추가된 것을 확인하십시오.
여러 기능 추가하기
종종 컨테이너에 여러 기능을 추가해야 할 수 있습니다. --cap-add 플래그를 여러 번 지정하여 이 작업을 수행할 수 있습니다.
docker run --rm -it --cap-add=NET_ADMIN --cap-add=SYS_TIME ubuntu:22.04 capsh --print
이 명령은 NET_ADMIN 및 SYS_TIME 기능을 모두 컨테이너에 추가합니다. SYS_TIME 기능은 컨테이너가 시스템 시계를 수정할 수 있도록 합니다.
실용적인 예: 네트워크 인터페이스 수정
기능의 실용적인 사용법을 보여주기 위해 NET_ADMIN 기능이 있는 컨테이너를 생성하고 네트워크 인터페이스 설정을 수정해 보겠습니다.
docker run --rm -it --cap-add=NET_ADMIN ubuntu:22.04 /bin/bash
이제 bash 셸이 있는 컨테이너 내부에 있습니다. 네트워크 인터페이스로 작업하기 위해 iproute2 패키지를 설치해 보겠습니다.
apt-get update && apt-get install -y iproute2
이제 더미 네트워크 인터페이스를 생성해 보십시오.
ip link add dummy0 type dummy
ip link show dummy0
새로 생성된 더미 네트워크 인터페이스를 보여주는 출력을 볼 수 있습니다.
6: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 2a:d5:cd:70:91:f4 brd ff:ff:ff:ff:ff:ff
NET_ADMIN 기능이 없으면 이 작업이 실패합니다. exit를 입력하여 컨테이너를 종료할 수 있습니다.
컨테이너 기능 보기
실행 중인 컨테이너의 기능을 검사하려면 docker inspect 명령을 사용할 수 있습니다. 먼저, 추가된 기능으로 컨테이너를 분리 모드로 시작해 보겠습니다.
docker run -d --name cap-test --cap-add=NET_ADMIN ubuntu:22.04 sleep 3600
이제 컨테이너를 검사하여 해당 기능을 확인합니다.
docker inspect cap-test | grep -A 20 CapAdd
출력은 NET_ADMIN 기능이 추가되었음을 보여줍니다.
"CapAdd": [
"NET_ADMIN"
],
이 단계를 완료한 후 정리하는 것을 잊지 마십시오.
docker stop cap-test
docker rm cap-test
Docker 컨테이너에 기능을 추가하는 방법을 이해하면 보안을 유지하면서 컨테이너가 수행할 수 있는 작업에 대한 더 많은 제어가 가능합니다.
Docker 컨테이너에서 기능 제거하기
이 단계에서는 --cap-drop 플래그를 사용하여 Docker 컨테이너에서 기능을 제거하는 방법을 배우겠습니다. 이는 최소 권한의 원칙을 따르는 중요한 보안 관행입니다. 즉, 컨테이너는 절대적으로 필요한 기능만 가져야 합니다.
기능 제거를 위한 기본 구문
Docker 컨테이너에서 기능을 제거하기 위한 기본 구문은 다음과 같습니다.
docker run --cap-drop=<CAPABILITY> <IMAGE> <COMMAND>
파일 소유권을 변경할 수 있는 CHOWN 기능을 제거해 보겠습니다.
docker run --rm -it --cap-drop=CHOWN ubuntu:22.04 capsh --print
출력에서 cap_chown이 더 이상 기능 목록에 포함되지 않음을 알 수 있습니다.
Current: cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
여러 기능 제거하기
--cap-drop 플래그를 여러 번 지정하여 여러 기능을 제거할 수 있습니다.
docker run --rm -it --cap-drop=CHOWN --cap-drop=NET_RAW ubuntu:22.04 capsh --print
이 명령은 컨테이너에서 CHOWN 및 NET_RAW 기능을 모두 제거합니다.
실용적인 예: 기능 제한 테스트
CHOWN 기능이 삭제된 컨테이너를 생성하고 파일 소유권을 변경해 보겠습니다.
docker run --rm -it --cap-drop=CHOWN ubuntu:22.04 /bin/bash
컨테이너 내부에서 테스트 파일을 생성하고 소유권을 변경해 보겠습니다.
touch test_file
ls -l test_file
chown nobody:nogroup test_file
작업이 허용되지 않음을 나타내는 오류 메시지가 표시됩니다.
chown: changing ownership of 'test_file': Operation not permitted
이는 CHOWN 기능을 제거하면 컨테이너가 root 로 실행 중임에도 불구하고 파일 소유권을 변경할 수 없음을 보여줍니다. 컨테이너를 종료하려면 exit를 입력하십시오.
--cap-add 및 --cap-drop 모두 사용하기
--cap-add 및 --cap-drop 플래그를 동일한 명령에서 사용하여 컨테이너의 기능을 정확하게 제어할 수 있습니다.
docker run --rm -it --cap-add=NET_ADMIN --cap-drop=CHOWN ubuntu:22.04 capsh --print
이 명령은 NET_ADMIN 기능을 추가하는 동시에 CHOWN 기능을 제거합니다.
모든 기능 삭제 및 특정 기능 추가하기
최대 보안을 위해 모든 기능을 삭제한 다음 애플리케이션에 필요한 특정 기능만 추가할 수 있습니다.
docker run --rm -it --cap-drop=ALL --cap-add=NET_BIND_SERVICE ubuntu:22.04 capsh --print
이 명령은 권한 있는 포트 (1024 미만) 에 바인딩할 수 있는 NET_BIND_SERVICE 기능만 있는 컨테이너를 생성합니다.
모든 기능이 삭제된 컨테이너 테스트
모든 기능이 삭제된 컨테이너를 생성하고 제한 사항을 관찰해 보겠습니다.
docker run -d --name no-caps --cap-drop=ALL ubuntu:22.04 sleep 3600
이제 컨테이너에 연결하여 다양한 작업을 시도해 보겠습니다.
docker exec -it no-caps /bin/bash
컨테이너 내부에서 외부 호스트를 ping 해 보십시오.
apt-get update && apt-get install -y iputils-ping
ping -c 1 google.com
ping 에 필요한 raw 네트워크 소켓을 생성하는 데 필요한 기능이 컨테이너에 없기 때문에 오류가 표시될 수 있습니다.
exit를 입력하여 컨테이너를 종료한 다음 정리합니다.
docker stop no-caps
docker rm no-caps
Docker 컨테이너에서 기능을 제거하는 방법을 이해하면 각 컨테이너가 수행할 수 있는 작업을 엄격하게 제한하여 컨테이너화된 애플리케이션의 보안을 크게 향상시킬 수 있습니다.
보안 모범 사례와 기능 관리 결합하기
이 마지막 단계에서는 Docker 기능 관리를 다른 보안 모범 사례와 결합하여 안전하고 최소 권한의 컨테이너를 만드는 방법을 살펴보겠습니다.
사용자 지정 기능 프로필로 컨테이너 생성하기
기능 관리와 다른 보안 기능을 결합하는 더 복잡한 예제를 만들어 보겠습니다.
docker run -d --name secure-container \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp \
ubuntu:22.04 sleep 3600
이 명령은 다음을 수행합니다.
- 모든 기능을 삭제합니다.
NET_BIND_SERVICE기능만 추가합니다.- 컨테이너 파일 시스템을 읽기 전용으로 만듭니다.
- 쓰기 작업을 위해
/tmp에 임시 파일 시스템을 생성합니다.
이 컨테이너를 검사하여 구성을 확인해 보겠습니다.
docker inspect secure-container | grep -A 5 CapAdd
docker inspect secure-container | grep -A 5 CapDrop
docker inspect secure-container | grep ReadonlyRootfs
다음과 같은 보안 설정을 확인하는 출력을 볼 수 있습니다.
"CapAdd": [
"NET_BIND_SERVICE"
],
"CapDrop": [
"ALL"
],
"ReadonlyRootfs": true,
제한 사항 테스트
보안 컨테이너에 연결하여 제한 사항을 테스트해 보겠습니다.
docker exec -it secure-container /bin/bash
컨테이너에서 시스템 파일을 수정해 보십시오.
echo "test" > /etc/test
파일 시스템이 읽기 전용이므로 오류가 표시됩니다.
bash: /etc/test: Read-only file system
이제 /tmp 디렉토리에 쓰기를 시도해 보십시오.
echo "test" > /tmp/test
cat /tmp/test
/tmp에 쓰기 가능한 tmpfs 를 마운트했으므로 이 작업이 작동해야 합니다.
test
exit를 입력하여 컨테이너를 종료합니다.
비 루트 사용자와 함께 기능 사용하기
추가 보안을 위해 기능을 관리하면서 비 루트 사용자로 컨테이너를 실행할 수 있습니다. 먼저, 비 루트 사용자와 특정 기능을 결합하는 새 컨테이너를 만들어 보겠습니다.
docker run -d --name nonroot-container \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--user 1000:1000 \
ubuntu:22.04 sleep 3600
NET_BIND_SERVICE 기능을 추가하고 비 루트 사용자로 실행하더라도 Linux 기능은 기본적으로 root 로 실행되는 프로세스에만 적용됩니다. 비 루트 사용자가 기능을 사용하도록 허용하려면 setuid 바이너리 또는 주변 기능과 같은 추가 구성이 필요합니다.
docker-compose 에서 기능 사용하기
여러 컨테이너를 관리하기 위해 docker-compose 를 사용하는 경우 docker-compose.yml 파일에서 기능을 지정할 수 있습니다.
version: "3"
services:
webapp:
image: ubuntu:22.04
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /tmp
이는 컨테이너 배포 전반에 걸쳐 기능을 관리하는 일관된 방법을 제공합니다.
정리하기
생성한 컨테이너를 정리해 보겠습니다.
docker stop secure-container nonroot-container
docker rm secure-container nonroot-container
모범 사례 요약
다음은 Docker 기능을 관리하기 위한 몇 가지 모범 사례입니다.
- 모든 기능을 삭제하고 필요한 기능만 추가합니다.
- 기능 관리와 다른 보안 기능을 결합합니다.
- 읽기 전용 파일 시스템
- 비 루트 사용자
- Seccomp 프로필
- AppArmor 또는 SELinux
- 컨테이너 기능을 정기적으로 감사합니다.
- Docker 및 컨테이너 이미지를 최신 상태로 유지합니다.
- 컨테이너 취약성 검사 도구를 사용합니다.
이러한 모범 사례를 따르면 Docker 컨테이너의 보안을 크게 향상시킬 수 있습니다.
요약
이 랩에서는 보안 및 기능을 향상시키기 위해 Docker 컨테이너 기능을 효과적으로 관리하는 방법을 배웠습니다. 다음은 수행한 작업에 대한 요약입니다.
- Docker 기능이 무엇인지, 컨테이너 보안에 왜 중요한지 이해했습니다.
--cap-add플래그를 사용하여 컨테이너에 기능을 추가하는 방법을 배우고, 컨테이너가 특정 권한 있는 작업을 수행할 수 있도록 했습니다.--cap-drop플래그를 사용하여 기능을 제거하는 연습을 하고, 최소 권한의 원칙을 구현했습니다.- 보안 컨테이너 환경을 만들기 위해 기능 관리와 다른 보안 기능을 결합하는 모범 사례를 살펴보았습니다.
이러한 기술을 적용하여 필요한 권한만 정확하게 갖춘 컨테이너를 만들 수 있습니다. 이 접근 방식은 컨테이너화된 애플리케이션의 잠재적인 공격 표면을 크게 줄이는 동시에 올바르게 작동하는 데 필요한 기능을 갖도록 보장합니다.
Docker 보안 기능을 계속 탐색하고 컨테이너화된 환경에서 강력한 보안 태세를 유지하기 위해 컨테이너 구성을 정기적으로 감사하고 업데이트하는 것을 잊지 마십시오.



