멀티클라우드에 대한 수요가 높아져서 교육을 받게 되었다.
방금까지 기본도 못갖춘 상태에서 컨테이너를 아는게 뭐가 중요한가에 대한 글쓰고나서 쓰려니 좀 민망하긴 한데, 교육은 열심히 들었고 버릴 수는 없으니 기록해보려고한다.
대신 나름의 협상으로 실무 중심(생성하고 배포하고 등등) 내용이었던 교육 + 기본적인 지식을 함께 포스팅할 것이다.
본 포스팅에서는 컨테이너에 대한 정의, Docker 를 다룬다.
Container 란
실행에 필요한 애플리케이션, 리소스, 메모리 등을 패키지화하고 다른 애플리케이션과 분리하는 기술이다. 실행에 필요한 모든 것들이 컨테이너라는 이름으로 묶여져 있기 때문에 쉽게 다른 환경으로 이전할 수 있다.
VM vs Container
이미지 출처: Google Cloud
가장 눈에띄는 차이점은 Guest OS 의 유무이다. 컨테이너는 OS 수준의 가상화를 통해 메모리와 속도측면으로 VM에 비해 우위를 가진다.
Why Container?
1. 이식성
위 그림에서 볼 수 있듯이 컨테이너는 실행가능한 모든 것들을 "묶어서" 관리한다. 이는 이대로 다른 환경에도 옮길 수 있음을 뜻한다. 예를들어, AWS ECS 에 배포했던 컨테이너는 그대로 내부 변경 없이 GCP Kubernetes에 배포할 수 있다.
2. 안정성
각 컨테이너는 격리되어있다. 따라서 어느 환경에 문제가 생겨도 다른 환경에 영향을 주지 않는다. MSA 아키텍처에 적합한 기술이다. 물론 OS 레벨에서 오류가 생기면 모든 컨테이너에 영향을 미친다.(VM도 마찬가지)
What is Docker?
"컨테이너 = 도커"라는 말이 많은데, Docker는 오픈소스 컨테이너 기술이다. 이 포스팅에서는 도커를 이용하여 컨테이너 실습을 진행한다.
Docker Image
도커 컨테이너는 도커 Image를 기반으로 실행된다. 즉, 실행에 필요한 모든 리소스를 이미지로 묶는 것이다. 이미지는 변하지 않는다는 것이 중요하다.
ex) MySQL Docker Image를 실행시킨 후 설정 값을 바꾸어도 기존 이미지의 설정값은 변화하지 않는다
이후 내용은 직접 도커를 설치하고 컨테이너를 실행하면서 정리해보려고한다.
Install Docker
Desktop 에서 진행하기 때문에 아래 링크에서 Desktop 버전을 찾아 설치한다. 나는 Stable 버전 Mac OS 전용을 다운로드 받았다.
https://docs.docker.com/v17.09/engine/installation/#supported-platforms
설치 후 아래 명령엉를 통해 설치되었는지 확인한다. 도커 버전이 정상적으로 출력되면 설치된 것이다.
docker --version
아래 명령어를 통해 현재 실행되고 있는 컨테이너를 확인할 수 있는데,
docker ps
아래와 같은 오류가 뜰 수 있다. docker가 설치는 되었지만 실행되지 않아서 그러는데,
Application에서 Docker를 더블클릭하여 실행시켜본다. 그럼 아마 상단 바에 도커 아이콘이 생길텐데(
))),
이후 다시 docker ps를 실행해보자.
위와 같은 결과가 나온다면 docker 설치를 완료한 것이다.
이제 컨테이너로 띄울 샘플 애플리케이션을 생성할 것이다. 환경은 아래와 같다. 하지만 배포할 jar 파일만 존재한다면 딱히 상관은 없다.
IntelliJ Ultimate
Spring Boot 2.XX
Gradle
거의 건드리는 것 없이 spring boot 프로젝트를 생성하고 버전 정보를 리턴하는 컨트롤러 정도만 작성한다.
package com.example.simple.web;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/")
public String home(){
return "version 0.0.1";
}
}
작성한 웹 애플리케이션을 도커 이미지로 말고 배포해야하는데, 이미지는 Dockerfile 을 기준으로 생성된다. Dockerfile 을 작성하기 전에 build를 한번 수행항여 jar 파일을 생성한다.
나는 Gradle 빌드하였기 때문에 build/libs 디렉터리 아래에 jar 파일이 생성되었다.
이제 프로젝트 루트 아래에 Dockerfile 을 생성한다.
해당 도커 파일을 아래와 같이 작성한다.(각각에 대한 설명은 하단 링크의 최하단에 작성되어있다) 간단히 덧붙이자면, simple-0.0.1-SNAPSHOT.jar 를 말고 컨테이너 실행과 동시에 jar 파일을 실행하는 이미지를 생성하는 Dockerfile이다.
FROM java:8
ADD ./build/libs/simple-0.0.1-SNAPSHOT.jar simple-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar", "simple-0.0.1-SNAPSHOT.jar"]
2019/08/10 - [Infra/AWS] - [AWS/Spring boot] AWS CodeDeploy로 웹 애플리케이션 배포하기
정상적으로 이미지가 생성되는지 다음 명령어를 현 프로젝트 위치에서 실행해본다.
docker build .
. 은 현재 위치의 Dockerfile 을 의미한다.
만약 Dockerfile 을 여러개 두고 필요에 따라 빌드하고 싶다면
docker build -f Dockerfile-name
-f 키워드를 통해 파일 이름을 직접 지정할 수 있다.
또, 로컬 빌드가 아닌 또 다른 Repository에 Push 할 이미지를 빌드하고 싶다면(Docker Hub와 같은)
docker build -t a1010100z/repository .
-t 키워드를 통해 레파지토리를 지정할 수 있다.
여기서는 로컬 빌드 후 배포이므로 docker build . 키워드면 충분하다.
해당 명령어를 입력하면 아래와 같은 결과를 확인할 수 있을 것이다.
여기서 확인할 수 있는 것은 도커 빌드는 "레이어 계층"으로 빌드된다는 것이다.
이 이미지는 was, source, 등 실행에 필요한 모든 자원을 담고 있는데 만약 한번에 빌드되면 어느 하나만 변경되어도 다시 처음부터 빌드되어야 하기 때문에 시간이 매우 오래걸릴 수 있다. 도커는 레이어 저장 방식을 사용하여 이러한 문제점을 해결한다.
좀더 육안으로 확인해보기 위해 한번 소스코드의 리턴 버전 정보를 v 0.0.2 로 변경한 뒤 다시 빌드하고 이미지를 생성해보자.
결과가 한결 간결해졌다.
이제 빌드한 이미지를 로컬에 배포해보자.
docker image 명령어를 통해 방금 내가 빌드한 이미지의 정보를 확인하자.
레포지토리도, 태그 정보도 입력하지 않았으니 none 처리 되어있고 Image ID 가 생성된 것을 학인할 수 있다. 만약 실제 서비스하는 애플리케이션이라면 당연히 원격 레포지토리를 지정해주고, 태그를 통해 버전 관리도 해야할 것이다.
이제 docker container 를 실행해보자
--name 키워드를 통해 컨테이너 이름을 지정하고 -d 키워드로 백그라운드 실행을 지정한다.
-p 은 포트포워딩 지정 키워드인데, 외부에서 8099 로 접근하면 8090 포트로 연결해준다는 의미이다.
맨 뒤의 해쉬값은 IMAGE ID 에 해당한다. 해쉬값이기 때문에 꼭 전부를 쓰지 않아도 지장 없다.
(위에서 말은 안했지만 내 애플리케이션 포트는 8090으로 지정해두었다.)
실행한 뒤 docker ps 명령어를 통해 현재 실행되고 있는 컨테이너를 확인해보자.(docker ps -a 키워드를 사용하면 종료된 컨테이너도 확인할 수 있다. 삭제가 아닌 종료다!)
이제 localhost:8099 로 해당 애플리케이션에 접근할 수 있다.
한번 확인해보자.
정상적으로 로컬 도커 컨테이너 배포가 되었다.
이제 이 쓸모없는 백그라운드 애플리케이션을 없애보자.
컨테이너 실행 시 name 을 지정했기 때문에 name 으로 삭제가 가능하고, 없다면 Container ID를 입력해도 무관하다.
-f 키워드를 사용하면 이미지까지 전부 삭제시켜준다. 다시 docker images 명령어를 입력하면 사라져 있을 것이다.
만약 이미지를 계속 쌓아둔다면 언젠가 풀차게될거고 ,, 일반적으로 원격 레파지토리 저장소에서 버전관리를 하기 때문에 로컬 레파지토리는 주기적으로 정리해두는게 좋지 않을까 생각한다.
아주 기본적인 도커 이미지 생성 후 컨테이너 실행하는 실습을 진행해보았다. 이렇게 쉬우면 누가 도커를 안쓸까 싶지만 실전은 그렇지 않기에 ,,
우선 이론적인 내용만 정리하고 다음 포스팅에서는 AWS ECS 배포를 정리해보려고 한다.