Spring Cloud + MSA 애플리케이션 개발 14(애플리케이션 배포를 위한 컨테이너 가상화)

지원·2024년 3월 4일
0

MSA개발

목록 보기
13/15

컨테이너 가상화

Virtualization

  • 물리적인 컴퓨터 리소스를 다른 시스템이나 애플리케이션에서 사용할 수 있도록 제공
    -> 플랫폼 가상화
    -> 리소스 가상화
  • 하이퍼바이저 (Hypervisor)
    -> Virtual Machine Manager (VMM)
    -> 다수의 운영체제를 동시에 실행하기 위한 논리적 플랫폼

OS Virtualization

  • Host OS 위에 Guest OS 전체를 가상화
  • VMWare , VirtualBox
  • 자유도가 높으나, 시스템에 부하가 많고 느려짐
  • Host OS 위에 Hypervisor 를 사용해서 Guest OS 를 놓게 되면 매우 무거워지기 때문에 overhead 가 발생한다.

Container Virtualization

  • Host OS 가 가진 리소스를 적게 사용하며, 필요한 프로세스 실행
  • 최소한의 라이브러리와 도구만 포함
  • Container 의 생성 속도 빠름
  • Host OS 바로 위에 컨테이너를 실행할 수 있는 소프트웨어를 놓으면 된다.
  • Hypervisor , Guest OS 가 들어가지 않기 때문에 매우 빠르다.
  • 이번 예제에서는 Docker Engine 이라는 소프트웨어를 사용한다.

Container Image

  • Container 실행에 필요한 설정 값
    -> 상태값X , Immutable
  • Image 를 가지고 실체화 -> Container

예시
1. 우분투 이미지 : 우분투를 실행하기 위해서 필요한 파일들
2. Mysql 이미지 : MySQL 을 실행하기 위해서 필요한 파일 , 명령어 , 포트정보 등등

Registry

그렇다면 어떻게 이미지를 생성하고 다운로드 받을까?

  • 이미지는 컨테이너가 실행에 필요한 설정값 , 정보들을 가지고 있다는 것이라고 생각하면 된다.
  • 이러한 이미지를 저장할 수 있는 저장소가 필요한데 그것을 Registry 라고 하고 public , private 으로 나뉠 수 있다.
  • 보통 public Registry 를 Docker hub 라고 한다.
  • private Registry 도 있다.

Docker Host

  • Docker Host 는 이미지를 사용할 수 있는 컨테이너 서버 자체를 의미한다.
  • 호스트에서 실행할 수 있는 Local Repository 가 있다.
  • Docker Host 에서 public Registry 또는 private Registry 에서 이미지를 다운 받아서 Local Repository 에 저장한다.
  • 위에서 설명한 것을 pull 한다 라고 표현한다.
  • Local Repository 에 있는 이미지를 가지고 필요한 컨테이너를 생성할 수 있다.

pull , create , start , run

  • pull : Registry 에서 Local Repository 로 이미지를 다운 받는 것
  • create : Local Repository 의 이미지를 가지고 컨테이너 생성
  • start : Local Repository 의 이미지를 가지고 컨테이너 생성
  • run : pull + create + start 를 한 번에 해주는 것

외부에서(클라이언트) 사용하기 위해서 적절한 포트가 공개되어 있다면 실제로 사용할 수 있다.

Dockerfile

  • Docker Image 를 생성하기 위한 스크립트 파일
  • 자체 문법을 사용한다 -> 이미지 생성과정 기술

명령어

FROM mysql:5.7
-> mysql 로부터 서버를 만들겠다는 것
EVN MYSQL_ALLOW_EMPTY_PASSWORD
EVN MYSQL_DATABASE mydb
-> 이미지 생성에 필요한 환경변수가 있다면 이렇게 설정하면 된다.

ADD
-> 가지고 있었던 로컬에 파일을 이미지 가지고 있는 곳에 저장할 때

EXPOSE
-> 생성된 컨테이너가 외부에 공개할 포트

CMD
-> 이 이미지가 전부다 실행된 뒤 최종적으로 mysqld 라는 커맨드를 실행하라는 것

Docker Destop 을 사용해서 배포를 해보자!

Docker 컨테이너

컨테이너 실행

  • docker run [OPTIONS] IMAGE[:TAG|@DIGEST][COMMAND][ARG...]
  • TAG 는 version 처럼 생각하면 된다.
    -> 같은 이름에 이미지를 생성하고 여러개의 버전을 만들거나 용도별로 태깅할 때 사용한다.
  • [COMMAND][ARG] 는 추가적으로 파라미터를 전달해서 컨테이너가 생성될 때 필요한 부가적인 정보를 전달할 수 있다.

