새소식

Server

[Docker] Docker란 ?

  • -
728x90
Docker 에 대해 학습하고 직접 실행하며 배우고 느낀 것들에 대해 정리하고 공유하고자 글을 작성한다 📖

Docker

  • 컨테이너를 사용하여 응용프로그램을 더 쉽게 만들고, 배포하고 실행할 수 있도록 설계된 도구이며 컨테이너 기반의 오픈 소스 가상화 플랫폼
  • 일반 컨테이너 개념에서 물건을 손쉽게 운송해주는 것처럼 어플리케이션 환경에 구애받지 않고 손쉽게 배포 관리를 할 수 있게 해준다.
  • 컨테이너 기반 배포 방식은 구글을 비롯해 대부분 서비스 회사가 컨테이너로 서비스 운영 중
  • 따라서 AWS, Azure, GC 등 어디서든 실행이 가능하다.

Docker 를 왜 사용해야 할까?

  • 똑같은 일을 하는 2대의 서버가 있다 해도, A 서버는 1년 전에 구성했고 B 서버는 이제 막 구성했다면 운영체제부터 컴파일러, 설치된 패키지까지 완벽하게 동일하기는 쉽지 않다. 이러한 차이는 문제를 발생시킬 수 있다.
  • 도커는 서버마다 동일한 환경을 구성해주기 때문에 이러한 문제를 해결할 수 있다.
  • 동일한 환경을 구성하기 때문에 auto scaling에 유리하다

    ⭐️ Auto Scaling의 주요 기능과 이점
    1. 성능 유지: 애플리케이션에 대한 요청이 증가할 때, 추가적인 컴퓨팅 자원을 자동으로 배치하여 처리 능력을 증가시킨다. 이는 사용자 경험을 저하시키지 않으면서 서비스의 가용성과 성능을 유지할 수 있게 한다.
    2. 비용 절감: 자동 확장은 실제 필요한 만큼의 자원만을 사용하도록 조정하기 때문에, 사용하지 않는 자원에 대한 비용을 절약할 수 있다. 특히, 트래픽이 낮은 시간대에 자원을 자동으로 축소함으로써 비용을 절감할 수 있다.
    3. 유연성 및 반응성: 애플리케이션의 트래픽 패턴이 예측하기 어려울 때, 자동 확장 기능은 시스템이 이러한 변화에 신속하게 대응할 수 있게 한다. 이는 예기치 않은 트래픽 증가나 감소에 효과적으로 대응할 수 있게 해준다.
    4. 자동화: 자동 확장은 정해진 규칙이나 정책에 따라 작동하므로, 인프라 관리에 드는 수동 작업을 줄여주고 IT 팀의 작업 부담을 경감시킨다.
    작동 방식
    • 트리거: 특정 메트릭(예: CPU 사용률, 메모리 사용량, 네트워크 트래픽 등)이 정의된 임계값에 도달하면, 자동 확장 시스템이 트리거된다.
    • 확장 정책: 확장(자원 추가) 또는 축소(자원 제거) 작업은 미리 정의된 확장 정책에 따라 실행된다. 이 정책은 특정 메트릭의 임계값, 확장 시 추가할 자원의 수, 축소 시 제거할 자원의 수 등을 포함할 수 있다.
    • 자원 할당 및 제거: 시스템은 정책에 따라 필요한 자원을 자동으로 할당하거나 제거하여, 애플리케이션의 성능을 최적화하고 비용을 관리한다.
    - 자동 확장은 클라우드 서비스 제공업체(AWS, Azure, Google Cloud 등)에서 널리 지원하는 기능이며, 현대적인 클라우드 인프라스트럭처 관리의 핵심 요소 중 하나다.

    - Auto scaling, 즉 자동 확장은 클라우드 컴퓨팅 환경에서 애플리케이션의 부하(traffic)에 따라 컴퓨팅 자원(예: 서버의 수)을 자동으로 조정하는 기술이다. 이 기능은 시스템의 부하가 증가하거나 감소함에 따라 자원을 동적으로 추가하거나 제거하여, 애플리케이션의 성능을 최적화하고 비용 효율성을 극대화한다.

