Docker를 사용하며 내가 겪었던 문제들

starkensin·2021년 7월 1일
1
post-thumbnail

inspect는 내 친구!
docker network inspect, docker volume instpect 등의 방식으로 사용할 수 있으며, 많은 정보를 추가로 제공해 주는 유용한 명령어 입니다.

내가 겪었던 문제들


1. localhost를 사용하며 컨테이너 환경에서도 그것이 문제 없이 동작할 것이라고 착각했다.

호스트 머신 및 컨테이너의 ip와 port

docker로 컨테이너 환경을 구축하기 이전에 '로컬 개발 환경'에서 shop-service와 api-gateway 모두 ip를 localhost로 설정하여 개발을 진행했습니다. 클라이언트에서 호스트 머신의 api-gateway로 요청을 보내면 api-gateway는 요청을 shop-service로 라우팅 해줘야 합니다.

만약 컨테이너화 되어있지 않았다면 shop-service와 api-gateway의 localhost192.168.155.49로 동일했을 것입니다. 하지만 컨테이너 환경에서 각 컨테이너는 고유한 ip를 가지기 때문에 이제 shop-service의 localhost와 api-gateway의 localhost는 각각 다른 ip를 지칭하게 됩니다.

이 사실은 인지하면 당연한 것이지만, 인지하지 못하면 어떤 상황인지 추적하기 힘든 네트워크 문제가 되어버립니다. 저는 이 문제로 당황을 한 경험이 있습니다.

기억합시다! 각 컨테이너는 고유한 ip를 가진다.

!주의: kubernetes에서 동일한 pod 내부의 모든 컨테이너는 동일한 localhost를 갖게 됩니다.

2. 파일 동기화에 대해서 명확히 이해하지 못하고 사용했다.

docker는 어떠한 운영체제 위에서 동작하냐에 상관 없이 두 가지 마운트 방식으로 호스트와 컨테이너의 파일을 동기화 시킬 수 있습니다.

  • Volumes
  • Bind mounts

두 방식 모두 파일 동기화라는 목적을 달성할 수 있습니다. 저는 처음에 튜토리얼 등의 자료를 보며 시작할 때 내가 어떠한 방법을 사용하는지, 파일 동기화가 어떤식으로 되는건지 명확히 이해하지 못한 채로 사용했습니다.

그러다 보면 언젠가 문제에 직면하게 될 가능성이 농후할 뿐만 아니라 상황에 적합한 방식을 택할 수 없게 되죠.

바인드 마운트

도커 호스트와 컨테이너간에 소스코드나 빌드 결과물을 공유할 수 있습니다. 이는 실시간으로 코드가 자주 변경되는 개발 환경에서 매우 유용합니다.

도커프로세스가 아닌 다른 방법으로 언제든지 쉽게 수정될 수 있습니다.

볼륨

볼륨은 도커안에 있는 데이터를 지속시키는 최고의 방법이라고 할 수 있습니다.

볼륨을 생성하면 도커 호스트 디렉토리에 저장이 됩니다. 볼륨을 컨테이너에 마운트하면 그 디렉토리가 컨테이너에 마운트 되는 것이죠. 볼륨이 도커에 의해 관리되고 호스트 머신의 코어 기능과 격리된다는 점에서 바인드 마운트와 차이점이 있지만 둘은 같은 결과를 가져옵니다.

host filesystem에 저장되는 volumes는 도커가 관리합니다. (/var/lib/docker/volumes/ on Linux)

특징

  • 볼륨은 여러 컨테이너에서 동시에 사용할 수 있습니다.
  • 해당 볼륨을 사용하고 있는 컨테이너가 없더라도 지워지지 않습니다.
  • 바인드 마운트보다 빠릅니다.(운영체제의 파일시스템을 거쳐서 관리되는 것이 아닌, 도커에 의해 직접 관리 되는 것이기 때문)
  • 볼륨을 사용하는 컨테이너의 크기를 증가시키지 않습니다.

추가 팁


1. 도커 이미지와 컨테이너 조금 더 이해하기

도커에는 크게 두 가지 layer가 존재합니다. → container layer, image layer

도커는 이미지를 계층화해서 구성하는데, FROM, COPY, RUN, CMD 명령어는 각각 layer를 생성 합니다.

이미지와 컨테이너의 가장 큰 차이는 writable layer의 유무입니다.
한 이미지로 여러 컨테이너를 생성할 수 있는데, writable layer는 공유되지 않고 있는걸 확인 할 수 있습니다.

2. 적절한 캐싱으로 더 빠른 도커 빌드

동료가 코드 리뷰로 제안을 해주었는데, 기존 방안과 비교를 해보았더니 기존 방법이 더 좋은 결과를 얻을 수 있었습니다.

그런데 저는 왜 그런지 궁금했습니다.(일전에는 그냥 지나쳐서 기억하지 못하고 있었습니다.)

그래서 왜 그런가?? 알아보았습니다.

  • 도커 이미지 빌드시 layer 마다 step이 나뉜다.
  • 특정 스텝에서 캐싱되어있다면 빠르게 그 스텝을 수행할 수 있다.

node_modules는 변경 빈도 수가 낮습니다. 소스 코드가 변경되었더라도 크기가 매우 큰 node_modules를 캐싱한다면 더 빠르게 도커 이미지를 빌드할 수 있습니다.

이사실은 제가 코드로 작성한 부분이지만 명확하게 기억하지 못하고 있었습니다.이번 기회에 정리하고 공유할 수 있게 되었네요. 동료 덕분입니다. 고맙습니다.

3. multi-stage builds를 활용하자

... 추가 예정

4. production 환경과 development 환경의 차이를 이해하자

... 추가 예정

환경별 file/data 동기화

Development: 컨테이너가 소스코드에 접근하기 위해서 바인드 마운트를 사용하자.
Production: 컨테이너의 데이터를 저장하기 위해서 볼륨을 사용하자.

마치며


이 문서가 도움이 되길 바랍니다. 🙂

0개의 댓글