OPTIONS 종류

  • -d : detached mode 흔히 말하는 백그라운드 모드
  • -p : 호스트와 컨테이너의 포트를 연결 (포워딩)
    -> Host OS 위에 Docker Engine 위에 우리가 원하는 Container 를 올리면 된다.
    -> 이때 올린 Container 와 Host OS 를 연결하는 것이라고 생각하면 된다.
  • -v : 호스트와 컨테이너의 디렉토리를 연결 (마운트)
  • -e : 컨테이너 내에서 사용할 환경 변수 설정
  • --name : 컨테이너 이름 설정
  • --rm : 프로세스 종료시 컨테이너 자동 제거
  • --it : -i 와 -t 를 동시에 사용한 것으로 터미널 입력을 위한 옵션
    -> 컨테이너가 실행된 다음에 부가적으로 컨테이너에 명령어를 전달하기 위해 사용하는 것
  • --link : 컨테이너와 연결 [컨테이너명:별칭]

예시

  • docker run ubuntu:16.04
    -> OPTIONS 를 사용하지 않고 IMAGE 가 ubuntu 에 TAG 를 16.04 로 지정한 명령어

DockerHub

  • DockerHub 링크에 가서 ubuntu , mysql 이러한 것들을 검색하면 이미지들을 다운로드 받을 수 있다.
  • ubuntu 를 검색하고 TAGS 를 들어가보면 해당 버전의 이미지를 가져올 수 있는 명령어를 복사할 수 있는데 pull 로 되어있다.
  • 하지만 run 을 사용하면 pull + create + start 를 해주기 때문에 run 좀 더 편하다.

Docker 명령어

 이미지 조회
 docker image ls
 
 컨테이너 조회
 docker container ls
 
 우분투 이미지 실행
 docker run ubuntu:16.04
 
실행됐던 컨테이너 조회
docker container ls -a == docker ps -a

컨테이너 삭제
docker container rm CONTAINER_ID

이미지는 필요한 정보에 따라서 레이어로 구분되어 있어서 그 구분된 레이어대로 다운로드가 된다.

docker run ubuntu:16.04 실행 후 로그
828b35a09f0b: Pull complete
66927c6d1d3d: Pull complete
000560be9165: Pull complete
6225a0253717: Pull complete

컨테이너 생성과 실행

이번에는 도커를 이용해서 mysql database 를 실행해보자.

  1. docker run -d -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=true --name mysql mysql:5.7
  • -d 는 백그라운드 모드
  • -p 는 포트 포워딩 ( : 을 기준으로 2가지를 정해주는데, 앞에 있는건 HOST PC 에서 접근하고자 하는것 , 뒤에 있는건 컨테이너에서 응답하기 위한 포트 번호)
    -> mysql 은 기본적으로 3306 포트 번호 사용
  • -e 는 환경 변수 전달 mysql:5.7 버전을 사용할것인데 이 버전의 특징은 루트 패스워드를 설정해줘야 한다.
    -> 그게 만약 아니라면 EMPTY_PASSWORD 를 사용 , 그래서 해당 설정을 넣은 것이다.
  • --name mysql 은 우리가 부여하는 컨테이너 이름
    -> 만약 부여하지 않으면 랜덤한 이름이 부여되기 때문에 찾기 어려울 수 있다.
  1. docker exec -it mysql /bin/bash
  • exec 는 추가적으로 컨테이너에다가 커맨드에 추가적인 쿼리를 넣고 싶을때
  • exec -it 실행되어 있는 컨테이너에 키보드와 같은 도구를 이용해서 터미널에 전달하겠다는 것
  • mysql 은 컨테이너이름 또는 컨테이너 아이디를 넣어주면 된다.
  • bash 는 어떤 쉘을 이용할꺼냐 여기서는 /bin/bash 쉘을 이용하겠다

먼저 1번 명령어를 실행하면 포트 충돌 에러가 발생한다.

  • 그렇다면 13306:3306 으로 수정하면 된다.
  • MacOS 의 13306 port 와 컨테이너에 있는 3306 포트를 연결하겠다.
    -> 즉 MacOs 에서 연결하기 위해서는 13306 포트번호로, 컨테이너 내부에서는 3306 포트로 연결

다시 1번 명령어를 실행하면 또 오류가 발생한다.

  • 그 이유는 1번 명령어를 먼저 실행 했었는데 그때 이미 컨테이너가 만들어졌기 때문에 컨테이너 이름이 같아서 오류가 발생한다.
  • docker container rm 컨테이너이름 명령어로 제거 후 다시 1번 명령어를 실행하면 정상적으로 동작한다.
  • 실행 결과 우분투의 /bin/bash 로 들어올 수 있다.
  • 여기서 mysql -uroot -p 을 실행하면 mysql 을 찾을 수 없다고 한다.
  • 이때 sudo 도 설치가 되지 않았기 때문에 mysql 도 설치할 수 없었다.
