목차
이번 글에서는 Docker 에 대해서 공부한 내용을 정리해보려 합니다.
Docker 가 무엇인지, 어떤 식으로 프로세스가 진행되는지 알아보겠습니다.
Docker
Docker 란 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 컨테이너 기반인 오픈소스 가상화 플랫폼 입니다.
Docker는 소프트웨어를 컨테이너라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있습니다.
Docker를 사용하면 환경에 구애 받지 않고 애플리케이션을 신속하게 배포 및 확장할 수 있으며 코드가 문제 없이 실행될 것임을 확신할 수 있습니다.
Docker 기술은 왜 등장하게 되었을까요?
Docker 등장 배경
Docker 는 소프트웨어 개발과 배포 과정에서 발생하는 일관성 문제와 환경 차이 문제를 해결하기 위해 등장했습니다.
대부분 개발자는 자신의 개발 환경에서 코드를 작성하고 테스트 합니다. 하지만 "내 시스템에서는 잘 작동하는데, 다른 시스템에서는 왜 안 될까?" 라는 문제가 자주 발생했습니다. 이는 개발 환경과 운영 환경이 다르기 때문에 발생했습니다.
Docker 는 어떤 방식으로 개발 환경과 운영 환경이 다른 문제점을 해결했을까요? 그것을 알기 위해서는 가상화 기술을 먼저 알아야 합니다.
가상화 기술
가상화란 하드웨어, 운영체제, 소프트웨어, 네트워크 등 다양한 컴퓨팅 리소스를 대상으로 하여 리소스를 추상화하고 분할하여 여러 개의 독립된 환경으로 만드는 기술입니다.. 가장 흔한 예로는 VM (Virtual Machine, 가상머신)이 있습니다.
VM을 사용하면 하드웨어 리소스를 더욱 효율적으로 사용할 수 있으며, 다양한 운영체제를 한 물리적인 머신에서 동시에 실행할 수 있습니다. 또한, VM을 쉽게 생성하고 복제할 수 있으므로, 애플리케이션의 배포와 스케일링이 더욱 쉬워집니다.
즉 안정성도 높이면 리소스도 최대한 활용할 수 있는 방법으로 나타난게 서버 가상화 입니다.
그런데 Docker는 전통적인 VM과는 조금 다른 방식의 가상화 기술을 사용합니다.
Docker는 "컨테이너"라는 형태의 가상화를 제공하는데, 컨테이너는 VM보다 훨씬 가볍고 빠르게 실행됩니다.
컨테이너는 어떻게 VM보다 가볍고 빠르게 실행할 수 있는 걸 까요?
컨테이너
컨테이너는 가상화 기술 중 하나로 대표적으로 LXC(Linux Container)가 있습니다. 컨테이너는 애플리케이션과 그 애플리케이션을 실행하는데 필요한 모든 소프트웨어 종속성을 패키지화하고 격리하는 소프트웨어 기술입니다. 이 컨테이너는 어떠한 컴퓨터 환경에서도 일관되게 작동하도록 설계되어 있습니다.
컨테이너는 가볍고 빠르게 시작될 수 있으며, 여러 컨테이너가 동일한 운영 체제 커널을 공유할 수 있습니다. 각 컨테이너는 서로 분리되어 있으며, 각자의 파일 시스템, 사용자, 그룹 ID, 네트워크 인터페이스 및 실행 중인 프로세스를 가지고 있습니다.
이러한 특성 덕분에 컨테이너는 마이크로서비스 아키텍처, 지속적인 통합 및 배포(CI/CD), 데브옵스(DevOps) 등의 모던 개발 패러다임에 매우 적합합니다.
VM은 전체 OS(운영체제)를 가상화하여 사용한 반면 Docker는 하나의 OS에서 독립적인 실행 환경(컨테이너)을 만드는 것에 중점을 둡니다.
가상 머신과 컨테이너 가상화의 차이점에 대해 좀 더 알아보도록 하겠습니다.
VM 가상화 플랫폼 vs Docker 가상화 플랫폼
전통적인 가상 머신은 Host OS(운영체제) 위에 가상화를 시키기 위한 Hypervisor 엔진, 그 위에 Guest OS 를 올려 사용합니다. 이는 가상화된 하드웨어 위에 OS가 올라가는 형태로 거의 완벽하게 Host와 분리된다고 봐도 무방합니다.
반면 컨테이너 기반 가상화는 Docker 엔진 위에 Application 실행에 필요한 바이너리와 라이브러리만 올라가게 됩니다. 가상 머신을 보면 Host OS 와 완전히 분리된다는 장점이 있지만 OS 위에 OS가 올라가기 때문에 무겁고 느릴 수 밖에 없습니다.
하지만 컨테이너 기반 가상화는 Host OS, Docker 엔진 위에서 바로 동작하며 Host OS의 커널을 공유합니다. 커널을 공유하게 되면 io 처리가 쉽게 되어 성능 효율을 높일 수 있고 메모리, CPU, 디스크 공간 등의 리소스를 더욱 효율적으로 사용할 수 있습니다.
컨테이너를 사용하는 것은 가상 머신을 생성하는 것이 아니라 Host OS가 사용하는 자원을 분리하여 여러 환경을 만들 수 있도록 합니다.
이렇게 쓰면 컨테이너가 가상 머신 보다 무조건 뛰어난 거 같지만 그렇지도 않습니다.
가상 머신은 컨테이너 기반 가상화 보다 더 높은 격리 레벨을 지원합니다. 즉, 보안적인 측면에서 더욱 유리 합니다.
또한 Host OS와 커널을 공유하지 않아 멀티 OS가 가능합니다. 즉, 하나의 호스템 시스템 위의 다양한 유형읜 가상 머신 (Linux, Windows) 을 실행할 수 있습니다. 반면 컨테이너는 호스트 시스템의 커널을 공유하기 때문에, 호스트와 같은 운영체제에서만 실행할 수 있습니다.
Docker는 하나의 Host OS 커널을 공유하기 때문에 다른 컨테이너나 호스트 시스템에 영향을 줄 수 있는 취약성이나 버그에 더 노출되어 있을 수 있습니다. 따라서 보안에 주의를 기울여야 합니다.
즉, 사용자의 환경에 맞게 가상 머신과 컨테이너 기반 가상화를 골라 사용하면 됩니다. 그렇다면 Docker가 사용하기에 어떤 장점이 있는지 알아보겠습니다.
Docker 장점
Docker는 장점은 환경 일관성, 배포의 단순화, 이식성, 리소스 효율성으로 볼 수 있습니다. 하나씩 알아보겠습니다.
환경 일관성
Docker는 애플리케이션과 그 의존성을 하나의 독립적인 패키지인 Docker 이미지로 캡슐화 합니다. 이 이미지는 어떤 Docker 환경에서도 동일하게 적용됩니다. 즉 개발자는 ‘내 컴퓨터에서 잘 작동했는데 여기서 안되네’ 같은 문제가 일어날 일이 줄어듭니다.
배포의 단순화
Docker 이미지는 모든 의존성과 함께 애플리케이션이 포함되있으므로, 이 이미지를 Docker가 설치된 어떤 시스템에서도 쉽게 실행할 수 있습니다. 이로 인해 애플리케이션 배포가 빠르고 쉬워집니다.
이식성
Docker 컨테이너는 호스트 OS에 묶여있지 않으므로, 개발 환경에서 테스트 환경, 프로덕션 환경으로 쉽게 이동할 수 있습니다. 또한 클라우드 환경에서 로컬 환경으로, 또는 반대로 이동하는 것도 가능합니다.
리소스 효율성
Docker 컨테이너는 가상 머신에 비해 훨씬 적은 시스템 리소스를 사용합니다. 각 컨테이너는 별도의 OS를 실행하지 않으므로 더 적은 메모리와 CPU를 사용하며 더 빠르게 시작합니다.
Docker 가 컨테이너 기반 가상화 플랫폼이고 위의 4가지 장점으로 인해 많이 사용된다는 것을 알았습니다.
그럼 이제 Docker 가 어떤 과정을 거쳐 애플리케이션을 배포하는지 알아보겠습니다.
Docker 배포 과정
Docker는 다음 과정을 거쳐 애플리케이션을 컨테이너화 해서 배포합니다.
- Dockerfile 작성
- Docker image 생성
- Docker image 저장
- Docker container 실행
각 단계별로 하나씩 알아보겠습니다.
Dockerfile 작성
Dockerfile이란 Docker 이미지를 생성하기 위한 설정 파일입니다. 이 파일은 애플리케이션과 그 실행 환경을 정의하는데 사용되며, Dockerfile에 정의된 지시문에 따라 Docker 는 실행 가능한 이미지를 빌드합니다.
위의 Dockerfile은 프로젝트를 진행하면서 제가 실제로 사용한 파일입니다.
보시는 바와 같이 명령어들이 나열된 형태로 작성되며 각 line의 맨 앞은 대문자로 이루어진 지시어로 시작됩니다.
Dockerfile에 대한 자세한 내용은 따로 포스팅을 하겠습니다.
Docker 이미지 생성
Docker 이미지란 애플리케이션을 실행하는데 필요한 파일과 설정값들을 담아둔 패키지 파일 입니다. 앞에 말한 것 처럼 Docker 이미지는 Dockerfile 에서 빌드됩니다. Dockerfile을 통해 Docker 이미지를 빌드하면 동일한 설정으로 Docker 이미지를 생성할 수 있습니다.
이미지란 이름에 맞게 컨테이너 안에 담긴 것들을 사진을 찍어두듯 저장해 둔 스냅샷이라 생각하면 됩니다. 운영 체제, 사용자가 추가한 파일, 메타데이터 등을 포함하는 이 스냅샷은 컴퓨터에서 다른 컴퓨터로 쉽게 전송할 수 있습니다. Docker 이미지는 버전 관리되며, 여러 개발자 사이에서 쉽게 공유할 수 있습니다.
이미지에 대해 더 잘 알기 위해서 이미지가 어떻게 만들어지는지 알아보겠습니다.
다음 그림을 보면 ubutu 이미지를 만들기 위해서 Layer A,B,C 가 들어갑니다. 그럼 nginx 이미지를 만든다고 생각했을 땐 어떨까요? 이미 만들어진 A,B,C 인 ubuntu 이미지를 베이스 이미지로 사용하여 nginx 만 더하게 됩니다. 결과적으로 A,B,C,nginx 가 더해진 것이지만 과정은 ubuntu + nginx 가 더해진 것 입니다. 이런 식으로 베이스 이미지를 기반으로 새로운 층을 올려 Docker image를 생성합니다.
위의 그림에서 보듯 Docker 이미지는 층층이 쌓인 Layer 구조로 이루어져 있습니다. 이 layer는 읽기 전용으로 구성되어 있고 파일이 추가되면 새로운 Layer가 생성되는 식 입니다. Docker 가 컨테이너를 만들 때 각각의 layer 에 있는 파일들을 가져오게 됩니다. 즉 기존 Layer + 추가 Layer 다운 받아 만들게 되는데 로컬에 이미 존재하는 layer의 경우 다시 다운로드 받을 필요가 없이 추가 Layer 만 다운받기 때문에 빠르게 컨테이너를 실행할 수 있는 장점이 있습니다.
즉 이미지를 보다 세세하게 나누어서 자원 효율화를 높인 구조라 볼 수 있습니다.
Docker 이미지의 특성은 다음과 같습니다.
- Docker 이미지의 용량은 수백MB ~ 수GB 가 넘습니다. 하지만 가상 머신 이미지에 비하면 굉장히 작은 용량 입니다.
- 이미지는 상태 값을 가지지 않고 변하지 않습니다.
- 하나의 이미지는 여러 컨테이너를 생성할 수 있고, 컨테이너가 삭제되더라도 이미지는 변하지 않고 그대로 남아 있습니다.
- Docker 이미지들은 github와 유사한 서버스인 DockerHub를 통해 버전 관리 및 배포가 가능합니다.
- 다양한 API가 제공되어 원하는 만큼 자동화가 가능합니다.
- Docker는 Dockerfile 이란 파일로 이미지를 만듭니다. Dockerfile에 소스와 함께 의존성 패키지 등 사용했던 설정 파일을 버전 관리하기 쉽도록 명시되어 집니다. (그래서 누구나 이미지 생성과정을 확인할 수 있으며 수정도 할 수 있습니다.)
Docker 이미지 저장
Docker 이미지는 주로 Docker 레지스트리에 저장됩니다. Docker 레지스트리는 Docker 이미지를 저장하고 배포하는 서비스를 말합니다.
가장 널리 알려진 Docker 레지스트리로는 DockerHub 얘기할 수 있겠습니다.
DockerHub 란 Docker 이미지를 생성, 저장, 공유하기 위한 클라우드 기반 서비스입니다. 이는 GitHub와 같은 공개 소프트웨어 레포지토리와 비슷한데요. 하지만 DockerHub는 코드 대신 Docker 이미지를 저장합니다.
DockerHub의 주요 기능은 다음과 같습니다:
- 이미지 호스팅: DockerHub는 개인적으로 또는 팀과 함께 사용할 수 있는 Docker 이미지를 저장할 수 있는 공간을 제공합니다. 이는 사용자가 이 이미지를 어디서나 사용할 수 있도록 하는 중요한 역할을 합니다.
- 공개 및 비공개 레포지토리: DockerHub는 사용자가 자신의 이미지를 공개적으로 공유하거나 비공개로 유지할 수 있게 합니다. 공개 레포지토리는 누구나 다운로드할 수 있지만, 비공개 레포지토리의 경우 권한이 있는 사용자만 접근할 수 있습니다.
- 자동 빌드 및 웹훅: DockerHub는 GitHub 또는 Bitbucket와 연동하여 Dockerfile이 있는 소스 코드 레포지토리를 통해 Docker 이미지를 자동으로 빌드하고 업데이트하는 기능을 제공합니다. 이는 개발 및 배포 프로세스를 자동화하고, 팀이 더 효율적으로 작업할 수 있게 합니다.
- 이미지 버전 관리: DockerHub는 이미지의 다양한 버전을 관리하고 추적하는 데 도움이 됩니다. 이를 통해 사용자는 애플리케이션의 이전 버전을 쉽게 찾을 수 있고, 필요한 경우 이전 상태로 롤백할 수 있습니다.
DockerHub를 사용하면 개발자는 자신이 만든 Docker 이미지를 쉽게 공유하고, 또 다른 개발자들이 만든 수많은 이미지를 검색하고 다운로드할 수 있습니다. 이는 Docker의 가장 강력한 기능 중 하나인 이미지의 재사용성을 극대화하는 데 큰 도움이 됩니다.
Docker 컨테이너 실행
Docker 컨테이너를 실행하는 것은 Docker 이미지를 메모리에 로드하고 실행하는 것을 의미합니다. Docker 컨테이너는 격리된 환경에서 실행되며, 각 컨테이너는 별도의 프로세스와 네트워크 인터페이스를 가집니다. 컨테이너는 호스트 시스템의 커널을 공유하지만, 그 외의 시스템 파일, 라이브러리, 애플리케이션 등은 컨테이너 내부에 존재합니다.
Docker 컨테이너를 실행하는 기본 명령어는 다음과 같습니다.
docker run <이미지 이름>
이 명령은 지정된 Docker 이미지를 찾아 해당 이미지를 기반으로 Docker 컨테이너를 생성하고 실행합니다.
다양한 옵션을 사용하여 docker run 명령을 구성할 수 있습니다. 예를 들면, -d 옵션을 사용하면 컨테이너를 백그라운드에서 실행할 수 있습니다. -p 옵션을 사용하면 호스트 시스템의 특정 포트를 컨테이너의 특정 포트에 바인딩할 수 있습니다.
docker run 실행에 옵션 명령어는 따로 포스팅을 하도록 하겠습니다.
Docker 아키텍쳐
지금까지 Docker에 프로세스에 대해 알아봤고 아키텍처를 보면서 한 번 더 정리해보려 합니다.
Dockerfile을 통해 애플리케이션을 Docker 이미지로 빌드할 수 있습니다.
이렇게 생성된 Docker 이미지를 DockerHub와 같은 저장소에서 저장을 하거나 버전 관리를 할 수도 있습니다. 물론 저장소에서 이미지를 다운 받는 것도 가능하고요.
이미지들을 실행시켜 Docker Container로 만들어 애플리케이션을 작동 시킬 수 있습니다. 이 때 복수의 컨테이너로 만들 수 있으며 이미지에 접근하는 것이 아니라 컨테이너 접근하여 작업을 하게 됩니다. 컨테이너는 이미지의 실행 가능한 인스턴스라 생각하면 됩니다.
위의 과정을 통해 애플리케이션을 컨테이너화 해서 배포가 이루어 집니다.
이번 포스팅은 여기서 마치도록 하겠습니다!
부족한 부분은 댓글이든 알려주시면 수정해 보도록 하겠고 추가 공부를 할 때 마다 수정할 예졍업니다.
그럼 글 읽어주셔서 감사합니다!
참고 사이트
개념
https://aws.amazon.com/ko/docker/
https://www.ibm.com/kr-ko/topics/docker
https://khj93.tistory.com/entry/Docker-Docker-개념
가상화
http://www.virtual-space.co.kr/virtualization.html
컨테이너
https://code-lab1.tistory.com/236
도커파일
https://toramko.tistory.com/entry/docker-도커파일Dockerfile-의-개념-작성-방법문법-작성-예시
도커이미지
도커 흐름
도커 아키텍쳐
도커 개발자를 위한 사이트
https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html