요약
컨테이너 런타임을 직접 만들어 보니 Docker의 속은 생각보다 훨씬 이상했습니다.
블로그 Code and Cake의 작성자가 재미 삼아 컨테이너 런타임(컨테이너를 실제로 띄우고 실행하는 프로그램)을 만들면서 알게 된 점을 정리한 글입니다. 작성자는 Docker가 여러 면에서 뜻밖이었다고 했습니다.
왜 중요한가
- 매일 쓰는 컨테이너가 작은 가상 머신이 아니라 제약을 건 평범한 리눅스 프로세스라는 점을 일깨웁니다.
- 런타임이 쓰는 커널 기능 대부분에 root 권한이 필요하다는 점에서 컨테이너 보안이 왜 어려운지 드러납니다.
- 자주 쓰는 도구의 작은 판을 직접 만들어 보는 것이 동작 원리를 배우는 좋은 방법이라고 권합니다.
핵심 내용
- 컨테이너에는 별도 커널이 없고, 호스트 커널이 돌리는 프로세스라서
/proc에서도 보입니다. - '컨테이너'라는 커널 기능은 따로 없고, 네임스페이스(보이는 범위 제한)와 cgroup(자원 사용 제한) 등 다섯 가지 안팎의 기능을 엮은 것입니다.
- 이미지는 디렉터리 트리일 뿐이며, Docker는 이를 디스크에 풀고
chroot나pivot_root로 컨테이너의 루트로 삼습니다. - Go로 짠 runc는 Go 런타임의 멀티스레드 구조와
fork부재를 C 모듈과/proc/self/exe재실행으로 우회합니다. - rootless 런타임(일반 사용자 권한으로 도는 런타임)은 좋아졌지만, 네트워크는 사용자 공간에서 상당 부분을 다시 구현해야 합니다.
HN 반응
- Docker를 만든 솔로몬 하익스가 직접 댓글을 달아 2013년 PyCon 첫 공개 당시를 회고했고, 현장에 있던 이용자들의 추억담이 이어졌습니다.
- Docker의 진짜 강점이 Dockerfile과 레지스트리인지, 커널 기능을 쉽게 쓰게 한 사용성과 생태계의 기세인지를 두고 의견이 갈렸습니다.
안녕하세요, 저는 Docker를 만든 사람인데 이 글을 우연히 보게 됐습니다. 다른 엔지니어들이 시스템을 어떻게 설계했는지 고민해 주는 모습을 보는 건 언제나 즐겁습니다. Docker 개발에서 손을 뗀 지 여러 해가 됐지만, 옛 기억을 더듬어 보는 재미가 있네요.
궁금한 점이 있으면 기꺼이 답해 드리겠습니다.
2013년 PyCon US 산타클라라에서 5분짜리 Docker 라이트닝 토크를 하실 때 저도 청중석에 있었습니다. 친구이자 동료( https://nvie.com/about/ )와 그 발표 이야기를 나눴는데, 그날 라이트닝 토크 중에 가장 흥미로웠다는 데 둘 다 동의했습니다.
웃기는 건, "그저" 라이트닝 토크였다는 이유로 PyCon이 끝나고 제가 팀에 보낸 정리 노트에는 들어가지도 못했다는 겁니다. 그런데 불과 1년 뒤에는 우리 팀이(그리고 다른 모든 사람이) Docker로 프로젝트를 로컬에서 돌리고 있었습니다.
2013년 그날의 기억 중에 흥미로운 게 있나요? 그리고 그 뒤 1년 사이에 어떤 일이 있었기에 Docker가 그렇게 널리 퍼졌다고 보시나요? 그 밖에 결정적인 순간이나 전환점이 있었나요?
그날은 제 기억에 영원히 새겨져 있습니다... 퍼뜩 떠오르는 대로 말씀드리면 이렇습니다.
저는 청중이 10~20명쯤일 거라고 생각하고 라이트닝 토크를 신청했습니다. 아직 완성하지 못했고 그때까지 1대1 시연으로만 보여 줬던 프로젝트를 비공개로 선보일 생각이었죠. 그런데 PyCon에서는 라이트닝 토크를 메인 무대에서 한다는 걸 알았을 때의 제 놀라움을 상상해 보세요!
앞 발표자가 나타나지 않아서 제가 일찍 시작했습니다. 녹화본을 보면 제가 "그분 시간도 제가 쓰면 안 될까요?" 하고 농담하는 게 들리는데, 사회자는 달가워하지 않았습니다.
저는 시간을 넘겨서 마지막 부분을 말을 빨리 몰아서 끝내야 했습니다.. 사회자는 이번에도 달가워하지 않았고, 거의 저를 무대 밖으로 떠밀다시피 했습니다 :-D
행사장에 작은 스폰서 부스가 있었고, 우리 소규모 마케팅 팀은 거기서 우리 제품(DotCloud)을 홍보할 준비를 하고 있었습니다. 그런데 발표가 끝나자 사람들이 떼로 몰려와서 "Docker"에 대해 묻는 바람에 팀원들이 완전히 어리둥절해했습니다. 그들이 아는 Docker는 창업자의 사이드 프로젝트일 뿐이었으니까요.
저는 갓 산 오토바이를 타고 산타클라라까지 갔는데, 고속도로를 처음 달려 본 길이었습니다. "오늘은 모든 위험을 감수하는 날이다!" 하고 스스로에게 말했던 기억이 납니다.
발표 때문에 불안할 때는 발표장까지 오토바이를 타고 가면 보통 모든 게 제자리를 찾는 느낌이 들어요.
저도 그 말에 동의합니다. 요즘은 타고 싶은 만큼 타진 못하지만요.
저는 죽을 뻔한 오토바이 사고를 당했는데 용케 거의 멀쩡하게 걸어 나왔고, 그 일로 제가 두려워하던 것들을 보는 관점이 완전히 바뀌었습니다.
그 사고 덕분에 당시 훗날 아내가 될 사람은 제가 없으면 못 산다는 걸 깨닫기도 했습니다. 찌그러진 오토바이 사진에 "아야야"라는 문자를 붙여 보냈거든요. 그러니까 그 사고는 제 삶을 좋은 쪽으로 확 바꿔 놓은 셈입니다.
그래도 제 초창기 Surface Pro가 박살 난 건 아직도 슬퍼요. 풀옵션 출시 모델이었고, 이제는 아예 사라진 쇼핑몰의 Microsoft 스토어에서 산 용의 해 터치 커버까지 붙어 있었는데요. 메신저백에 넣어 등에 메고 있었다가 결국 미친 듯이 뒤틀린 쇳덩이가 되어 버렸습니다.
그러니까 오토바이는 여러분의 인생을 바꿔 놓을 겁니다.
저도 거기 있었습니다. 정말 인상 깊었는데, 그 자리에 있던 사람들이 대수롭지 않게 반응해서 이상하게 얼떨떨하기도 했습니다. 그래서 내가 본 게 그렇게 대단한 게 아닌가 하는 의심까지 들었어요. 분명 청중 중에는 저보다 잘 아는 사람이 있을 테니까요.
저도 거기 있었습니다 :-) PyCon에 같이 갔던 동업자는 Docker가 easy_install을 고치는 복잡한 방법처럼 보인다고 했습니다(당시에는 공식 해법이 pip를 채택하는 쪽으로 갈 것처럼 보였거든요). 저는 가능성이 있다고 생각했지만 :-) 이렇게까지 휩쓸 줄은 전혀 예상하지 못했습니다.
문제의 영상입니다: https://www.youtube.com/watch?v=wW9CAH9nSLs
와, 이거 보니 놀랍네요. 나중에 이 기술을 알게 됐을 때 얼마나 신났는지 기억나거든요. 그게 이렇게 5분짜리 깜짝 소개로 축소됐다가 무대에서 쫓겨나듯 끝나는 모습이라니 대단합니다. 이런 맥락에서 영상을 공유해 주셔서 고맙습니다.
공유해 주셔서 감사합니다. 정말 흥미로운 역사의 한 장면이네요. 현대 세계를 움직이는 위대한 기술의 시작을 돌아보는 건 언제나 좋습니다. 솔로몬 님께도 감사드립니다!
그 라이트닝 토크 세션 녹화본은 https://pyvideo.org/pycon-us-2013/friday-evening-lightning-talks.html 에 있습니다. 저도 거기 있었고, 바로 이해하지 못한 사람 중 하나였습니다. 그래도 PyCon 남은 기간 동안 오가던 대화에서 그 발표가 여러 번 언급됐던 건 기억나요.
저는 Docker의 열렬한 팬이고, 무엇보다 Docker를 세상에 내놔 주셔서 감사하다는 말씀을 드리고 싶습니다.
처음 컨테이너를 써 보려 한 건 2015년쯤 파나마 보카스델토로의 어느 해변 카페 와이파이에서였습니다. 어떻게 됐을지는 짐작이 가시죠...
잠깐 손을 놓았다가 다시 돌아온 뒤로는, 제가 구성한 수많은 로컬 개발 스택, 심지어 프로덕션 스택(compose)에서도 핵심이 됐습니다. 제게 마법 같은 순간은 소스를 마운트해서 로컬의 네이티브 개발 도구를 전부 그대로 쓰면서 나머지는 전부, 특히 필요한 런타임과 의존성 조합이 뭐든 완전히 가상화할 수 있다는 걸 처음 깨달았을 때였습니다.
정말 전구가 켜지는 순간이었습니다. '내 컴퓨터에선 되는데'가 말끔히 해결되고, 새 사람이 프로젝트에 합류해 환경을 갖추는 것도 간단해졌죠. 소프트웨어 엔지니어링이 원래 이래야 한다 싶었고, 한번 경험하고 나면 돌아가기 어렵습니다.
궁금한 게 있습니다. 만드신 분으로서 지금도 Docker를 쓰시나요, 아니면 새로운 방식을 내다볼 줄 아는 분이니 이미 다음 것으로 넘어가셨나요? 그렇다면 그게 뭔가요? :-)
공유해 주셔서 감사합니다!
네, 지금도 Docker를 씁니다. 다만 쓰는 방식은 다른 많은 분들처럼 시간이 지나면서 달라졌고요.
제 새 프로젝트인 Dagger는 Docker와 직접 경쟁하지는 않지만 자체 컨테이너 런타임과 오케스트레이터(CI 파이프라인용)를 구현하고 있고, 최근에는 Dockerfile과 Docker Compose 파일 호환성까지 추가했습니다... 그래서 CI 파이프라인에서는 Docker 대신 Dagger를 쓰는 일이 점점 늘고 있습니다.
반면 개인 프로젝트에는 거의 전부 docker compose를 씁니다. 아이들을 위한 마인크래프트 서버, 홈 오토메이션, AI 해킹 같은 것들요. 요즘은 설정도 그냥 AI 에이전트가 해 주게 하지만요 :)
Dagger 정말 좋아해요! 여기서 연결고리를 이제야 알아챘다니 어떻게 놓쳤는지 모르겠네요.
KubeCon 2024의 "You’re overpaying for CI"( https://www.youtube.com/watch?v=tsH3eTo2GLI )는 AI 시대인 요즘 특히 와닿는 것 같아요.
그해 제가 가장 좋아한 발표 중 하나였고, 덕분에 Dagger가 제대로 이해되기 시작했어요.
그거 제 발표예요! 그 발표를 준비하는 게 정말 즐거웠는데, 아직도 사람들이 이야기해 주신다니 너무 기뻐요 :)
Dagger 한번 살펴볼게요, 흥미로워 보이네요.
네, 저도 AI로 docker/compose 설정과 그에 딸린 일회성 스크립트를 짜는 걸 정말 즐기고 있어요. 원래도 꽤 이해하기 쉬웠지만, 이제는 생각나는 건 뭐든 말 그대로 몇 분 만에 구성할 수 있죠. 딱 한 번 쓸 특정 구성이 필요할 때도요. 데브옵스에겐 멋진 시대예요!
vito가 설득해서 Garden을 채택하신 거죠?
</injoke>그나저나 오늘 새 프로젝트를 공개했습니다 :) 번개는 같은 곳에 두 번 치지 않는다고들 하지만, 모르는 일이죠!
이런 자리에 홍보를 해도 괜찮을지 모르겠습니다. 부적절했다면 죄송합니다.
https://dagger.io/blog/dagger-10-beta/
제 생각에 Docker를 독보적으로 만든 건 컨테이너 기술 자체가 아닙니다. 저는 20년 전에 chroot를 썼고 아무 문제 없이 잘 돌아갔습니다. 네, 네트워크 네임스페이스도 프로세스 네임스페이스도 없었지만, 그런 게 그렇게 중요하다고 생각하지도 않습니다.
Docker를 독보적으로 만든 건 다음 세 가지였습니다.
Dockerfile이라는 개념. 이미지를 레이어 단위로 쌓아 만들고, 레이어를 캐시하고, 모든 걸 파일 하나에 담았습니다. 덕분에 이미지를 빠르게 반복해서 다듬을 수 있었고, CI 빌드를 효율적으로 구현할 수 있었습니다.
Docker 네트워크 레지스트리라는 개념. 범용 이미지를 서버에 올려 세상과 공유하는 것입니다.
기세. 전통적으로 배포가 복잡했던 수많은 소프트웨어가 갑자기 Docker 서버에 올라오기 시작했습니다. 작디작은 docker-compose 파일로 WordPress 사이트를 배포할 수 있었을 때 얼마나 신기했는지 기억납니다. 게다가 얼마나 깔끔하게 격리돼 있었는지도요. 호스트에서 흔적을 전부 지워 버릴 수 있었습니다. 저는 이것저것을 호스트에 설치할 때마다 늘 찜찜했는데, Docker가 그 찜찜함을 해결해 줬습니다.
흥미롭네요, 저라면 거의 정반대로 말했을 겁니다.
저한테 가장 큰 매력은 Docker가 컨테이너를 놀랍도록 쉽게 만들었다는 점이었습니다. 물론 직접 격리 환경을 만들려면 얼마든지 오랜 시간을 들여 알아낼 수 있었겠지만, 실제로는 대부분의 사람들이 Apache가 워커를 루트가 아닌 uid로 포크하게 하는 데서 멈췄습니다. 격리와 재현 가능한 구성을 원한다고요? VM을 하나 더 띄우고 Ansible로 세팅하면 됐죠. Docker는 여러 애플리케이션을 한꺼번에 격리하고 관리하는 가벼운 방법을 필요한 건 다 갖춘 채로 제공했습니다.
Dockerfile이요? 저는 Bash 스크립트나 tarball을 건네는 방식이었어도 만족했을 겁니다. 캐싱과 빠른 반복이요? 컴퓨팅 자원은 사실상 공짜입니다. 파일 하나로 해결한다는 점은요? 어차피 옆에 앱 소스 파일이 잔뜩 있는데
setup/디렉터리에 몇 개 더 둔다고 뭐가 달라지나요? 레지스트리는요? 공통 베이스는 필요한 의존성, 파일, 설치 후 스크립트를 제공하는deb파일 같은 것으로도 만들 수 있었을 겁니다.기세에는 저도 동의합니다. 모든 소프트웨어가 여러 쪽짜리 설치 가이드에서 명령어 하나로 줄어들고, 그러면서 내 컴퓨터 전체를 망칠 위험도 없다는 건 정말 마법 같습니다.
Dockerfile은 전혀 필수가 아닙니다. 이미지를 만드는 여러 방법 중 하나일 뿐이에요.
Bash 스크립트로도 얼마든지 이미지를 만들 수 있습니다. 예시는 여기 있습니다(바이브 코딩으로 만든 쓰레기지만 동작은 합니다): https://github.com/andi0b/vibe-todo/blob/main/docker-build.sh
그 스크립트는
docker create/docker commit/docker run등으로 docker를 호출해 레이어를 수동으로 쌓을 뿐이고, Dockerfile을 그 위의 초보적인 DSL처럼 쓰고 있습니다. 결국 "Docker가 하는 방식대로" 이미지를 만드는 건데, 오히려 실수하기 더 쉽습니다.상위 댓글이 "Bash 스크립트나 tarball을 건네는 방식이었어도 만족했을 겁니다"라고 말하려던 건, 말 그대로의 tarball을 넘길 수 있어야 한다는 뜻입니다. 예를 들어
make install DESTDIR=./out && tar -czf image.tgz -C ./out .로 얻는 것 같은 파일 말이죠. 아니면 이미 있는 다른 괜찮은 빌드 시스템의 빌드 산출물을 그냥 tar로 묶거나요. 산출물을 만들기 위해 컨테이너 맨 아래 레이어 안에서 실행해야 하는 "컨테이너화된" 작업으로 이미지 빌드를 취급할 필요가 없습니다.사실 요즘은 컨테이너 빌드를 분리하는 게 모범 사례라서, "빌드에 쓴 컨테이너이니 의존성이 반드시 들어 있다"는 말에는 이점이 없습니다. 실제로 런타임 컨테이너에 빌드 환경 전체를 넣어 배포하고 싶은 사람은 없으니까요. 그래서 빌드용 컨테이너를 하나 두고, 필요한 산출물만 골라 런타임 컨테이너에 넣습니다. 그렇다면 애초에 빌드에 컨테이너를 쓰는 의미가 뭘까요?
당연히 그렇게 할 수 있습니다. 아주 쉽게요: https://blog.ttulka.com/building-container-images-without-dockerfile/
그런데 대부분의 사람들에게는 그게 나쁜 생각입니다. 대부분은 RPATH, ldd, 여러 버전/심볼릭 링크 라이브러리 탐색 같은 게 뭔지 알 필요가 없으니까요. 설령 알았다 해도 Dockerfile은 예전에는 쉽게 할 수 없던 일을 쉽게 해 줍니다. 멀티 스테이지 빌드, 그리고 "전이적 의존성 가운데 빌드할 때만 필요했던 부분을 버린다"를 아주 견고하게 표현하는 방법이요. Dockerfile의 의미 체계는 스테이지, 병렬화, 이미지 레이어의 캐시 키 계산, 의미 단위의 레이어 쌓기(FROM)가 필요했던 데서, 그리고 단순한 사용 사례를 한눈에 들어오고 한곳에 모이게 하려는 데서 자연스럽게 나왔다고 봅니다.
저는 그렇게 할 수 없다고 말한 적이 없습니다. 상위 댓글의 예시가 그렇게 하는 예가 아니라고 지적했을 뿐입니다.
제 요점은 Dockerfile이 그다지 좋은 빌드 시스템이 아니라는 겁니다. 어려운 부분(무엇을 어떻게 빌드할지, 언제 무엇을 빌드할지)은 하나도 해결하지 않고, 스스로 만들어 낸 문제(매번 실행할 때 같은 작업을 다시 돌리지 않는 방법)만 해결하는데 그마저 형편없이 해결합니다(의존성을 추적하지 않고 줄마다 캐시됐는지 아닌지만 판단합니다). 그래서 불필요한 레이어가 생기지 않도록 모든 빌드 단계를 거대한
cmd && \줄 사슬로 이어 붙이는 끔찍한 편법까지 나오죠.제대로 된 빌드 시스템은 무엇을 빌드해야 하는지 의존성을 추적하고 도달하려는 목표(target)가 있습니다. Docker는 "빌드는 명령형으로 알아서 하세요, 캐시는 저희가 알아서 할게요"라고 할 뿐이고, 발등을 찍어 이미지가 지나치게 커지기가 아주 쉽습니다.
예를 들어 "빌드 컨테이너: 이 빌드를 해서 결과물을 여기에 두고, 런타임 컨테이너: 그 결과물을 가져다 여기에 저장"이라고 하면서 빌드 컨테이너에 다른 곳에선 쓰이지 않는 임시 레이어를 만들지 않을 방법이 없습니다. 그래서 산출물이 1GB라면 빌드할 때마다 항상 2GB가 필요합니다. 런타임 컨테이너에 하나(원하는 위치), 빌드 컨테이너에 하나(잠깐만 필요했던 것)요. 디스크가 어김없이 가득 찰 때마다 가끔 "docker builder prune"을 해 줘야 하고, 애초에 중복본을 만들지 않게 할 방법은 없습니다.
(제 우회법은 산출물을 type=cache 마운트에 두고, 그 SHA 합계를 빌드 컨테이너에 저장한 다음, 런타임 컨테이너에서 type=cache 마운트의 산출물을 가져와 SHA 합계를 비교해 바뀌지 않았는지 확인하는 겁니다. 캐시 마운트는 언제든 GC될 수 있어서 이 방법이 동작한다는 보장조차 없지만요.)
예전에 Docker를 대규모로 썼을 때 가장 잘 먹혔던 방식은 늘 이랬습니다. 산출물 디렉터리를 빌드 컨테이너에 바인드 마운트하고 빌드를 돌립니다. 그런 다음 산출물 디렉터리를 패키징합니다. 런타임에는 산출물을 가져와 런타임 컨테이너에 바인드 마운트합니다. 그러면 docker 레이어를 만지작거리는 대신 평범한 HTTP 서버 위의 진짜 아티팩트 저장소를 쓸 수 있고(Dockerfile에 &&를 충분히 안 붙였다고 1KB짜리 레이어 100개를 푸시할 걱정도 없습니다), 실제로 어떤 docker 레지스트리보다 훨씬 빨랐습니다.
Dockerfile은 단순한 작업에는 훌륭하지만, 단일 바이너리를 만들어 내는 훌륭한 빌드 시스템이 이미 있다면 그냥 그걸 쓰는 쪽이 훨씬 쾌적합니다.
그렇게 하는 것도 아무도 막지 않습니다.
수정: 아니면 뭔가가 그렇게 하는 걸 막고 있나요? 다들 Dockerfile이 싫다고 하면서, 다르게 하면 되는데도(가능합니다, 그냥 tar 파일과 매니페스트일 뿐이에요) 계속 불평만 하는 것 같습니다.
저는 보통 bazel로 파일 하나하나 단위로 최소한의 이미지를 만듭니다. 완전히 hermetic하게요.
#1과 #2가 기술적으로 Docker를 "독보적"으로 만든 요소라는 데는 동의하지만, 그게 Docker의 혁신이었다고는 생각하지 않습니다.
둘 다 몇 년 전 https://www.usenix.org/legacy/event/lisa11/tech/full_papers/Potter.pdf (자세한 내용)와 https://www.usenix.org/conference/usenix-atc-10/apiary-easy-use-desktop-application-fault-containment-commodity-operating (동기를 부여하려고 "그럴싸한" 사용 사례로 보여 준 것)에 기술돼 있습니다. (그리고 저는 사람들이 "그럼 당신이 컨테이너를 발명했다는 거예요?"라고 말하면 짜증이 납니다. Docker와 컨테이너를 동일시해서 하는 말이거든요. 저는 이렇게 답합니다. 아니요, 컨테이너는 70년대 말~80년대 초 메인프레임의 논리 파티션까지 거슬러 올라갈 만큼 오래전부터 있었습니다. 제가 주장한 건 컨테이너용 파일 시스템을 빌드하고 배포하는 새로운 방법이고, 그 덕분에 컨테이너가 훨씬 유용하고 가치 있어졌다는 것, 그리고 apiary에서는 그걸 활용해 데스크톱 보안을 높인 새로운 데스크톱 구성이었다는 것뿐입니다.)
유니온 파일 시스템을 쓴 초기 Docker 구현(aufs를 쓰는 Docker)조차 거기에 기술된 것과 똑같았습니다.
Docker가 독자적으로 생각해 냈다 하더라도(LISA나 Usenix ATC 같은 학회는 논문이 발표되는 곳이자 dotcloud/Docker 같은 회사들이 제품을 홍보하던 곳이고, 실제로 Docker Inc도 거기 전시 업체로 참가했으니 숨겨진 일도 아닙니다), Docker의 독창성과 논문에 기술된 내용 사이의 차이는 사소하고(물론 다소 편향됐을 수 있는 제 의견입니다), 제가 먼저였던 건 분명합니다.
저는 기세가 나머지 둘보다 훨씬 중요하다고 생각합니다. Makefile로도 이미 캐싱이 되는 레이어 구조를 만들 수 있었고, 아티팩트 저장소도 오래전부터 있었으니까요.
하지만 Docker를 탐탁지 않아 하는 환경에서 제가 Docker를 옹호할 때 썼던 논거는, 리눅스 컨테이너가 사실상 표준 배포 단위가 됐다는 점이었습니다. 그 전제로 작성된 도구가 아주 많고, 그런 도구를 쓰려면 Docker와 별로 엮이고 싶지 않더라도 배포물을 리눅스 컨테이너로 패키징해야 합니다. 그래서 그렇게 기세가 대단했던 거죠.
그리고 빠뜨리신 네 번째 요소는 Docker가 쓰는 개념이 비교적 단순하다는 점이라고 생각합니다. 저는 리눅스 컨테이너가 뭔지 알기 전에 "리눅스 사용자, cgroup, 네임스페이스 같은 걸로 프로세스를 격리할 수 있는데 Docker를 왜 신경 써야 하지?" 하고 생각하곤 했습니다. 그때 몰랐던 건, "리눅스 사용자, cgroup, 네임스페이스 등"이 바로 Docker가 친절한 UI를 입혀 준 대상이라는 사실이었습니다.
저는 대체로 Podman을 선호하지만, Docker는 정말 대단했고(지금도 그렇고) 이른바 "트렌치코트 하나에 들어간 서로 다른 리눅스 커널 기능 5개" 위에 훌륭한 개발자 경험(DX)을 얹었습니다. 그게 핵심 매력이죠. 이미 있었거나 개발 중이던 OS 기능을 최대한 활용하는 아주 가벼운 방식인데, 그 기능들은 쓰기 불편했고 전문 지식이 잔뜩 필요했으니까요.
Postman은 Docker의 이런 이상한 점들을 피해 가나요? 아니면 일부만요?