1. apt-get update
2. apt-get install sudo
3. sudo apt install -y mysql-server
  • 위에 명령어를 순차적으로 실행한 후 다시 mysql -uroot -p 을 실행하면 mysql 에 접속할 수 있다.

여기서 mydb 라는 database 를 만들고 exit 명령어로 나왔다.

그런후 MySQL 워크벤치를 열고 Connection 을 만들 떄 Port 를 13306 으로 바꿔주고 들어가보면 위에서 설치했던 mydb 라는 database 가 있는 것을 확인했다.

  • 즉 컨테이너와 Host 가 연결이 된 것

Docker 이미지 생성과 Public Registry 에 Push

FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY target/users-ws-0.1.jar users-service.jar
ENTRYPOINT ["java" , "-Djava.security.egd=file:/dev/./urandom" , "-jar", "users-service.jar"]

FROM : 우리가 앞으로 올린 user-service 와 같은 경우는 java 가 꼭 있어야 하기 때문에 FROM 에 java 로부터 만들어 달라는 명령어가 있어야 한다.

VOLUME : /tmp 라는 가상의 디렉토리 , 컨테이너 안에 tmp 를 넣기 (임시 티렉토리)

COPY : 앞에 있는 것을 뒤에 있는 곳으로 복사해달라 -> target/... 파일을 user-service.jar 파일로 복사해달라는 것

ENTRYPOINT : 어떤 명령어를 가지고 도커를 실행할 것인지에 대한 실행 커맨더들을 명시
-> java , user-service.jar 이런 명령어들이 있으면 도커가 실행

docker build -t supportkim/user-service:1.0 .
-> 이미지를 만들기 위해서 사용되는 커맨드가 build
-> -t 는 어떤 이름으로 만들어달라는건지 설정
-> 마지막에 . 은 현재 디렉토리에 있는 도커 파일을 가지고 이미지를 만들어 달라는 것

docker push supportkim/user-service:1.0
-> Hub 사이트에서 supportkim/user-service:1.0 으로 업로드
docker pull supportkim/user-service:1.0
-> Hub 사이트에서 supportkim/user-service:1.0 으로 다운로드

우선 user-service 에 들어가서 target 와 같은 depth 에 Dockerfile 을 만든다.

FROM openjdk:17-ea-jdk-slim
VOLUME /tmp
COPY target/user-service-1.0.jar UserService.jar
ENTRYPOINT ["java","-jar","UserSerivce.jar"]
  • 위와 같이 설정을 하고 티미털에서 가서 DockerFile 과 target 이 같이 있는지 확인한다.
  • 같이 있다면 mvn clean compile package -DskipTests=true 명령어를 실행한다.
  • 그러면 /target 파일에 user-service-0.0.1-SNAPSHOT.jar 파일이 만들어지는데 파일명이 너무 길기 때문에 pom.xml 에서 version 부분을 1.0 으로 바꿔준다.
  • 그런후 다시 명령어를 실행하면 user-service-1.0.jar 파일로 만들어진다.
  • 이렇게 위에서 DockerFile 에 만든 커맨드와 똑같이 만들었다. (COPY)

docker build --tag supportkim/user-service:1.0 .

  • 우리가 정해준 총 4가지의 커맨드가 있기 떄문에 일정한 절차에 의해서 도커 파일이 만들어진다.
  • 다 만들어진 후 docker image ls 명령어를 실행하면 방금 만들었던 supportkim/user-service:1.0 이 만들어진 것을 확인할 수 있다.

docker push supportkim/user-service:1.0

  • 명령어를 실행하고 난 후 DockerHub 사이트에 들어가보자.
  • 들어가보면 support/kim/user-service 의 이름의 Repository 가 만들어진다.

다시 터미널에서 user-service 에 들어간다.

  • docker rmi IMAGE_ID 로 이미지를 삭제한다.
  • IMAGE_ID 는 docker images 로 알 수 있다.

docker pull supportkim/user-service:1.0

  • 이 이미지로 다시 가져올 수 있다.

build -> push -> pull 로 가지고 와서 docker run supportkim/user-service:1.0 명령어를 실행하면 Spring 서버가 실행된다!!!!

  • 에러가 발생하는 이유는 user-service 를 실행하기 전 몇 개 더 실행해야하는 서버가 있어야 하는데 실행하지 않아서 발생한 오류들이다.
  • docker run -d ... 를 사용해서 백그라운드에서 기동할 수 있다.

다른 서비스 , 운영해야할 서비스들을 도커에 이전해서 동작해도록 해보자!

참고자료

profile
덕업일치

0개의 댓글