컨테이너 가상화
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 를 실행해보자.
- 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 은 우리가 부여하는 컨테이너 이름
-> 만약 부여하지 않으면 랜덤한 이름이 부여되기 때문에 찾기 어려울 수 있다.
- 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 가 있는 것을 확인했다.
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 ... 를 사용해서 백그라운드에서 기동할 수 있다.
다른 서비스 , 운영해야할 서비스들을 도커에 이전해서 동작해도록 해보자!
참고자료