Docker에 대해 간략히 알아보고 도커를 직접 설치하여 컨테이너를 생성, 동작, 삭제, PUSH, PULL 등을 진행해본다.
사전 지식
모놀리식 아키텍쳐
전통적인 아키텍쳐 방식
다양한 서비스를 포함한 하나의 애플리케이션으로 개발 및 배포하는 방법
문제점
각각의 기능이 서로 다른 기능을 제공해 각 기능 라이브러리 업데이트 시 충돌이 발생하는 등 버전 종속성 관리의 어려움
전체가 하나로 동작하기 때문에 작은 수정에도 전체를 다시 빌드해서 배포해야 함
마이크로 서비스 아키텍쳐
모놀리식 아키텍처의 대안으로 반대되는 개념
애플리케이션의 각각의 기능을 분리하여 개발 및 관리
장점
서비스 단위 빠른 개발: 개발자가 특정 비즈니스 로직에 대해서만 집중하여 개발 가능
배포 용이: 개별 서비스 단위로 개발, 패키징, 빌드, 테스트, 배포로 종속성 문제가 없음
서비스 단위 고효율 저비용 Scale-Out 구조: 서비스 단위로 스케일링이 가능해 서비스의 활용도에 따라 확장 가능
단점
서비스별로 분리되어 분산 시스템 환경에서 Transaction 보장, 테스트, 배포, 관리 복잡 등의 문제 발생
이를 해결하기 위해 컨테이너, 도커, 쿠버네티스가 등장
컨테이너
가상 머신을 이용하여 각 마이크로 서비스를 격리하는 기술
가상 머신 동작과 달리 하드웨어를 전부 구현하지 않아 빠르고 용량이 적음
(일반적으로 VM 이미지는 수십 GB, 컨테이너 이미지는 수십 MB이다.)
하나의 컨테이너에는 하나의 프로세스를 실행시켜 관리하는 것이 좋다.
격리 기술
리눅스 네임 스페이스
데이터에 이름을 붙여 충돌을 줄이고 쉽게 참조
각 프로세스가 파일 시스템 마운트, 네트워크, UID, UTS 등에 대해 시스템에 독립된 환경을 제공
리눅스 컨트롤 그룹(cgroup)
프로세스 별로 소비할 수 있는 리소스 양(CPU, 메모리, I/O 네트워크 대역, device 노드 등)을 제한할 수 있는 리눅스 커널 모듈
자원 경합을 줄이고 예측성을 높여 성능 향상
도커(Docker)
컨테이너 기술을 활용하는 앱의 개발, 제공 및 실행을 위해 설계된 소프트웨어 컨테이너 플랫폼
(컨테이너 기술의 사실상 표준)
개발자는 애플리케이션에 국한되지 않고 의존성 및 파일 시스템까지 패키징하여 빌드, 배포, 실행을 단순화
DevOps 환경에 적합하게 설계된 개방형 애플리케이션 개발 프레임워크
DevOps
소프트웨어의 개발(Development)과 운영(Operations)의 합성어
소프트웨어 개발자와 운영팀 간의 소통, 협업 및 통합을 강조하는 개발 환경
장점 : 작업 속도 향상, 신속한 제공, 안정성, 협업 강화, 확장성, 보안
https://aws.amazon.com/ko/devops/what-is-devops/
도커 이미지
서비스 운영에 필요한 모든 파일과 환경 값을 포함하여 추가적인 의존성 작업 없이 생성 가능한 형태로 만들어진 파일
도커 이미지를 실행하면 저장된 환경 값을 이용해 격리된 공간에서 프로세스를 실행하는 도커 컨테이너가 된다.
하나의 이미지는 여러 개의 도커 컨테이너를 생성할 수 있으며 이때 이미지는 변하지 않고 원본 상태를 유지한다.
이미지를 이용하면 내가 설정한 서비스와 환경을 합쳐서 배포할 수 있기 때문에 종속성에서 자유로울 수 있다.
이미지 레이어(Layer)
도커 이미지는 레이어로 구성되어있어 모든 데이터를 저장하는 것이 아니라 변경된 레이어만 저장하여 효율적으로 관리된다.
예 1) 이미지 A와 이미지 B가 설치되어있을 경우 이미지 A를 삭제한다 해도 이미지 B에서 같은 레이어 A, B, C를 사용하기 때문에 레이어는 삭제되지 않음
예 2) 이미지 C, D, E를 차례로 내려받을 때 이미지 C에서 설치된 레이어 A, B는 이미지 D, E에서 중복되므로 이미지 D, E를 설치할 때는 중복되지 않는 레이어 C만 설치하게 된다.
쿠버네티스(Kubernetes, K8S)
Docker 컨테이너 및 워크로드를 실행할 수 있는 오픈소스 통합관리 시스템
컨테이너의 양이 많아질 경우 관리가 힘들어지는 도커의 한계를 보완
기능
컨테이너 수명 주기 자동 통합관리
컨테이너의 상태 프로비저닝, 예약, 삭제 및 모니터링 기능
수요에 따라 리소스를 빠르게 확장하거나 축소
많은 시스템을 통합, 컨테이너를 다루기 위한 API 제공
실습
도커 설치 환경 구성
도커를 설치하기 이전 환경으로는 리눅스 운영체제를 이용할 것이다.
실습에서는 이후 도커 취약점을 분석하기 위해서 칼리 리눅스를 사용하지만 우분투를 이용하여도 무방하다.
VMware를 이용하여 칼리리눅스를 설치 후 도커를 설치한다.
VMware에 OS를 설치하는 방법은 생략한다.
도커 설치
OS의 터미널을 연 뒤 다음과 같은 명령어를 입력한다.
sudo apt update
sudo apt install docker.io
# 버전 명령어을 통한 설치 확인
docker version
아래와 같이 버전이 출력된다면 성공적으로 설치가 된 것이다.
라이프 사이클
도커에서 서비스를 실행하기 위해서는 아래와 같은 라이프 사이클을 따라야 한다.
Registry | 도커 이미지들이 저장된 저장소이다. 크게는 Docker hub가 있으며 사용자가 생성할 수도 있다. |
Image | 서비스와 환경이 통합되어 저장된 형태의 파일이다. |
Container | Image를 동작하여 현재 서비스를 이용 가능한 상태이다. |
PULL | Registry에서 이미지를 내려받는 동작이다. |
CREATE | 이미지를 이용해 컨테이너로 변환한다. |
START | 컨테이너를 메모리에 올려 실행한다. |
RUN | PULL + CREATE + START의 작업을 한번에 실행한다. |
STOP | 실행중인 컨테이너를 종료한다. |
RM | 저장된 컨테이너를 삭제한다. |
RMI | 저장된 이미지를 삭제한다. |
COMMIT | 컨테이너의 현재 상태를 이미지로 만든다. |
PUSH | 저장된 이미지를 저장소로 업로드한다. |
도커 컨테이너 실행
이미지를 설치하기 위해 Registry에서 이미지를 찾는 명령어를 실행
sudo docker search nginx
명령어를 입력하면 위와 같은 결과가 나오는데 추천 수(STARS)와 공식(OFFICAL)을 보고 알맞은 이미지를 찾는다.
도커 이미지는 누구나 업로드할 수 있기 때문에 보안에 각별히 주의해야 한다.
Registry에서 원하는 이미지를 내려받는다.
sudo docker pull nginx
설치 시 다음과 같이 일련의 코드처럼 보이는 문자(ex. e9995326b091)은 모두 레이어를 나타낸다.
설치가 잘 되었는지 확인하기 위해 다음 명령어를 이용한다.
# 저장된 이미지 조회
sudo docker images
sudo docker image ls
설치된 이미지를 이용해 컨테이너를 생성한다.
# nginx 컨테이너 생성
sudo docker create -it -p 8888:80 --name=webapp nginx
# 생성한 컨테이너 조회
sudo docker ps -a
sudo docker container ls -a
-it 옵션 : 컨테이너의 쉘(shell)이나 CLI 도구를 사용하기 위해 사용된다.
-p 옵션 : 호스트의 포트와 컨테이너의 포트를 포트 포워딩한다. 호스트의 8888 포트를 접속하면 컨테이너의 80번 포트와 연결
--name 옵션 : 컨테이너의 이름을 지정한다. 지정하지 않으면 임의의 값으로 설정된다.
생성된 컨테이너를 실행한다.
sudo docker start webapp
sudo docker ps
결과상으로는 정상적으로 실행되고 있으니 호스트의 8888번 포트로 접속해서 웹서버가 뜨는지 확인한다.
RUN 명령어를 이용하면 더 간편하게 이미지로 컨테이너를 실행할 수 있다.
sudo docker run -idt -p 8889:80 --name=webapp2 nginx
RUN 명령어는 이미지가 없을 경우 PULL, 컨테이너가 없을 경우 CREATE를 진행한 뒤 START 한다.
도커 컨테이너 상태 확인
# 도커 컨테이너 자원 사용량을 확인
sudo docker stats
# 도커 요소(컨테이너, 네트워크 등)의 상세정보를 확인
sudo docker inspect [ID]
# 도커 컨테이너 내부 프로세스 정보를 확인
sudo docker top [컨테이너 ID]
# exec는 컨테이너에서 시스템 명령어를 호출
# sh를 실행하여 내부 쉘에 접근 가능
sudo docker exec -it [컨테이너 ID] sh
도커 컨테이너 종료/삭제
# 모든 컨테이너 확인
sudo docker ps -a
# 컨테이너 중단
sudo docker pause [컨테이너ID]
# 컨테이너 종료
sudo docker stop [컨테이너ID]
# 컨테이너 삭제
sudo docker rm [컨테이너ID]
# 이미지 삭제
# 이미지를 사용하고 있는 컨테이너가 있을 시 삭제할 수 없음
sudo docker rmi [이미지ID:tag]
ID의 일부만 입력해도 해당 ID로 인식하고 삭제가 되는 것을 볼 수 있다.
도커 이미지 PUSH
도커 허브에 이미지를 업로드하기 위해서는 우선 도커 허브 계정이 있어야 한다.
hub.docker.com에서 가입을 진행하도록 한다.
업로드를 진행하기 전 nginx 이미지로 컨테이너를 생성 후 일부 수정 뒤에 새로운 이미지로 만들 것이다.
# nginx 컨테이너 생성
sudo docker run -idt -p 8000:80 --name=myweb nginx
# 변경할 index.html 파일 생성
echo "<h1> my web DOCKER </h1>" > index.html
# myweb 컨테이너에 호스트의 파일을 복사
sudo docker cp index.html myweb:/usr/share/nginx/html/index.html
주소로 접근하면 index.html 파일이 변경됨을 확인할 수 있다.
이제 해당 컨테이너를 이미지로 만든 뒤 도커 허브로 업로드시켜보자.
# 수정된 파일을 확인할 수 있다.
# A: 추가, C: 변경
sudo docker diff webapp
# 컨테이너를 도커 이미지로 생성
# -a 옵션 : 제작자를 쓰는 옵션, hub에 가입한 이름으로 안하면 push할 때 디나이됨
# sudo docker commit -a "[hub에 가입한 이름]" [컨테이너명] [원하는 레포지터리명]:[버전]
sudo docker commit -a "[hub에 가입한 이름]" myweb mynginx:1.0
# 확인
sudo docker images
# 도커 로그인(도커 허브 계정)
sudo docker login
# 도커 컨테이너에 태그 달기
# hub에 가입한 이름으로 안하면 권한 오류
sudo docker tag mynginx:1.0 [hub에 가입한 이름]/mynginx:1.0
# 도커 이미지 허브에 업로드하기
sudo docker push [hub에 가입한 이름]/mynginx:1.0
성공적으로 업로드되면 docker hub 사이트에서 내가 올린 이미지를 확인할 수 있다.
위와 같이 리눅스 상에서도 내가 올린 이미지를 검색할 수 있다.
- 모놀리식 아키텍쳐와 마이크로 아키텍쳐의 차이에 대해 알아보았다.
- 마이크로 아키텍쳐 방법을 이용하는 Docker에 대한 내용과 원리에 대해 알아보았다.
- Docker를 이용하여 nginx 서버를 구축해보면서 기초적인 사용법을 익혀보았다.
'보안 이론 > 클라우드 보안' 카테고리의 다른 글
Docker - 도커 파일, 도커 컴포즈 (0) | 2022.11.07 |
---|---|
Docker - Volume, Network (0) | 2022.11.06 |
AWS - Auto Scaling (0) | 2022.11.03 |
AWS - Load Balancing(ALB, NLB) (0) | 2022.10.26 |
AWS - RDS 활용 3-Tier 구축 (0) | 2022.10.19 |