아무도 말하지 않는 Docker 의존성 문제 (하지만 모두가 느낀다)
Source: Dev.to
Before Docker
- “It works on my machine” 은 환경 불일치를 의미했다.
After Docker
- “It works in my container” 라고 해도 프로덕션에서 동작한다는 보장은 없다.
New Mismatches
- 베이스 이미지 차이.
- 누락된 시스템 라이브러리.
- 미묘한 커널 동작 차이.
- 아키텍처 불일치 (amd64 vs arm64 – 고통은 실재한다).
우리는 일관성을 없앤 것이 아니라, 그것을 캡슐화했다.
Inside a Docker Image
- 이미지는 깔끔하고 독립적인 것처럼 보이지만, 내부에서는:
- Debian / Alpine / Ubuntu 버전이 중요하다.
libc버전이 조용히 모든 것에 영향을 미친다.- OpenSSL 버전이 프로덕션에서 인증을 깨뜨릴 수 있다.
- Python / Node 베이스‑이미지 태그가 시간에 따라 조용히 바뀐다.
당신의 “간단한 컨테이너”는 실제로 한 순간에 고정된 깊은 의존성 트리이며, 문제가 발생하면 레이어 안의 레이어를 디버깅하게 된다.
Docker Build Cache Pitfalls
-
보이는 마법:
- 빠른 빌드.
- 재사용된 레이어.
- 즉각적인 피드백.
-
실패할 때:
- 캐시 무효화가 예측 불가능하다.
- 작은 Dockerfile 변경이 무관한 레이어를 깨뜨린다.
- “No cache” 빌드가 갑자기 다르게 동작한다.
이 시점에서 디버깅은 엔지니어링이라기보다 고고학에 가깝다.
Service Sprawl
Docker는 서비스를 쉽게 띄울 수 있게 만든다—너무 쉽게.
- 로컬에서 12개의 컨테이너가 실행될 수도 있다.
- 서비스 A가 B에, B가 C에 의존한다.
- 환경 변수는 세 레이어를 거쳐 전달된다.
docker‑compose파일은 스파게티‑아키텍처 다이어그램처럼 보인다.
이제 디버깅은 단일 시스템이 아니라, 살아있는 의존성 네트워크를 재구성하는 일이 된다.
Reproducibility Trade‑offs
Docker의 가장 큰 약속은 재현성이고, 실제로 제공한다—대가를 치르고:
- 동일한 환경을 얻는다.
- 하지만 왜 동작하는지에 대한 가시성을 자주 잃는다.
- 모든 것이 “동작하니 건드리지 마”가 되어, 시스템을 이해하는 문화에서 아티팩트를 신뢰하는 문화로 전환된다.
Conclusion
Docker가 악당은 아니다; 우리가 이미 가지고 있던 복잡성을 비추는 거울일 뿐이다:
- 의존성 체인.
- 환경 드리프트.
- 서비스 간 숨겨진 결합.
그 복잡성을 충분히 가려서 존재한다는 사실을 잊게 만든다—2 AM에 뭔가 깨질 때까지. 진짜 교훈은 현대 IT가 복잡성을 없앤 것이 아니라, 그것을 포장하는 방법을 배웠다는 것이다.