도커와 기존 가상화 기술(VM)의 차이

  • 한대의 서버에서 하나의 어플리케이션만 운영하는 전통적인 방식에서 하이퍼 바이저 기반 가상화 기술이 등장했다.
  • 하이퍼 바이저는 호스트 시스템(Linux, Window 등) 에서 다수의 게스트 OS(가상머신)을 구동할 수 있게 하는 소프트웨어다.
  • 각 VM 마다 독립적으로 동작한다.
  • 도커는 하이퍼 바이저 구조 토대로 등장했으며, VM 보다 훨씬 가볍게 동작하기 때문에 성능에 유리하다.
  • 논리적으로 구분이 되어 있기 때문에 하나의 어플리케이션에서 장애가 발생을 해도 다른 어플레키에션에 전혀 영향을 받지 않는 구조이다.
    이미지란 ?
  • 이미지란 코드, 런타임, 시스템 도구, 시스템 라이브러리 설정과 같은 응용프로그램을 실행하는데 필요한 모든 것을 포함하는 패키지이다.
  • 이미지는 Github 와 유사한 서비스인 https://hub.docker.com/ 을 통해 버전 관리가 가능하다.

컨테이너란?

  • 도커 이미지를 독립된 공간에서 실행할 수 있게 해주는 기술이다.

⭐️ 즉, 도커 이미지는 프로그램을 실행하는데 필요한 설정이나 종속성들을 가지고 있고, 도커 컨테이너는 이미지 인스턴스이며 프로그램을 실행한다. 또한 하나의 도커 이미지는 여러 컨테이너를 실행할 수 있다.

Dockerfile이란 ?

  • Dockerfile이란 도커 이미지를 구성하기 위해 있어야할 패키지, 의존성, 소스코드 등을 하나의 file 로 기록하여 이미지화 시킬 명령 파일이다.
  • 즉, 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 더 이상 새로운 서버가 추가되면 의존성 파일을 컴파일하고 추가적인 설치가 불필요해진다.
[FROM]
새로운 이미지를 생성할 때 기반으로 사용할 이미지 지정(이미지 이름:태그)
jdk 11 이 있는 컨테이너 사용

[ARG]
이미지 빌드 시점에서 사용할 변수 지정

[COPY]
호스트에 있는 파일이나 디렉토리를 Docker 이미지의 파일 시스템으로 복사

[ENV]
컨테이너에서 사용할 환경 변수 지정
TimeZone 환경 변수

[ENTRYPOINT]
컨테이너가 실행되었을 때 항상 실행되어야 하는 커맨드 지정
// base Image
FROM openjdk:11 

// 어떤 변수를 사용할 것인지
ARG JAR_FILE=build/libs/app.jar 

// 컨테이너의 어떤 부분을 카피할 것인지
COPY ${JAR_FILE} ./app.jar 
COPY pharmacy.csv ./

// 어떤 타임존을 사용할 것인지
ENV TZ=Asiz/Seoul 

// 컨테이너가 실행될 때 어떤 명령어를 입력할 건지
ENTRYPOINT ["java", "-jar", "./app.jar"] 

Docker Compose란 ?

  • Docker Compose란 멀티 컨테이너 도커 어플리케이션을 정의하고 실행하는 도구이다.
  • 멀티 컨테이너 환경, 예를 들어 Application, Database, Redis, Nginx 등을 각각 독립적인 컨테이너로 관리한다고 했을 때 멀티 컨테이너 라이프 사이클을 자동으로 관리해준다.
  • 즉, 여러개의 도커 컨테이너로 부터 이루어진 서비스를 구축 및 네트워크 연결, 실행 순서를 자동으로 관리해준다.
  • docker-compose.yml 파일을 작성하여 1회 실행하는 것으로 설정된 모든 컨테이너를 실행할 수 있다.

 

📚 Spring boot에서 Docker 연동

1. Docker 설치하기

https://docs.docker.com/desktop/install/mac-install/

 

Install Docker Desktop on Mac

Install Docker for Mac to get started. This guide covers system requirements, where to download, and instructions on how to install and update.

docs.docker.com

해당 페이지에서 OS에 맞게 설치한다. Linux 의 경우엔 docker-compose 를 추가로 설치해 주어야 한다.

설치가 완료됐으면 아래의 명령어를 통해 버전을 확인하여 설치를 확인!

docker -v
docker-compose -v

 

2. Spring Boot 에서 Docker 실행하기

도커 설치가 모두 완료되었으면 이제 Spring Boot 에서 직접 Docker 를 실행시켜 보자!

 

