[Docker]초짜의 삽질기 리뷰 2 (feat. Django Dockerizing)
SW개발/개발이야기

[Docker]초짜의 삽질기 리뷰 2 (feat. Django Dockerizing)

Django 이미지를 만들어 냈던 기쁨도 잠시 Postgres, Redis, Websocket과 같은 스택들을 컨테이너화 시켜야 되는 작업들이 남아있었습니다. 하지만, 이를 만들어내는 과정은 생각보다 엄청난 속도로 구현할 수 있었습니다!!

 

한줄기의 빛.. Docker hub

Docker hub의 빛

Postgres와 같은 스택들도 Dockerfile을 작성하여 우분투 환경에 설치하고, Dockerfile을 작성하고, 이미지를 빌드하는 힘든 작업이 될거라 예상했지만 단순하게 끝났습니다. Github와 비슷한 것처럼 Docker에는 Docker hub라는 곳이 존재합니다. official 이미지나 사용자들이 커스텀 해놓은 이미지들을 받아서 사용할 수 있는 곳이죠. 저는 이곳에서 Postgres, redis와 같은 스택들을 띄울 컨테이너의 이미지로 Docker hub의 official 이미지를 사용하기로 결정했습니다.

 

이 덕분인지 불필요한 세팅과정은 전부 생략할 수 있었고 docker-compose.yml에 몇가지의 옵션만 설정해 주는 것으로 아주 간편하게(?) 컨테이너를 구동시킬 수 있었습니다. 이미지로 모든 것이 구동되는 도커에서 이를 공유하는 공식 저장소가 존재한다는 것은 정말 엄청난 Docker의 장점이 아닐까 싶습니다.

 

기쁨도 잠시

Postgres, Redis, RabbitMQ와 같은 스택들은 offcial 이미지를 사용하는 것으로 결정했습니다. 하지만 제 프로젝트의 스택중에는 파이썬 위에서 구동 해야하는 Celery, Websocket, 또 Vue 파일을 빌드하기 위한 node 환경이 필요 했는데 이 스택들의 공통점은 전부 소스코드가 존재하는 컨테이너가 필요하다는 것이었습니다. 

 

처음에 바로 들었던 생각은, "아 그럼 Dockerfile을 여러개 만들고 이 이미지로 컨테이너를 각각 띄우면 되겠다" 였습니다.

하지만, 조금 더 생각해보니 이미지를 빌드하는데 걸리는 시간(캐싱이 되어있기는 하지만)과 중복된 Dockerfile이 생기는 것에 대한 문제점이 존재함을 깨달았습니다.

 

막히면 항상 드는 생각이 있습니다. "대체 다른 사람들은 일반적으로 어떻게 하는거지? 지금 내가 만드는 구조가 맞는 건가?"

이렇게 또 무한 검색과, 아는 지인의 찬스를 통해서 답변을 얻을 수 있었습니다.

정답은 바로 간단한...빌드된 이미지 파일을 재 사용하는 것 입니다. 

 

도커의 경우 이미지를 빌드하면 레이어로 하여 그 결과를 로컬 PC에 저장시켜 둡니다. 이 때 이름을 지정해두고 해당 이름을 docker-compose.yml에 적어준다면 로컬의 이미지를 가져다 사용할 수 있습니다. 즉, 하나의 이미지로 동일한 환경의 컨테이너를 여러개 생성할 수 있다는 뜻입니다. 이를 활용해 Django 환경이 구축된 컨테이너를 여러개 띄울 수 있었고 이 위에서 앞서 언급한 스택을 구동할 수 있었습니다.

 

예상과 달리 발목을 잡는 Nginx

위에서 언급한 스택들은 전부 기술과 관련된 것이었다면 저희 프로젝트에서는 Nginx라는 스택이 포함되어 있습니다. 가장 큰 목적으로는 리버스 프록시 용도로 사용하고 있는데, 이것을 세팅하는 과정이 진짜 그 무엇보다도 잘 안됐던 것 같습니다.

웹소켓을 open 하거나 요청이 들어올 때 port 번호를 바꾸어 넘겨주는 것에 대한 세팅이 기존 Nginx에 되어있었습니다.

 

