루트리스 Docker 사용 팁
루트리스 Docker 사용 팁
루트리스(rootless) 모드로 Docker를 운영할 때 알아두면 좋은 고급 사용법과 모범 사례를 정리했어요. 데몬을 systemd로 관리하는 방법부터 클라이언트 설정, 리소스 제한까지 하나씩 차근차근 살펴볼게요. 아래 명령어들은 환경에 맞게 그대로 사용하시면 됩니다.
출처: 공식문서
본문
고급 사용법
데몬
systemd 사용 시 (강력 권장)
systemd 유닛 파일은 ~/.config/systemd/user/docker.service로 설치돼요. 데몬의 수명 주기를 관리하려면 systemctl --user 명령을 사용하면 됩니다.
$ systemctl --user start docker
시스템 부팅 시 데몬을 자동으로 시작하려면 systemd 서비스를 활성화하고 lingering을 켜두세요.
$ systemctl --user enable docker
$ sudo loginctl enable-linger $(whoami)
루트리스 Docker를 시스템 차원의 systemd 서비스(/etc/systemd/system/docker.service)로 실행하는 것은 User= 지시문을 사용하더라도 지원되지 않아요.
systemd를 사용하지 않는 경우
systemd 없이 데몬을 직접 실행하려면 dockerd 대신 dockerd-rootless.sh를 실행해야 해요. 이때 다음 환경 변수를 반드시 설정해야 합니다.
$HOME: 홈 디렉터리$XDG_RUNTIME_DIR: 예상 사용자만 접근할 수 있는 임시 디렉터리로, 예를 들면~/.docker/run같은 경로예요. 이 디렉터리는 호스트가 종료될 때마다 제거되어야 하며, tmpfs에 둘 수는 있지만/tmp아래에는 두지 않는 것이 좋아요./tmp아래에 두면 TOCTOU 공격에 취약해질 수 있습니다.
디렉터리 경로와 관련해 꼭 기억해야 할 사항이 몇 가지 있어요.
- 소켓 경로는 기본적으로
$XDG_RUNTIME_DIR/docker.sock으로 설정돼요.$XDG_RUNTIME_DIR는 보통/run/user/$UID로 설정됩니다. - 데이터 디렉터리는 기본적으로
~/.local/share/docker로 설정돼요. 이 디렉터리는 NFS 위에 두면 안 됩니다. - 데몬 설정 디렉터리는 기본적으로
~/.config/docker로 설정돼요. 이 디렉터리는 클라이언트가 사용하는~/.docker와는 다르니 혼동하지 마세요.
클라이언트
Docker Engine v23.0부터는 dockerd-rootless-setuptool.sh install 명령이 docker CLI가 rootless 컨텍스트를 사용하도록 자동으로 설정해줘요.
Docker Engine v23.0 이전 버전에서는 사용자가 소켓 경로나 CLI 컨텍스트를 직접 지정해야 했어요.
$DOCKER_HOST로 소켓 경로를 지정하려면 이렇게 하면 됩니다.
$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
$ docker run -d -p 8080:80 nginx
docker context 명령으로 CLI 컨텍스트를 지정하려면 이렇게 하세요.
$ docker context use rootless
rootless
Current context is now "rootless"
$ docker run -d -p 8080:80 nginx
모범 사례
Docker 안에서 루트리스 Docker 실행하기
"루트풀(rootful)" Docker 안에서 루트리스 Docker를 실행하려면 docker:<version>-dind 이미지 대신 docker:<version>-dind-rootless 이미지를 사용하세요.
$ docker run -d --name dind-rootless --privileged docker:25.0-dind-rootless
docker:<version>-dind-rootless 이미지는 비루트 사용자(UID 1000)로 실행돼요. 다만 seccomp, AppArmor, 마운트 마스크를 비활성화하려면 --privileged 옵션이 필요합니다.
Docker API 소켓을 TCP로 노출하기
Docker API 소켓을 TCP로 노출하려면 DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp" 옵션을 지정한 상태에서 dockerd-rootless.sh를 실행해야 해요.
$ DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp" \
dockerd-rootless.sh \
-H tcp://0.0.0.0:2376 \
--tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem
Docker API 소켓을 SSH로 노출하기
Docker API 소켓을 SSH로 노출하려면 원격 호스트에 $DOCKER_HOST가 설정되어 있는지 확인해야 해요.
$ ssh -l <REMOTEUSER> <REMOTEHOST> 'echo $DOCKER_HOST'
unix:///run/user/1001/docker.sock
$ docker -H ssh://<REMOTEUSER>@<REMOTEHOST> run ...
ping 패킷 라우팅
일부 배포판에서는 기본적으로 ping이 동작하지 않아요. ping을 사용하려면 /etc/sysctl.conf(또는 /etc/sysctl.d)에 net.ipv4.ping_group_range = 0 2147483647을 추가하고 sudo sysctl --system을 실행하세요.
특권 포트 노출
특권 포트(1024 미만)를 노출하려면 rootlesskit 바이너리에 CAP_NET_BIND_SERVICE를 설정하고 데몬을 재시작하세요.
$ sudo setcap cap_net_bind_service=ep $(which rootlesskit)
$ systemctl --user restart docker
또는 /etc/sysctl.conf(또는 /etc/sysctl.d)에 net.ipv4.ip_unprivileged_port_start=0을 추가하고 sudo sysctl --system을 실행해도 됩니다.
리소스 제한
--cpus, --memory, --pids-limit 같은 cgroup 관련 docker run 플래그로 리소스를 제한하는 기능은 cgroup v2와 systemd 환경에서만 지원돼요. cgroup v2를 활성화하려면 cgroup 버전 변경 문서를 참고하세요.
docker info 명령에서 Cgroup Driver가 none으로 표시되면 조건이 충족되지 않은 거예요. 이 경우 루트리스 모드는 cgroup 관련 docker run 플래그를 무시합니다. 해결 방법은 cgroup 없이 리소스 제한하기를 참고하세요.
docker info 명령에서 Cgroup Driver가 systemd로 표시되면 조건이 충족된 거예요. 다만 기본적으로는 memory와 pids 컨트롤러만 비루트 사용자에게 위임되는 경우가 일반적입니다.
$ cat /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers
memory pids
모든 컨트롤러의 위임을 허용하려면 systemd 구성을 변경해야 해요.
$ sudo mkdir -p /etc/systemd/system/[email protected]
/etc/systemd/system/[email protected]/delegate.conf 파일을 생성하세요.
[Service]
Delegate=cpu cpuset io memory pids
그런 다음 systemd를 다시 로드합니다.
$ sudo systemctl daemon-reload
참고
cpuset위임에는 systemd 244 이상이 필요해요.
cgroup 없이 리소스 제한하기
cgroup을 사용할 수 없는 상황에서도 전통적인 ulimit과 cpulimit을 사용할 수 있어요. 다만 이 도구들은 컨테이너 단위가 아니라 프로세스 단위로 동작하며, 컨테이너 프로세스가 임의로 비활성화할 수도 있다는 점을 유의하세요.
예를 들어 이런 식으로 사용할 수 있습니다.
-
CPU 사용량을 0.5코어로 제한하려면(
docker run --cpus 0.5와 유사):docker run <IMAGE> cpulimit --limit=50 --include-children <COMMAND> -
최대 VSZ를 64MiB로 제한하려면(
docker run --memory 64m와 유사):docker run <IMAGE> sh -c "ulimit -v 65536; <COMMAND>" -
네임스페이스 UID 2000 기준 최대 프로세스 수를 100개로 제한하려면(
docker run --pids-limit=100와 유사):docker run --user 2000 --ulimit nproc=100 <IMAGE> <COMMAND>