2-1. jar 파일을 생성

우선 gradle wrapper 를 이용하여 jar 파일을 생성해 주어야 한다. build.gradle 에서 생성되는 jar 파일의 이름을 변경해 줄 수도 있다! (기본 경로는 프로젝트의 build/libs/*.jar)

 

// build.gradle, jar 파일 네이밍 설정
boojJar {
	archiveFileName = `app.jar`
}

// 터미널에 아래의 명령어를 통해 build (Linux, OS)
./gradlew build

 

 

위의 과정을 모두 진행하면 build/libs 경로에 app.jar 파일이 정상적으로 생성된 것을 확인할 수 있다.

 

2-2. Dockerfile 파일을 생성

이제 이 jar 파일을 기반으로 도커 이미지를 생성한다. 먼저 루트 디렉토리에 Dockerfile 을 채워준다. 자세한 내용은 위에서 설명했기에 생략!

FROM openjdk:11
ARG JAR_FILE=build/libs/app.jar
#app.jar 이라는 네임으로 카피
COPY ${JAR_FILE} ./app.jar
ENV TZ=Asia/Seoul
ENTRYPOINT ["java", "-jar", "./app.jar"]

 

2-3. Dockerfile 파일을 이미지로 Build

모두 작성했으면 Docker file 을 이미지로 build 해보자. 아래의 명령어를 통해 Build!

[MANUAL]
docker build -t {도커 Hub ID}/{도커 image Name} {DockerFile 이 있는 경로}

[EX]
docker build -t userid/application-test-app .

 

 

 

실행한 결과를 확인하기 위해 docker images 명령어를 사용한다.

 $ docker images
REPOSITORY                       TAG       IMAGE ID       CREATED              SIZE
userid/application-test-app   latest    25173000d985   About a minute ago   663MB

 

2-3. Docker 실행하기

복잡한 과정은 모두 끝났다. 이제 Docker run 명령어를 통해 컨테이너 생성 및 실행 !

[MANUAL]
docker run {docker Hub Id}/{docker image} -p {host port}:{docker Container port}

[EX]
docker run userid/application-test-app -p 8080:8080

 

💡 port 옵션을 사용하여 포트를 지정하는 이유

도커 컨테이너는 독립된 공간에서 실행되기 때문에 호스트와 컨테이너 간의 port 포워딩 처리가 필요하다.

(호스트로 온 Request 요청을 도커 컨테이너로 포워딩을 해줘야 하는 경우가 발생)

 

위와 같은 과정을 통해 Spring boot 가 실행되는 것을 확인할 수 있다! 또한 이름은 지정하지 않았기 때문에 임의로 지정된 모습을 확인할 수 있다.

$ docker run userid/application-test-app -p 8080:8080

.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

2024-02-11 10:29:59.180  INFO 1 --- [           main] c.example.pharmacy.PharmacyApplication   : Starting PharmacyApplication using Java 11.0.16 on ca5ac2e75d9f with PID 1 (/app.jar started by root in /)
2024-02-11 10:29:59.182  INFO 1 --- [           main] c.example.pharmacy.PharmacyApplication   : No active profile set, falling back to 1 default profile: "default"
2024-02-11 10:29:59.709  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2024-02-11 10:29:59.718  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-02-11 10:29:59.718  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.62]
2024-02-11 10:29:59.775  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-02-11 10:29:59.775  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 552 ms
2024-02-11 10:29:59.963  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2024-02-11 10:29:59.970  INFO 1 --- [           main] c.example.pharmacy.PharmacyApplication   : Started PharmacyApplication in 1.063 seconds (JVM running for 1.379)

 

실행되고 있는 도커 리스트 조회
$ docker ps

CONTAINER ID   IMAGE                            COMMAND                   CREATED          STATUS          PORTS     NAMES
ca5ac2e75d9f   userid/application-project-test   "java -jar ./app.jar…"   25 seconds ago   Up 24 seconds             hungry_archimedes

 

도커를 싱글 컨테이너 환경에서 실행하는 것까지 모두 진행했다. 더 길어지는 내용은 다음 포스트에서 설명하겠다 : )

728x90

'Server' 카테고리의 다른 글

[Docker] 다중 컨테이너 한번에 구현하기  (0) 2024.02.12
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.