본문 바로가기

정보/Dev

Docker (1) - Docker?

 

어떤 프로그램을 개발하고, 이를 테스트하거나 배포하고 실행할 때 실행 환경을 확인해야 하는 작업이 필요하다.

가령 게임만 하더라도 OS와 스펙을 확인한다.

개발에서도 일례로 package.json이나 package-lock.json을 통해 의존성을 확인하고 node 버전을 확인한다.

 

만약 소프트웨어를 개발하고, 이와 같은 일련의 환경 설정(런타임, OS 설정까지) 한 번에 제공한다고 가정해보면?

환경 설정 자체는 하지 않아도 되겠지만 실질적으로는 매우 힘들다.

일단 OS만 하더라도 설치에 수십 GB가 들어갈 것이다.

 

그러나 이를 비슷하게 처리해주는 것이 바로 Docker라는 컨테이너 기반 소프트웨어이다.

Docker를 자세히 알아보자.

 

1. Docker란?

Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker's methodologies for shipping, testing, and deploying code, you can significantly reduce the delay between writing code and running it in production. https://docs.docker.com/get-started/docker-overview/

 

Docker는 어플리케이션의 개발, 배포(배송), 실행을 위한 오픈 플랫폼(소프트웨어)이다.

당신의 어플리케이션과 당신의 인프라를 분리하게 해서 빠른 배포를 하게 해준다.

이를 통해 당신이 어플리케이션을 다루는 방식과 동일하게 인프라도 다룰 수 있다.

Docker의 코드를 배송, 테스트, 배포하는 이런 방법론의 이점을 통해,

당신은 코드를 작성하고 production에서 이를 실행 할 때 생기는 딜레이를 단축 시킬 수 있다.

 

물론 개발, 배포, 실행을 하는데 Docker가 필요하지 않을 수 있다.

어떻게든 다른 방식으로 실행이 가능하다.

그렇다면 Docker가 개발, 배포, 실행을 하는데 있어서 차별화되는 점이 무엇일까?

이들이 강조하는 Docker의 방법론이란 어떤 것일까? 를 알아보자.

 

 

2. Docker를 사용하는 이유? - (1) 일관성 보장

앞서 말했던 실행 환경에 대한 불편함에 해결책을 제시해준다.

어플리케이션이 머신에 구애받지 않게 동작시키기 위해 필요한 모든 것을 제공한다.

다시 말해, 어플리케이션과 실행  환경들을 중앙화 해서 구동한다.

이때 들어가는 파일들을 나열하자면

  • Application 파일
  • Environment Variables : 환경 변수; 네트워크, DB 접속시의 id, pw 또한 중앙화
  • Runtime Environment : JVM과 같은 런타임 환경의 버전도 중앙화
  • Third party Library : package가 같은 버전이 되도록 중앙화
  • Cut-down OS : OS는 용량이 크지만, 이를 kernel을 포함한 구동에 필요한 부분만 남겨 놓는다.

이 모든 것을 적절하게 줄여서 같이 제공한다면, 플랫폼에 상관없이 해당 환경에서 동작이 가능하게 된다.

 

 

3. Docker를 사용하는 이유? - (2) 격리 환경 설정

앞의 Docker 공식 홈페이지의 설명에서 "어플리케이션과 인프라를 seperate한다"고 나왔다. 이것을 이제 설명하려 한다.

 

로컬에서 어떤 어플리케이션이 JVM 16을 지원하는데, 나는 현재 17을 사용하고 있다면

해당 어플리케이션을 구동하기 위해서는 JVM 16을 추가로 설치해야 한다.

그렇기에 이런식으로 필요한 것을 계속 설치한다면, 사용자의 local환경이 더러워진다.

이러한 환경의 충돌을 막고자 Docker를 사용한다.

 

Docker는 앞서 설명한 방식 대로 환경 설정 세팅 + App 구동 후, 이러한 환경들을 버릴 수 있다.

그렇기에 로컬의 환경은 그대로 유지하는 격리 환경을 Docker가 제공한다는 것이다.

 

DB 버전이 여러 개가 있다면, nvm과 같이 명령어를 통해 DB 버전을 바꿀 수 있다.

이러한 방식으로 도커의 사용이 가능하다.

 

 

4. Docker를 사용하는 이유? - (3) 다중 컨테이너 지원

 

하나의 서버에서 여러개의 컨테이너를 동작시켜서 다양한 어플리케이션을 조합 할 수 있다.

가령, WAS와 DB를 하나의 서버에서 돌리는 방식으로 만들 수도 있다.

AWS EC2 하나만으로 서버를 띄울 수도 있다는 것이다.

그렇지만 실무에서는 실질적으로 WAS와 DB를 같이 띄우는 방식은 사용되지 않는다고 한다.

 

다른 예시로 WAS와 Logstash와 같이 하나의 서버를 구동하고 동시에 로그를 수집하고 전송하는 방식으로 

다중 컨테이너를 사용할 수도 있다.

만약 Elastic Search와 Kibana와 같은 로그 저장 nosql과 로그 분석 기능을 통해 ELK 스택으로 사용하기도 한다.

 

 

 

5. Docker에서 사용되는 용어

  1. Image : App + Bins / Libs 
    어플리케이션 파일과 구동시 필요한 라이브러리, 실행파일, 환경변수 OS 등이 포함된 기본 단위
  2. Dockerfile : 어떤 Bins/Libs/App을 포장 할지가 담긴 이미지 생성 규칙(하나의 특정 Image에 대한)
  3. Container : 해당 이미지를 구동한, 다시 말해 실행중인 이미지가 바로 Container

Image와 Container의 관계는 마치 프로그램과 프로세스의 관계를 보는 듯 하다.

 

 

6. Docker에서 Dockerfile을 통해 Image를 형성하는 방법

FROM eclipse-temurin:21.0.2_13-jdk-jammy AS builder
WORKDIR /opt/app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY ./src ./src
RUN ./mvnw clean install

 

Dockerfile은 하나의 이미지에 대한 이미지 생성 규칙을 말하는 것이라고 했다.

위의 코드는 docker 공식 doc에서 제공하는 dockerfile의 예시인데,

 

여기서 첫 번째 줄의 FROM을 통해서 Base image를 생성한다.

이 base image 자체만으로 이미 하나의 image가 되는 것이다.

다시 말해서 os라는 어플리케이션을 실행할 수 있는 환경이 만들어지는 것이기 때문에 image가 되는 것이다.

 

그리고 Docker의 이미지는 layer기반이고, 이 layer는 Dockerfile의 맨 윗줄부터 하나 하나씩 생성된다.


즉, Dockerfile의 첫 번째 줄로부터 첫번째 이미지인 base image를 구성한다.
두 번째 줄을 통해서 첫 번째 이미지 위에 layer를 올린다.

(참고로 docker는 이 레이어를 올린 스냅샷은 캐싱한다.) 아직 이 상태로는 image가 되지는 않는다.
이런식으로 맨 마지막 줄 까지 layer를 쌓아서 업데이트하고, 다 쌓였을 때

dockerfile을 통해서 정의한 온전한 최종 이미지가 완성되는 것이다.