설정을 비슷하게 옮겨 놓는 과정, 호스트 포트와 바인딩을 하는 방법, proxy할 주소에는 도커 컨테이너 명을 넣을 수 있다는 점, url 마지막 /의 부재 등 정말 문제들이 복합적으로 얽혀있던 작업이었습니다. 특히나 구글에는 제 프로젝트와 거의 유사한 상황을 보여주는 자료가 전혀 없었기에 더 헤맸던 것 같습니다. (다른 상황의 세팅파일들을 많이 보면서 조합해서 해결했습니다)

 

진짜 끝이 보인다!

Nginx의 세팅이 끝나자 드디어 채팅이 실시간으로 되는 것을 확인할 수 있었습니다. (제 프로젝트는 메신저 입니다) 진짜 이때의 기쁨은...말로 다할수 없었습니다. 막상 완료를 하고보니 Nginx쪽의 설정은 생각보다 간단해 보였습니다.

 

M1  Mac 의 한계?

저희 회사에서는 개발환경으로는 Mac을 사용하고 있습니다. 최근에 M1 Mac이 출시하면서 몇대를 구입 했기 때문에 팀 내에서는 Intel, M1 Mac이 공존하는 상태였습니다. 개발환경을 컨테이너로 구축하고 이제 직접 사용해보면서 피드백을 받아보는 과정이었습니다.

하지만, 뭔가 이상하게 컨테이너에서의 명령어 속도가 느리다고 체감이 되기 시작하였습니다. 그래서 기존 VM 환경과 비교해보니 역시나 !! 2배 정도는 느렸습니다!!

 

애써 힘들게 구축한 환경인데 실제로 개발을 할 때 답답하다면 만든 저라도 사용하기 싫을 것 같았습니다.. 또 해결하기위해 저는 무한 검색, 무한 삽질을 반복하게 됩니다. 네, 대표적인 이슈로 호스트의 디렉토리를 바인딩 하면 퍼포먼스가 저하되는 Docker volume에 관한 자료들이 있네요. 정말 제 증상과 거의 동일하다고 느꼈기에 이거다 싶었습니다.

해결책으로는 docker-sync, mutagen 같은 3rd 라이브러리가 있었습니다. Docker, Docker-compose를 새롭게 배우는 것도 모자라 이제는 3rd 라이브러리까지 사용해보려니 정말 시작이 쉽지 않았습니다. 그렇게 위에 언급한 2가지를 모두 적용해본 결과...달라진 것이 없었습니다?! 

 

따라서 저는 아예 volume 옵션을 제거하고 컨테이너에 접속하여 명령어의 속도를 비교해보기 시작합니다. 여전히 느립니다!! "아..volume 문제가 아니구나" 라는 것을 이제야 깨닫게 됩니다. 그 후 Intel Mac에서 실행해보니? Wow 너무 빠릅니다.

이렇게 M1 mac이 문제가 있다는 것을 알아차립니다. 심지어 컨테이너에서 go lang 빌드가 종종 에러가 발생하였는데 그 증상 역시 말끔히 사라졌습니다. 

 

 

M1 mac에서는 Docker의 퍼포먼스를 제대로 못쓰는 건가.. 하면서 굉장히 큰 좌절감에 빠지게 됩니다. 혹시 놓친 부분이 없나 하고 살펴보니 Docker file에서 우분투 이미지의 architecture를 x86_64로 설정해 두었던 것이 기억이 납니다.

불타는 도전정신과 함께 x86_64 -> arm64로 우분투 이미지를 변경해봅니다.

 

이제는 정말 언제 누가 그랬냐는 듯이 모든 것이 매우 빠르고 정확하게 동작합니다!! 현재 M1 mac에서의 x86_64 운영체제를 사용할 때 performance 이슈가 있는 것으로 확인이 되고 있습니다. 어쨋든 해결을 하였으니 도커를 구동하는 각 OS에 맞게 분기처리 할 수 있는 로직을 Dockerfile에 추가해두면서 마무리 하였습니다.

마치며..

이번 포스팅도 마찬가지로 여러 가지 상황을 적다보니 굉장히 길어졌습니다. 다음번 포스팅을 마지막으로 여태까지의 느낀 점과 현재는 Docker로 개발을 실제로 진행중인지? 정말 좋은지? 에 대해서 다뤄보도록 하겠습니다!

 

긴 게시글 읽어주셔서 감사합니다.

 

728x90