0. 강추 추천 강의
개발자를 위한 쉬운 도커 | 데브위키 - 인프런
데브위키 | 현업 개발자가 도커를 사용한 경험을 녹여낸 새로운 커리큘럼으로 기존 교재 및 강의와 차별된 강의를 제공합니다. 단순한 명령어 사용법이 아닌 도커를 왜 사용해야하는지 대한 근
www.inflearn.com
1. 가상화 기술
- 컴퓨터 안에서 또 컴퓨터를 실행하는 기술
- 물리적인 컴퓨팅 환경 내부에서 논리적인 컴퓨팅 환경을 만들 수 있는 기술
가상현실은 실제로 존재하는 현실은 아니지만, 마치 존재하는 것처럼 느껴지고
가상 화폐 역시 실제로 눈으로 볼 수 있는 화폐는 아니지만 물건을 구입하는 등 화폐 역할을 수행하는 것처럼
가상화 기술은 마치 컴퓨터가 있는 것처럼 만들어주는 기술..!
2. 엔터프라이즈 서버 운영 방식 3가지
👉 베어메탈, 하이퍼바이저, 컨테이너
베이메탈(Baremetal)
- 서버를 하나 구입한 다음에, 서버 위에 OS를 설치하고 여러 개의 소프트웨어를 실행시키는 것
- 그러나 이 방식은 기업에서 운영하기에는 비효율적...
- 수많은 물리적인 서버를 관리해야 한다고 생각해 보자!
하이퍼바이저(Hypervisor)
- 하이퍼바이저는 컴퓨터에 설치되는 프로그램
- 이 하이퍼바이저를 사용해서 가상 OS를 만들고, 실행시키거나 종료시킬 수 있음
- 호스트 OS
- 물리적인 서버에 설치되는 OS
- 이 호스트 OS에 하이퍼바이저를 설치해서 가상 환경을 만들 수 있음
- 하이퍼바이저는 호스트 OS의 자원을 격리해서 새로운 OS를 실행함
- 물리적인 하드웨어와 직접 연결되어 있음
- 게스트 OS
- 호스트 OS의 리소스를 나눈 논리적인 공간
- 논리적으로 격리되어 있는 게스트 OS를 일반적으로 '가상 머신'이라고 부름
- 이 가상 머신에 웹 서버, WAS, DB와 같은 서버 프로그램을 프로세스로 실행해서 운영함
- 윈도우 호스트 OS에서 리눅스 게스트 OS를 실행할 수 있는 것처럼 호스트 OS와 다른 종류의 게스트 OS를 사용할 수 있는 이유는, 하이퍼바이저가 다른 커널 간의 언어를 통역해 주는 통역과 역할을 하기 때문!
컨테이너(Container)
- 하이퍼바이저 가상화가 하이퍼바이저라는 소프트웨어로 격리된 공간을 만들었다면, 커널의 자체 기술(LXC)을 사용해서 격리된 공간을 만든 것이 컨테이너 가상화 (그 각각의 격리된 공간을 '컨테이너'라고 부름)
- 모든 컨테이너는 호스트 OS의 커널을 공유해서 사용 (컨테이너 가상화의 가장 중요한 특징 중 하나)
- 컨테이너 가상화는 하이퍼바이저 가상화보다 훨씬 더 부팅 속도가 빠르고 가볍기 때문에, 모던 애플리케이션 운영 환경에서 선호된다.
3. 도커(Docker)
- 도커라는 소프트웨어는 컨테이너 가상화 기술을 편리하게 사용하기 위해 만들어진 소프트웨어로, 사용자는 도커를 통해서 컨테이너를 만들고, 운영할 수 있다. 도커와 같은 컨테이너 가상화 도구를 컨테이너 플랫폼이라고 부른다.
- 컨테이너 플랫폼 = 컨테이너 엔진 + 컨테이너 런타임
- 컨테이너 엔진
- 사용자의 요청을 받아서 컨테이너를 관리해 주는 역할
- 컨테이너 런타임
- 직접 커널과 통신하면서 실제로 격리된 공간을 만드는 역할
도커 아키텍처
- 도커는 클라이언트 - 서버 모델로 실행됨
- 클라이언트
- 사용자의 명령을 도커 데몬에게 전달
- 도커 데몬
- 호스트 OS 커널의 기능을 활용해서 컨테이너를 관리하는 기능을 제공
- 도커 데몬은 클라이언트가 기능을 사용할 수 있도록 API를 제공
- 클라이언트 CLI(Command Line Interface)
- CLI를 통해 간단한 명령어를 사용해 컨테이너를 관리할 수 있음
- 명령어를 실행하면 CLI는 API에 맞게 요청을 만들어 도커 데몬에 전달
- 도커 데몬은 컨테이너 런타임을 통해서 컨테이너를 조작하고 그 결과를 CLI로 전달
정리
- 컨테이너를 생성해서 프로세스를 실행시키면, 이 프로세스는 디스크/네트워크/메모리/CPU 같은 공간이 완전히 격리된 공간에서 실행
- 여러 개의 컨테이너를 실행시키면, 각각의 컨테이너를 격리된 공간에서 안전하게 운영할 수 있다.
4. 이미지와 컨테이너
서버에서 프로그램을 실행하기 위해서는 소프트웨어적으로 3가지가 필요
- 기본 OS
- 프로그램이 실행하기 위해서 필요한 구성 요소 (특정 패키지, 라이브러리 의존성, 자바 런타임과 같은 런타임 언어 등)
- 실행시킬 프로그램
이미지
- 이미지란, 파일 시스템의 특정 시점을 저장해 놓은 압축파일
- 단순히 소프트웨어뿐만 아니라 소프트웨어가 실행하기 위해서 필요한 모든 요소들을 준비해서 압축한다.
- 가상 머신의 스냅샷과 비슷하나 압축 파일의 사이즈가 훨씬 작아 인터넷을 통해 저장하고 공유하기가 훨씬 수월하다.
- 직접 이미지를 만들 수도 있고, 다른 사람이 만든 것을 사용할 수도 있다.
- 디스크 공간만 차지
컨테이너
- 컨테이너는 이미지를 통해서 실행할 수 있다.
- 이미지를 컨테이너로 실행시키면, 호스트 OS 안에서 완전히 격리된 공간인 컨테이너가 만들어지고 이 컨테이너 안에서 소프트웨어가 실행된다.
- CPU와 메모리를 사용
이미지는 프로그램이 실행되기 위한 환경이 모두 포함되어 있는 파일 시스템이고,
이 이미지를 실행한 것이 컨테이너이다.
이미지의 메타데이터
- 메타데이터란 데이터에 대한 데이터
- 이미지가 실제로 압축된 데이터라면, 메타데이터는 이 이미지에 대한 정보를 기술하는 데이터
- ENV
- 소프트웨어가 실행 시 참조할 설정 정보
- CMD
- 컨테이너 실행 시 프로세스 실행 명령 지정
컨테이너의 라이프사이클
이미지 네이밍 규칙
- 이미지 레지스트리란 도커 이미지를 저장하기 위한 저장소
- 이미지 레지스트리를 통해서 다른 사람과 공유하거나 필요한 이미지를 다운 받을 수 있다.
- 이미지 이름에는 이미지를 어디서 다운받는지, 어떤 버전의 이미지를 다운받는지에 대한 정보가 모두 포함되어 있어야 한다.
레지스트리주소/프로젝트명/이미지명:이미지태그
(docker.io)/happyprogfrog/MyNginx:2.1.0-alpine
- 레지스트리주소
- 어떤 레지스트리를 사용할지 지정
- 비어있는 경우에는 기본값으로 지정된 레지스트리 주소가 사용됨
- 도커를 사용한다면 기본 레지스트리 값은 docker.io
- 프로젝트명
- 도커 허브의 경우 계정명이 프로젝트명
- 이미지명
- 다운받을 이미지의 이름
- 이미지태그
- 이미지 버전을 의미
- 기본값은 최신 버전을 의미하는 latest
- 공식 이미지의 경우 nginx와 같이 이미지명만 작성하기도 함
이미지와 레이어
- 이미지는 컨테이너를 실행하기 위한 읽기 전용 파일
- 도커 이미지는 저장소를 효율적으로 사용하기 위해 레이어드 파일 시스템으로 구성되어 있음
- 이미지 레이어: 읽기 전용 레이어
- 컨테이너 레이어: 읽기/쓰기 레이어
- Layering
- 각 레이어는 이전 레이어 위에 쌓이며, 여러 이미지 간에 공유될 수 있음
- 레이어 방식은 중복 데이터를 최소화하고, 빌드 속도를 높이며, 저장소를 효율적으로 사용할 수 있게 해 줌
- Copy On Write 전략
- 다음 레이어에서 이전 레이어의 특정 파일을 수정할 때, 해당 파일의 복사본을 만들어서 변경사항을 적용
- 원래 레이어는 수정되지 않고 그대로 유지
- Immutable Layers
- 이미지의 각 레이어는 불변으로, 한 번 생성되면 변경되지 않음
- 이렇게 함으로써 이미지의 일관성을 유지하고, 여러 컨테이너에서 안전하게 공유할 수 있음
- Caching
- 레이어를 캐시하여, 이미 빌드된 레이어를 재사용할 수 있음
- 이는 이미지 빌드 시간을 크게 줄여주며, 같은 레이어를 사용하는 여러 이미지에서 효율적으로 작동
- 변경되지 않는 레이어들을 아래의 레이어로 배치하면 캐싱을 활용하는 빈도를 높일 수 있다.
- ex) 라이브러리 설치 단계와 애플리케이션 빌드 과정을 분리
5. 이미지 커밋
이미지를 만드는 방식은 크게 두 가지
- 커밋 방식: 현재 컨테이너의 상태를 이미지로 저장
- 빌드 방식: Dockerfile을 통해 이미지를 저장
커밋 방식
# 이미지 실행과 동시에 터미널 접속
docker run -it --name officialNginx nginx /bin/bash
# index.html 내용 변경
echo hello-my-nginx > /usr/share/nginx/html/index.html
# 실행 중인 컨테이너를 이미지로 생성
docker commit -m "edited index.html" -c 'CMD ["nginx", "-g", "daemon off;"]' officialNginx happpyprogfrog/commitnginx
# 컨테이너로 실행
docker run -d -p 80:80 --name my-nginx happpyprogfrog/commitnginx
빌드 방식
- IaC(Infrastructure as Code): 인프라 상태를 코드로 관리
- Dockerfile: 이미지를 만드는 단계를 기재한 명세서
- 빌드 컨텍스트
- 이미지를 빌드할 때 전달되는 폴더
- .dockerignore 파일을 통해 전달될 수 있는 파일을 관리할 수 있음
# 베이스 이미지를 지정
FROM 이미지명
# 파일을 레이어에 복사
COPY 파일경로 복사할경로
# 컨테이너 실행 시 명령어 지정
CMD ["명령어"]
FROM nginx:1.23
COPY index.html /usr/share/nginx/html/index.html
CMD ["nginx", "-g", "daemon off;"]
멀티 스테이지 빌드
- 도커 파일에서 두 개의 베이스 이미지를 활용하는 방법
- 빌드에 사용하는 이미지와 실행에 사용하는 이미지로 나눈 것
- 이 멀티 스테이지 빌드를 잘 활용하면, 실제 애플리케이션이 실행되는 이미지 크기를 줄일 수 있다.
6. 클라우드
- 다른 회사의 서버를 빌려서 운영
- 사용 요청 즉시 서버를 생성(Provisioning)
- 실제 사용한 시간만큼 비용 지불
- 마소의 Azure, 아마존의 AWS, 구글의 GCP
- 특징
- 트래픽이 증가할 때 빠르게 대처 가능
- 장애 발생 시 빠르게 복구 가능
- 사용한 만큼만 지불할 수 있으므로 운영 비용에 효율적
클라우드 네이티브
클라우드 환경을 더 잘 활용할 수 있는 애플리케이션 구조
- MSA : 트래픽 증가에 빠르게 대처하기 위해서 애플리케이션이 MSA 구조로 개발되어야 함
- Container: 컨테이너를 활용해 실행 환경에 종속되지 않는 동작이 보장되어야 함
- Stateless: 애플리케이션 서버는 상태를 가지지 않아야 하며, 상태를 가지지 않은 애플리케이션은 어디에나 즉시 배포 가능
- DevOps와 CI/CD: 배포가 자동화되어야 하고, 빠르게 릴리즈가 수행되어야 함
모놀리식 vs. MSA
모놀리식 아키텍처 | 마이크로서비스 아키텍처 | |
구조 | 단일 코드베이스와 애플리케이션 | 기능별로 독립된 서비스 |
배포 | 전체 재배포 필요 | 개별 서비스 독립 배포 |
확장성 | Scale-Up 주로 사용 | Scale-Out 용이 |
개발 속도 | 초반 개발 속도는 빠르나, 코드베이스 커질 수록 느려짐 | 초기 구성 복잡하고 오래 걸림 |
장애 영향도 | 전체 애플리케이션 영향 | 영향이 적고 분리 가능 |
기술 스택 | 일반적으로 하나의 스택 | 서비스별 다양한 스택 가능 |
유지 보수 | 전체 코드 이해 필요 | 각 서비스 별로 개발 및 유지보수 |
복잡성 | 낮음 | 서비스 간 통신, 데이터 일관성 유지 등 복잡성이 매우 높음 |
7. 도커 네트워크
네트워크
- 네트워크는 여러 개의 장치들이 서로 연결되어 정보를 주고받을 수 있는 시스템
- 네트워크는 기계와 기계 사이를 랜선이라는 케이블로 물리적으로 연결
- 이 물리적인 케이블을 통해 전기신호를 통해서 정보를 주고받을 수 있다.
- 실제로 바다 건너 미국에 있는 컴퓨터의 정보를 받아올 때도, 아시아와 미국을 연결하는 해저 케이블을 통해서 정보를 받아오는 것이다!
IP 주소
- 집들에 각각의 고유한 주소가 있는 것처럼, 컴퓨터가 인터넷에 연결될 때 IP 주소를 할당받는다.
- 이 IP 주소를 통해서 컴퓨터나 기계들이 인터넷에서 서로를 찾고 통신할 수 있는 것!
- 8바이트에 3자리 숫자 4개 조합 ex) 223.130.200.107
- 고유하며, 다른 IP 주소와 중복될 수 없다.
- IP 주소는 각각 통신사가 관리하고 있다.
공인 IP와 사설 IP
- IP 주소는 8비트 숫자 4개의 조합 (0.0.0.0 ~ 255.255.255.255)
- 약 43억 개의 이 주소는 인터넷과 디바이스가 빠르게 늘어남으로써 점차 고갈되고 있다.
- 따라서, 하나의 IP로 여러 기기가 인터넷을 사용하려면 사설 IP를 사용해야 한다.
- 공인 IP는 집 주소, 전 세계에서 유일
- 사설 IP는 방 주소, 집 내에서 유일 (하나의 공인 IP를 나누어서 정의)
- WAN, LAN
- WAN: 공인 IP를 받는 인터넷 선을 꽂아놓는 부분
- 외부에서 들어오는 인터넷 신호를 연결해야 한다.
- LAN: 각각의 기기에 연결해서 사설 IP를 분배하는 곳
- 공유기에 연결되는 장비들은 새로운 사설 IP를 할당받아 인터넷을 사용할 수 있다.
- 하나의 네트워크 장비(ex. 공유기) 안에서만 고유하다.
- WAN: 공인 IP를 받는 인터넷 선을 꽂아놓는 부분
- 공인망, 사설명
- 공인망: 공인 IP를 사용하는 네트워크 통신
- 사설망: 기업 안에서 사설 IP를 사용한 통신망
- 이 기업에서 사용하는 IP가 124.111.46.91이라고 하면,
- 이 IP를 각각의 사내 서버로 분배해 주는 라우터라는 장비가 존재(공유기와 비슷한 역할 수행)
- 가정에서 구성하는 네트워크보다 더 복잡할 뿐이지 구조는 동일하다.
NAT
내부 -> 외부 서버
- Network Address Translation
- 공인 IP와 사설 IP를 맵핑해 주는 기술
- 공인 IP와 사설 IP의 맵핑 테이블을 만들어 놓고, 어떤 서버로 전달할지에 대한 정보를 기록해 두는 것
- 사설망을 구성하는 라우터 장비는 모두 이 NAT 기능을 가지고 있다.
- NAT 테이블은 공인 IP의 랜덤 한 포트를 여러 개 지정해 두고, 각각의 포트에 사설 IP의 정보를 매칭시켜서 활용함
포트포워딩
외부 서버 -> 내부
- 외부에서 사내망으로 접근할 때는 포트포워딩이라는 기술을 사용하여, 사용자가 직접 NAT 테이블과 같은 맵핑 정보를 관리
- 외부에서 공인 IP의 포트로 접근할 때, 포트포워딩 룰에 맞는 사설 IP로 변환해서 트래픽을 전달해 줌
DNS
- Domain Name System
- https://www.naver.com과 같은 도메인 주소가 IP 주소보다 더 외우기 쉽고 직관적이다.
- 사용자가 이런 도메인 주소를 사용해서 접근할 수 있도록 도메인 주소와 IP 주소 데이터를 가지고 있는 시스템
가상 네트워크
도커 네트워크의 포트포워딩 기술
docker run -p HostOS의포트:컨테이너의포트
- docker run 명령을 사용할 때 -p 옵션을 사용해서 포트를 지정했었다.
- -p 옵션은 콜론(:)을 기준으로 두 개의 포트를 지정하는데,
- 왼쪽은 내 PC인 호스트 OS의 포트를 지정하고
- 오른쪽은 컨테이너가 사용하는 포트를 지정한다.
- 이렇게 하면, 이 도커가 실행 중인 서버의 포트를 사용해서 컨테이너로 접근할 수 있다.
가상 네트워크 안에서 컨테이너를 실행하면 기본적으로 컨테이너들끼리는 통신이 가능하다.
그러나 사용자 PC인 호스트 OS나 가상 네트워크 바깥에 있는 서버에서 이 컨테이너로 접근하려면 '포트포워딩' 기술을 사용해야 한다. 호스트 OS의 포트는 아무거나 지정해도 상관없지만, 이미 포트포워딩으로 등록된 포트는 중복해서 설정할 수 없다.
가상 네트워크와 DNS
- 도커는 컨테이너들이 기본적으로 사용할 수 있는 DNS 서버를 제공한다.
- 이 DNS 서버에는 IP 주소와 도메인명이 저장되어 있으며, 도메인은 컨테이너의 이름으로 자동 저장된다.
- 그래서 컨테이너들은 컨테이너의 IP가 아닌 컨테이너의 이름으로 서로 통신할 수 있다.
- 이 DNS 서버는 외부의 DNS 서버와도 연동이 되어있기 때문에 google.com 같은 외부 도메인도 사용할 수 있다.
- 다만 기본으로 생성되는 브릿지 네트워크는 이 DNS 기능이 제공되지 않고, 사용자가 직접 생성한 브릿지만 컨테이너의 이름을 통해서 통신할 수 있다.
8. 스토리지와 볼륨
9. 도커 컴포즈
- 도커 컴포즈는 많은 양의 컨테이너를 편리하게 다룰 수 있는 도구
- 도커 컴포즈의 캐릭터를 살펴보면, 문어의 다리가 여러 개 있고 이 다리로 컨테이너를 들고 있는 모습이다.
- 이는 컴포즈가 여러 개의 컨테이너를 핸들링하기 위한 도구라는 것을 보여주는 것이다.
- 도커 컴포즈도 도커 파일 같은 정의서가 필요하면, YAML이라는 문법을 사용해서 컴포즈 파일을 작성해야 한다.
- 이 컴포즈 파일을 사용해서 여러 개의 컨테이너를 관리할 수 있다.
- 도커 파일을 작성할 때와 마찬가지로 IaC 방법론을 적용해서 소스코드로 컨테이너를 관리할 수 있다.
10. DevOps, 파이프라인, CI/CD 파이프라인
DevOps
- DevOps는 개발을 의미하는 Development와 운영을 의미하는 Operations의 합성어
- 보통 개발자 그룹과 운영자 그룹은 사이가 좋지 않다ㅋㅋㅋㅋ전통적인 IT 개발 환경에서 개발자의 목표는 애플리케이션에 새로운 기능을 추가하는 것이고, 운영자의 목표는 안정적으로 서비스를 운영하는 것이다. 그런데 개발자가 새로운 기능을 추가해서 애플리케이션이 변경되면, 서버에 새로운 버전으로 배포를 해야 하고 이 애플리케이션을 배포하는 과정에서 서비스에 장애가 발생하는 경우가 많이 있었다.
- 그래서 운영자는 새로운 기능을 추가하는 것에 방어적이 되고, 개발자 그룹과 운영자 그룹이 서로를 탓하면서 마찰이 일어나는 과정이 업무 프로세스를 비효율적으로 만들었다.
- 이렇게 의사과정이 느려지면 느려질수록 결국 고객에게 제공하기 위한 서비스의 질은 떨어질 수밖에 없다.
DevOps는 운영자와 개발자의 간격을 없애기 위한 문화이다.
- 결국 개발자나 운영자가 목표하는 것은 질 높은 서비스를 제공하고자 하는 것!
- DevOps는 배포 과정에서 일어날 수 있는 많은 문제들을 해결하는 것이 목표이다.
- 그중 대표적인 것이 컨테이너를 도입해서, 환경의 차이를 줄이는 것이다.
- DevOps가 지향하는 기술들: CI/CD, 자동화, MSA, IaC
- 그리고 이 기술들의 가장 아래 뿌리 역할을 하는 것이 바로바로바로 컨테이너!
파이프라인
- 파이프라인은 물이 흐르는 관을 의미
- 파이프라인의 시작 지점에 물을 넣으면, 파이프라인의 끝까지 물이 자동으로 흐르게 된다.
- IT 운영 환경의 파이프라인 개념에서는 파이프라인 안에 물 대신 소스 코드가 흘러간다고 생각하면 된다.
- 첫 지점에 넣은 소스 코드는 👉 파이프라인을 흐르면서 아티팩트로 빌드되고 👉 이 아티팩트가 운영 환경까지 배포된다.
일련의 과정들이 자동화되어서 개발자가 소스 코드를 push 했을 때,
배포까지 자동화가 이루어지는 것을 CI/CD 파이프라인이라고 부른다.
CI/CD 파이프라인
- CI/CD 파이프라인은 CI 파이프라인과 CD 파이프라인으로 나눌 수 있다.
- CI
- 지속적 통합
- 배포 환경에 배포할 수 있는 아티팩트를 만드는 단계를 자동화하는 것을 의미
- 일반적으로 컨테이너 환경에서는 이미지를 빌드하고 푸시하는 단계까지를 자동화하는 것을 의미
- CD
- 지속적 배포
- CI 파이프라인에서 생성된 아티팩트를 실제 환경에 배포하는 것을 의미
👉 다음글
[도커] 명령어 정리
# 컨테이너에 명령 실행하기docker exec -it postgres /bin/bash# 클라이언트, 서버 버전 및 상태 확인docker version# 플러그인, 시스템 상세 정보 확인docker info# 메뉴얼 확인docker --help# 컨테이너 실행docker ru
progfrog.tistory.com