Docker란 컨테이너를 사용하여 응용 프로그램을 더 쉽게 만들고, 배포하고 실행할 수 있도록 설계된 도구이며 컨테이너 기반의 오픈소스 가상화 플랫폼이다.
Docker는 environment disparity라는 문제점을 해결해준다.
일반 컨테이너가 물건을 손쉽게 운송해준 것처럼 어플리케이션 환경에 구애받지 않고 어디에서든 손쉽게 배포 관리를 할 수 있게 해주는 것이 컨테이너의 개념이다. (Containerization 즉 컨테이너화 기술은 도커와 도커 컴포즈에서 가장 중요한 개념이다.)
컨테이너 기반 배포 방식은 구글을 비롯해 대부분의 서비스 회사가 채택하고 있다.
따라서 AWS, Azure, Google Cloud 등 어디서든 실행 가능하다.
도커를 굳이 왜 사용해야할까?
서비스가 되고 있는 어플리케이션은 보통 두 대 이상의 서버로 로드 밸런싱이 되고 트래픽을 분산시킨다.
똑같은 일을 하는 A서버와 B서버 2대의 서버가 있다고 가정해보자.
A서버는 1년전에 구성했고, B서버는 이제막 구성했다면 운영체제부터 컴파일러, 설치된 패키지까지 완벽하게 같기는 쉽지 않다. 이런 사소한 버전 차이가 문제(A서버는 작동하는데 B서버는 작동이 안됨)를 발생시키고 크게는 장애까지 발생시킬 수 있다.
도커는 서버마다 동일한 환경을 구성해주기 때문에 위와 같은 문제를 해결할 수 있다.
도커의 가장 큰 장점은 동일한 환경을 구성해주기 때문에 auto scaling에 유리하다는 것이다.
서버를 늘리고 줄일 때 자동으로 동일한 환경을 계속해서 구성해주므로, 서버를 추가할 때마다 직접 패키지를 설치하는 등의 작업을 할 필요가 없기 때문이다.
- 로드 밸런싱:
- Auto scaling: 사용자가 많이 사용하는 시간대에는 자동으로 서버를 늘려주고 트래픽이 줄어든 시간대에는 비요을 아끼기 위해 서버를 줄여주는 것
데이터베이스나 레디스를 도커베이스 이미지로 받아서 사용한다.
데이터베이스나 레디스를 로컬에서 설치할 때, 직접 설치를 하고 세팅(ex. 환경변수 세팅)을 일일이 다 직접해줘야하는데 도커를 이용하면 잘 만들어진 도커베이스를 받아서 실행만 해주면 되기 때문에 굉장히 구성하기 쉽기 때문이다.
도커와 기존 가상화 기술(VM)의 차이
VM전에 한 대의 서버에 하나의 어플리케이션만 운영하는 전통적인 방식이 있었다.
그림에서 알 수 있듯이 여러 어플리케이션을 올릴 수는 있지만 하나의 OS를 공유해서 사용하고 있다.
이렇게 하나의 OS를 공유해서 사용하면 하나의 어플리케이션에서 문제가 발생했을 때 다른 어플리케이션에서도 문제가 전파된다. 하지만 한 대의 서버에서 하나의 어플리케이션만 운영할 경우 남는 리소스가 발생하고 비효율적인 문제가 있다. 이때문에 VM이 등장한 것이다.
VM은 Hypervisor이라는 개념에서 출발하는데, 이 Hypervisor 가상화라는 개념은 호스트 시스템(윈도우나 리눅스 등)에서 다수의 게스트 OS를 구동할 수 있게 하는 소프트웨어이다.
두 번째 그림에서 볼 수 있듯 각각의 Virtual Machine이 있고 그 위에 게스트 OS가 각각 올라가게 된다.
VM은 조금 무겁다는 것(버벅이고 느림)이 단점이다.
도커의 경우, 컨테이너 위에 바로 라이브러리나 여러 가지 의존성 패키지들이 올라가 있는 것을 확인할 수 있다.
VM에 비해 한 단계가 생략된 것이기 때문에 VM에 비해서 굉장히 가볍고 성능에서도 굉장히 유리하다.
전통적인 방식에 비해 VM이나 도커가 더 안전한 이유는 그림에서 볼 수 있듯이 논리적으로 어플리케이션끼리 구분이 되어있기 때문에 하나의 어플리케이션에서 장애가 발생해도 다른 어플리케이션에서 전혀 영향을 받지 않는 구조이기 때문이다. 정리하자면 도커는 Hypervisor 구조를 가지고 있고 VM보다 훨씬 가볍게 동작하기 때문에 성능에 있어 유리하다.
도커 컨테이너와 이미지
도커를 사용하다보면 이미지라는 말이 무조건 등장한다.
여기서 이미지란 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 으용 프로그램을 실행하는데 필요한 모든 것을 포함하는 패키지이다.
이미지는 소스코드의 버전을 관리하는 Github처럼 https://hub.docker.com을 통해 버전 관리가 가능하다.
작업 시 도커 풀을 받아서 필요한 버전의 이미지를 이용할 수 있다.
도커 이미지는 프로그램을 실행하는데 필요한 설정이나 종속성들을 모두 가지고 있고 하나의 도커 이미지는 여러 개의 도커 컨테이너를 실행할 수 있다. 그래서 컨테이너를 이미지 인스턴스라고 부르기도 한다.
도커 파일이란?
Dockerfile이란 도커 이미지를 구성하기 위해 잇어야할 패키지, 의존성, 소스코드 등을 하나의 파일로 기록하여 이미지화 시킬 명령 파일이다.
즉 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 더 이상 새로운 서버가 추가되면 의존성 파일을 컴파일하고 이것저것 설치할 필요가 없다.
도커 파일의 주요 명령어는 다음과 같다.
- FROM: 새로운 이미지를 생성할 때 기반으로 사용할 이미지를 지정 (ex. From openjdk:17)
- ARG: 이미지 빌드 시점에서 사용할 변수 지정 (ex. ARG JAR_FILE=build/libs/app,jar)
- COPY: 호스트에 있는 일이나 디렉토리를 Docker 이미지의 파일 시스템으로 복사 (ex. COPY ${JAR_FILE}./app.jar)
- ENV: 컨테이너에서 사용할 환경변수 지정등 (ex. ENV. TZ=Asia/Seoul)
- ENTRYPOINT: 컨테이너가 실행되었을 때 항상 실행되어야하는 커맨드 지정 (ex. ENTRYPOINT{"java", "-jar", "./app.jar"})
Docker Compose란?
Docker Compose란 멀티 컨테이너 즉 도커 어플리케이션을 정의하고 실행하는 도구이다.
보통 도커를 싱글 컨테이너가 아니라 멀티 컨테이너로 배포하게 된다.
Application, Database, Redis, Nginx 등을 각각의 독립적인 컨테이너로 관리를 하기 때문에 여러 컨테이너를 실행하게 된다. 그러면 이 여러 멀티 컨테이너의 라이프 사이클 관리를 자동으로 도커 컴포즈가 해주게 된다.
어플리케이션이 먼저 실행되고 데이터베이스가 실행 되면서 데이터베이스 커넥션이 맺어져야하는데, 이렇게 실행 순서가 중요한 경우도 도커 컴포즈가 관리해준다.
또 도커 컨테이너는 각각 독립적인 환경으로 구성되어 있기 때문에 각 컨테이너별로 네트워크를 연결하는 부분을 따로 설정해주어야 한다. 이런 부분들도 도커 컴포즈가 알아서 관리를 해준다.
doker-compose.yml 파일을 작성하여 실행하면(1회 실행하는 것만으로도) 라이프 사이클과 컨테이너간 실행 순서도 관리 해준다.
Docker 실습
jar파일 이름이 app이 되도록 build.gradle에 아래 블록을 추가했다.
bootJar{
archiveFileName ='app.jar'
}
그리고 ./gradlew build 명렁어를 입력해서 build가 성공적으로 이루어지면 jar파일이 생성된다.
라이브러리 및에 정상적으로 jar파일이 만들어진 것을 확인할 수 있다.
생성된 jar파일을 이용해서 docker container 내부로 이 jar파일을 카피하고 어플리케이션을 실행하게 된다.
Docker Container를 띄우기 위해서는 제일 먼저 도커 파일(어떤 명령어들을 실행시킬지에 대한 명령어 모음)이 필요하다.
FROM openjdk:17
ARG JAR_FILE=build/libs/app.jar
COPY ${JAR_FILE} ./app.jar
ENV TZ=Asia/Seoul
ENTRYPOINT ["java", "-jar", "./app.jar"]
아래 그림처럼 스프링부트가 올라가는 것을 확인할 수 있다.
도커 이미지 생성
컨테이너 내부에서 실행시킬 수 있도록 명령어를 지정해보겠다.
docker build -t 도커아이디/application-project-test .라는 명령어를 사용해서 build를 해주면 도커 파일이 도커 이미지로 빌드가 된 것을 확인할 수 있다.
docker images라는 명렁어를 이용해서 도커이미지가 생성된 것을 아래 사진과 같이 확인할 수 있다.
도커 데스크탑으로 확인해도 이미지가 올라온 것을 볼 수 있따.
도커 컨테이너 생성
docker run 도커아이디/application-project-test -p 8080:8080 . 라는 명령어로 도커 이미지를 이용해서 도커 컨테이너를 생성할 수 있다.
이 명령어를 살펴보면 -p 즉 포트라는 옵션이 있다. 도커 컨테이너는 독립된 공간에서 실행되기 때문에 호스트와 도커 컨테이너 간에 포트 포드링이 필요하다. (호스트로 리퀘스트 온 요청을 도커 컨테이너로 포드링 해줘야 함)
-p 다음에 앞에 있는 부분이 호스트 포트이고 :뒤에가 도커 컨테이너 포트이다.
docker ps라는 명령어를 사용해서 컨테이너가 성공적으로 생성되었는지 확인할 수 있다.
도커 데스크탑으로도 확인해보면 성공적으로 컨테이너가 생성되었다.
it이라는 옵션을 이용하면 셸이나 배시등의 터미널 환경, 컨테이너 내부에 접근할 수 있다.
아래 사진을 보면 컨테이너 내부로 카피안 app.jar을 확인할 수 있다.
'개발' 카테고리의 다른 글
[Spring] Web Service의 인증과 Spring Security (0) | 2024.09.26 |
---|---|
[Spring] Spring과 SpringBoot의 핵심 개념 정리: IoC/DI, AOP, PSA (0) | 2024.09.21 |
[Spring] Thymeleaf(타임리프란?) (0) | 2024.07.16 |