Docker
'데이터 또는 프로그램을 격리시키는 기능'을 제공하는 소프트웨어
- 다양한 프로그램과 데이터를 각각 독립된 환경에 격리하는 기능을 제공 (운영체제 통째로 격리)
- 각각의 독립된 환경을 컨테이너라고 함
- 이 컨테이너를 다루는 기능을 제공하는 소프트웨어가 도커(docker)
- 도커를 사용하려면 도커 소프트웨어 본체인 엔진(docker engine) 을 설치해야함. 그리고 도커 엔진을 사용해 컨테이너를 생성하고 구동할 수 있음
- 컨테이너를 만들려면 도커 엔진 외에도 컨테이너의 빵틀과도 같은 역할을 할 "이미지" 가 필요함
- 도커는 리눅스 컴퓨터에서 사용함. 컨테이너에서 동작시킬 프로그램도 리눅스용 프로그램임. => 도커가 리눅스 운영체제에서 사용하는 것을 전제로 만들어졌기 때문
데이터나 프로그램을 독립된 환경에 '격리'해야 하는 이유
- 공유하는 대상을 어느 한쪽만을 위해 수정하면 다른 쪽에서 오류가 발생하게 된다. (프로그램 간 공유)
- 도커 컨테이너를 사용해 프로그램을 격리하면 '여러 프로그램이 한 서버에서 실행되면서 발생하는 문제를 대부분 해결할 수 있음'
- 일반적인 환경에서는 한 대의 서버 혹은 컴퓨터에서 한 벌만 설치할 수 있는 소프트웨어가 대부분. 그러나 도커 컨테이너는 완전히 독립된 환경이므로 여러 컨테이너에서 같은 프로그램을 실행할 수 있음
- 컨테이너는 자유로이 옮길 수 있다
컨테이너의 정보를 내보내기한 다음, 다른 도커 엔진에서 복원하는 형태로!
도커만 설치돼 있으면 되므로 운영체제가 달라도 이를 신경 쓰지 않고 컨테이너를 옮길 수 있음
- 도커를 이용하면 "물리적 환경의 차이, 서버 구성의 차이를 무시"할 수 있음
서버와 도커
-
도커는 서버에서 사용되는 소프트웨어
서버: 어떤 서비스(service)를 제공(serve)하는 것
-
'기능적 의미의 서버'와 '물리적 컴퓨터로서의 서버'
기능적 의미의 서버
'무스무슨 서버'라는 말은 '무슨무슨 기능을 제공한다'는 의미
* 예) 메일서버: 메일 기능을 제공하는 서버
- 물리적 컴퓨터로서의 서버
- 데스크톱 컴퓨터와 마찬가지로 어딘가에 물리적으로 존재하는 컴퓨터
-
하나의 '물리적 컴퓨터로서의 서버'에 여러 개의 '기능적 의미의 서버'를 함께 둘 수 있음
-
서버의 기능은 소프트웨어가 제공한다
* 소프트웨어를 설치하면 '서버'의 기능을 갖게 됨
- 예) Sendmail 갖은 메일서버 소프트웨어를 설치하면 메일 서버가 됨
- '무슨무슨 서버를 만든다'는 말은 '무슨무슨용 소프트웨어를 설치해 이 기능을 갖춘다'는 말과 같음
도커와 가상화 기술의 차이
도커 vs. 가상화 기술
- 도커는 "실행 환경을 독립적으로 격리한 컨테이너"
* 운영체제의 기능 중 일부를 호스트 역할을 하는 물리 서버에게 맡겨 부담을 덜어 둔 형태
- 컨테이너는 운영체제의 일부 기능을 호스트 컴퓨터에 의존하기 때문에 물리 서버에도 리눅스 기능이 필요하며, 컨테이너의 내용도 리눅스 운영체제가 될 수밖에 없음
- 가상화 기술(ex: VirtualBox, VMware)은 가상의 물리 서버를 만드는 것 (물리적 대상을 소프트웨어로 대체함)
* 즉, 메인보드와 CPU, 메로리 등의 물리적인 소품을 소프트웨어로 구현하는 것
도커 vs. AWS EC2
- AWS EC2는 가상화 기술
- 다만, "인스턴스"는 컨테이너와 마찬가지로 AMI라는 이미지로부터 생성하므로 인스턴스를 배포하는 방법은 도커와 비슷
도커 vs. 호스팅 서비스
- AWS ECS가 이에 해당
- 이들 서비스를 사용하면 별도로 가상 서버를 만들지 않아도 컨테이너 이미지를 그대로 실행할 수 있음
도커의 동작 원리
도커의 구조
물리서버 > 서버운영체제 > 도커소프트웨어(도커엔진) > 컨테이너
- 프로그램 및 데이터(일부)는 컨테이너 안에 위치 예) 메일서버 프로그램은 컨테이너에 설치
- 모든 컨테이너에는 '리눅스 운영체제 비슷한 무언가'가 들어있음 (운영체제 비슷한 무엇가일 뿐 실제 운영체제가 아님)
- 도커 엔지 아래에도 리눅스 운영체제가 있는데, 컨테이너 속에 또 리눅스 운영체제(비슷한 것)가 있다.
- 도커에서는 컨테이너가 완전히 분리돼 있으므로 밑바탕이 되는 리눅스 운영체제의 주변 부분이 컨테이너 속 프로그램의 명령을 전달받을 수 없다. 따라서 컨테이너 속에 운영체제의 주변 부분이 들어 있어 프로그램의 명령을 전달받고 이를 밑바탕이 되는 커널에 전달하는 구조로 돼 있다 => 컨테이너 속에 '리눅스 운영체제 비슷한 것'이 들어 있는 것은 이 때문! 전체 리눅스 운영체제가 들어있는 것이 아니라 주변 부분만 들어있기 때문에 '비슷한 것'이라고 표현하는 것
- 간단하게 리눅스 운영체제 전체를 컨테이너 속에 넣으면 되지 않을까 싶지만 주변 부분만 컨테이너에 넣고 커널은 밑바탕에 있는 것을 빌려 쓰는 형태 => 도커의 가장 큰 장점 '가벼움'을 얻을 수 있음!
운영체제가 하는 일
운영체제: 소프트웨어나 프로그램의 명령을 하드웨어에게 전달하는 역할
- 운영체제는 '커널'이라는 부분과 '그 외의 주변 부분'으로 구성됨
- 주변 부분: 프로그램에서 명령을 전달받거나 커널이 실행 결과물을 프로그램에 다시 전달하는 역할
도커는 기본적으로 '리눅스용'이다
- 도커는 밑바탕에 "리눅스 운영체제가 동작하는 것을 전제"로 하는 구조로 돼 있기 때문에 "리눅스 운영체제에서만 동작"할 수 있다
- 컨테이너 안에 들어 있는 주변 부분도 이에 맞춰 "리눅스 운영체제의 주변 부분"이어야 한다
도커 허브와 이미지, 그리고 컨테이너
- 도커 이미지: 컨테이너를 만드는 "빵틀"과 같은 것 => 컨테이너의 설계도 역할!
- 도커 허브: 인터넷 상에 도커 이미지를 모아 놓은 곳
- 컨테이너로도 이미지를 만들 수 있다!
- 컨테이너는 도커 엔진만 설치돼 있으면 구동이 가능하므로 다른 서버나 컴퓨터에 도컨 엔진을 설치하고 새로운 도커 엔진에 이미지를 이용해 똑같은 컨테이너를 생성하여 컨테이너를 이동 시키는 효과를 얻을 수 있음 => 즉, 동일한 컨테이너를 여러 개 만들지 않더라도 다른 물리 서버에 설치된 도커 엔진으로 컨테이너를 이동시는 효과!
도커 허브와 도커 이미지
- 도커허브: 공개된 컨테이너 이미지가 모여 있는 곳
도커 컨테이너의 생애주기와 데이터 저장
- 컨테이너는 '오랫동안 아껴 쓰는' 물건이 아니라 '그때그때 스고 버리는' 일회용품에 가깝다
- 컨테이너는 쉽게 만들 수 있다. 그러므로 컨테이너 하나를 업데이트하면 계속 사용하기보다는 업데이트된 소프트웨어가 들어있는 새로운 컨테이너를 사용하는 것이 좋음 => 즉, 새로운 버전이 나오면 새로운 컨테이너로 갈아타는 것
* 이것이 가능한 이뉴는 컨테이너는 일반적으로 여러 개를 동시 가동하는 상황을 전제로 하기 때문
컨테이너의 생애주기
컨테이너를 '만들고', '실행하고', '종료하고', '폐기한' 다음, 다시 컨테이너를 '만드는' 일련의 과정
데이터 저장
- 컨테이너를 폐기하면 해당 컨테이너 안에서 편집된 파일은 당연히 사라진다. 이 파일은 컨테이너 안에 들어있었기 때문
- 이런 일을 방지하기 위해 보통은 "도커가 설치된 물리적 서버(호스트)의 디스크를 마운트해" 이 디스크에 데이터를 저장한다
도터의 장점과 단점
- 장점 => "여러 개", "이동성", "생성", "보안"
* 한 대의 물리 서버에 여러 대의 서버를 띄울 수 있다
- 서버 관리가 용이하다
- 서버 고수가 아니어도 다루기 쉽다
- 단점
* 리눅스용 소프트웨어밖에 지원하지 않는다
- 호스트 서버에 문제가 생기면 모든 컨테이너에 영향이 미친다
- 컨테이너를 여러 개 사용하는 형태를 가정하므로 컨테이너 하나를 장기간에 걸쳐 사용할 때는 그리 큰 장점을 느끼기 어렵다
도커의 주 용도
- 팀원 모두에게 동일한 개발환경 제공하기(=동일한 환경을 여러 개 만들기)
- 새로운 버전의 테스트(=격리된 환경을 이용)
- 동일한 서버가 여러 대 필요한 경우(=컨테이너 밖과 독립된 성질을 이용)
도커 사용하기
1. 도커 엔진 시작하기
2. 컨테이너 관련 명령어
docker <상위커맨드:무엇을> <하위커맨드:어떻게> (옵션) <대상> (인자)
예) docker container run -d penguin --mode=1
"container"를 실행하라 모드 1(백그라운드 모드)로
docker run
- docker image pull
- docker container create
- docker container start
위의 명령어 3개를 하나로 합친 것이 "docker run"
포트 설정 방법
-p <호스트포트번호>:<컨테이너포트번호>
예) -p 8080:80
docker ps
docker container ls
위의 명령을 줄여서 docker ps
가상 네트워크 만들기
docker network create <가상네트워크명>
워드프로세스 구축하기 관련 명령어
1. mysql 컨테이너 실행
docker run --name 컨테이너명 -dit --net=네트워크이름 -e MYSQL_ROOT_PASSWORD=루트패스워드 -e MYSQL_DATABASE=데이터베이스이름 -e MYSQL_USER=사용자명 -e MYSQL_PASSWRD=사용자패스워드 mysql --character-set-server=문자인코딩 --collaction-server=정령순서 --default-authentication-plugin=인증방식
docker run --name mysql000ex11 -dit --net=wordpress000net1 -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=mydatabase -e MYSQL_USER=writer -e MYSQL_PASSWORD=password mysql --character-set-server=utf8mb4 --collaction-server=utf8mb4_unicode_ci --default-authentiation-plugin=mysql_native_password
2. 워드프로세스 컨테이너 실행
- 워드프로세스 공식이미지에는 워드로프로세스, apache, php가 함께 들어있음
docker run --name 컨테이너명 -dit --net=네트워크이름 -p 포트설정 -e WORDPRESS_DB_HOST=데이터베이스컨테이너명 -e WORDPRESS_DB_NAME=데이터베이스명 -e WORDPRESS_DB_USER=데이터베이스사용자명 -e WORDPRESS_DB_PASSWORD=데이터베이스패스워드 wordpres
docker run --name wordpress000ex12 -dit --net=wordpress000net1 -p 8085:80 -e WORDPRESS_DB_HOST=mysql000ex11 -e WORDPRESS_DB_NAME=mydatabase -e WORDPRESS_DB_USER=writer -e WORDPRESS_DB_PASSWORD=mysql wordpress
도커 명령어 참조
컨테이너<->호스트 파일 복사하기
docker cp A B
A를 B로 복사하기
-
컨테이너 <- 호스트
docker cp <호스트경로> <컨테이너이름>:<컨테이너경로>
-
컨테이너 -> 호스트
docker cp <컨테이너명:컨테이너경로> <호스트경로>
볼륨 마운트
마운트: '연결하다'라는 의미 그대로 대상을 연결해 운영체제 또는 소프트웨어의 관리하에 두는 일을 말함
데이터 퍼시스턴시 (data persistency): 컨테이너는 생성 및 폐기가 매우 빈번하기 때문에 매번 데이터를 옮기는 대신 처음부터 켄테이너 외부에 둔 데이터에 접근해 사용하는 것이 일반적임. 이를 '데이터 퍼시스턴시'라고함. 이때 데이터를 두는 장소가 '마운트된 스토리지 영역'임
스토리지 마운트라고 하면 의미가 모호하기 때문에 관례적으로 '볼륨 마운트'라는 용어를 사용하는데, 마운트 대상이 되는 스토리지는 볼륨 외에도 디렉터리나 파일, 메모리가 될 수 있음!
- 스토리지 마운트의 종류
- 볼륨 마운트
- 바인드 마운트
- 임시 메모리(tmpfs) 마운트
볼륨 마운트
-
볼륨 생성/확인/삭제
// 볼륨생성
docker volume create <볼륨명>
// 볼륨 상세 정보 확인
docker volume inspect <볼륨명>
// 볼륨 삭제
docker volume rm <볼륨명>
-
docker volume create <볼륨명>
으로 생성한 볼륨의 위치는 도커 엔진에서 알아서 관리함
-
위에서 생성한 볼륨 도커 컨테이너에 연결하여 실행하기
docker run --name <컨테이너명> -d -p 8091:80 -v <볼륨명>:/usr/local/apache2/htdocs httpd
바인드 마운트
docker run --name apache-jek -d -p 8080:80 -v ./apa_foler:/usr/local/apache2/htdocs httpd
컨테이너로 이미지 만들기
- 방법1) commit 커맨드로 기존 컨테이너를 이미지로 변환
docker commit <컨테이너 이름> <새로운 이미지 이름>
- 방법2) dockerfile 스크립트로 이미지를 만드는 방법
- dockerfile 스크립트를 작성하고, 이 스크립트를 빌드해 이미지를 만드는 방법
- dockerfile 스크립트에는 토대가 될 이미지나 실행할 명령어 등을 기재
- dockerfile을 호스트 컴퓨터의 이미지 재료가 들어있는 폴더(위치는 상관 없음)에 넣음
- 재료 폴더에는 그 외 컨테이너에 넣을 파일을 함께 둠
docker build -t <생성할 이미지 이름> <재료 폴더 경로>
컨테이너 개조
- 방법1) 파일복사와 마운트를 이용한 방법
- 방법2) 컨테이너에서 리눅스 명령어를 실행하는 방법
* docker exec -it <컨테이너명> bash
- bash가 실행되면 셸에 입력된 명령은 도커 엔진이 아니라 해당 컨테이너로 전달됨
- bash를 통해 컨테이너 내부를 조작하는 동안에는 도커 명령을 사용할 수 없음
- 컨테이너를 만들고 삭제하거나 컨테이너 자체에 대한 명령은 도커 엔진을 통해서 하는 것이고, 컨테이너 내부를 다루는 명령은 bash를 통함
도커 엔진을 통한 명령 vs. 컨테이너 내부에서 실행하는 명령
- 도커 엔진을 통한 명령
* 도커 엔진 자체의 시작/종료
- 네트워크, 디스크 설정, 실행 중인 컨테이너 목록 확인 등
- 컨테이너 전체에 대한 관리 작업
- 컨테이너 내부에서 실행하는 명령
* 컨테이너 속에서 새로운 소프트웨어를 추가하거나, 컨테이너 속 소프트웨어의 실행 및 종료, 설정 변경, 컨테이너 안과 밖의 파일 복사 및 이동, 삭제 작업
도커 허브와 도커 레지스트리
도커 레지스트리
: 이미지를 배포하는 장소
도커 허브
: 도커 제작사에서 운영하는 공식 도커 레지스트리
레지스트리 vs. 리포지토리
- 레지스트리: 이미지 배포 장소
- 리포지토리: 레지스트리를 구성하는 단위
- '이미지 태그'를 붙이는 방법
* <레지스트리 주소>/<리포지토리이름>:<버전>
- 예) zozo.comm/nayapachi:13
도커 컴포즈
- 도커 컴포즈는 도커 설정을 기재한 설정 파일을 이용해 한 번에 여러 개의 컨테이너를 생성, 실행, 폐기하는 기능을 제공
- 도커 컴포즈는 시스템 구축에 필요한 설정 YAML(YAML Ain't a Markup Language) 포맷으로 기재한 정의 파일을 이용해 전체 시스템을 일괄 실행(run) 또는 일괄 종료 및 삭제(down)할 수 있는 도구
도커 컴포즈 vs. Dockerfile 스크립트
- 도커 컴포즈는 docker run 명령어를 여러 개 모아놓은 것과 같음. 컨테이너와 주변 환경을 생성. 네트워크와 볼륨까지 함께 만들 수 있음
- Dockerfile 스크립트는 이미지를 만들기 위한 것으로 네트워크나 볼륨은 만들 수 없음
도커 컴포즈 vs. 쿠버네티스
- 쿠버네티스는 컨테이너를 관리하는 도구인 데 비해,
- 도커 컴포즈의 기능은 컨테이너를 생성/삭제하는 것 뿐 (컨테이너 관리기능은 X)
서비스와 컨테이너
- 도커 컴포즈가 컨테이너에 모인 것을 '서비스'라고 부름
쿠버네티스 (k8s)
- 쿠버네티스는 컨테이너 오케스트레이션 도구의 일종으로, 도커 컴포즈보다 더욱 다양한 컨테이너 관리 기능을 제공
- 쿠버네티스는 여러 대의 물리적 서버가 존재하는 것을 전제로 함. 또 이 물리적 서버 한 대 한 대마다 제각기 여러 대의 컨테이너를 실행
- 쿠버네티스도 컨테이너를 생성하거나 삭제할 수 있지만 일일이 명령어를 입력하는 방식을 사용하지는 않음. "컨테이너는 OO개, 볼륨은 XX개로 구성하라"와 같이 어떤 '바람직한 상태'를 YAML 파일에 정의하고, 자동으로 컨테이너를 생성하거나 삭제하면서 이 상태를 만들고 유지하는 것이 쿠버네티스의 기본적인 아이디어
- 쿠버네티스의 기능은 어디까지나 '자동으로 상태를 유지하는' 것으로, 컨테이너를 삭제하고 싶다면 삭제 명령어를 입력하는 것이 아니라 파일에서 '바람직한 상태'를 수정해야함!
마스터 노드와 워커 노드
- 마스터 토드
- 전체적인 제어를 담당
- 마스터 노드에서 컨테이너를 실행하지는 않으며, 워커 노드에서 실행되는 컨테이너를 관리하는 역할! 그래서 도커 엔진 같은 컨테이너 엔진도 설치되지 않음!
- 워커 노드
클러스터
- 마스터 노드와 워커 노드로 구성된 일군의 쿠버네티스 시스템
- 클러스터는 사람이 개입하지 않아도 마스터 노드에 설정된 내용에 따라 워커 노드가 관리되며 자율적으로 동작
쿠버네티스의 구성과 관련된 용어(파드, 서비스, 디플로이먼트, 레프리카세트)
- 파드(pod)
- 쿠버네티스에서 컨테이너는 '파드'라는 단위로 관리됨
- 컨테이너와 볼륨을 함께 묶은 것으로, 기본적으로 파드 하나가 컨테이너 하나이지만 컨테이너가 여러 개인 파드도 있을 수 있음
- 파드에 포함되는 볼륨은 기본적으로 함께 파드에 포함되는 컨테이너가 정보를 공유하기 위해 사용하는 것으로, 파드에 볼륨이 없는 경우도 많음
- 서비스 (service)
- 파드를 여러 개 모은 것이 서비스
- 여러 개의 파드를 이끄는 방장같은 것
- 서비스는 여러 개의 파드를 이끄는 반장이므로 여러 개의 워커 노드(물리적 서버)에 걸쳐 동작하더라도 이들을 모두 관리함
- 서비스가 분해하는 통신은 한 워커 노드 안으로 국한됨. 여러 워커 노드 간의 분배는 실제 '로드밸런서' 또는 '인그래스'가 담당함
- 레플리카세트(ReplicaSet)
- 파드의 수를 관리하는 반장
- 장애 등의 이유로 피드가 종료되었을 때, 모자라는 파드를 보충하거나 정의 파일에 정의된 파드의 수가 감소하면 그만큼 하드의 수를 실제로 감소시킴
- 레플리카세트가 관리하는 동일한 구성의 파드를 '레플리카(replica)'라고 부름
- 파드의 수를 조정하는 것 = 레플리카의 수를 조정
- 파드의 수를 결정하는 것 = 레플리카의 수를 결정
- 레플리카세트는 'deployment'와 함게 쓰일때가 많음
- 디플로이먼트 (deployment)
- 파드의 디플로이먼트(배포)를 관리하는 요소
- 파드가 사용하는 이미지 등 파드에 대한 정보를 갖고 있음
- 레플리카세트가 반장이라면, 디플로이먼트는 반장보다 위에 있는 상사임
쿠버네티스 종류
- 쿠버네티스는 '클라우드 네이티브 컴퓨팅 재단(Cloud Native Computing Foundation, CNCF)라는 단체에서 제정한 표준
- 쿠버네티스는 본래 구글에서 개발됐지만 구글 등의 회사가 CNCF를 조직하고 이 재단에 쿠버네티스를 기부해 개발이 오픈소스로 전환되면서 급속하게 보금됨
메니페스트 파일(정의 파일)
- 쿠버네티스는 매니페스트 파일(정의파일)에 기재된 내용에 따라 파드를 생성
- 메니페스트 파일의 내용을 쿠버네티스에 업로드하면 그 내용이 데이터베이스(etcd)에 '바람직한 상태'로 등록되며, 서버 환경을 이 바람직한 상태로 유지
- 도커는 컨테이너 기반의 오픈소스 가상화 플랫폼
- 다양한 프로그램, 실행환경을 컨테이너로 추상화하고 동일한 인터페이스를 제공하여 프로그램의 배포 및 관리를 단순하게 해줍니다.
- 백엔드 프로그램, 데이터베이스 서버, 메시지 큐등 어떤 프로그램도 컨테이너로 추상화할 수 있음
- 조립PC, AWS, Azure, Google cloud등 어디에서든 실행할 수 있음
Q1. Docker를 사용하는 이유는?
- 새로운 컨터이너를 만드는데 걸리는 시간은 겨우 1-2초(체감 0.001초)로 가상머신과 비교도 할 수 없이 빠름
- 컨테이너, 오버레이 네트워크overlay network, 유니온 파일 시스템union file systems등 이미 존재하는 기술을 도커처럼 잘 조합하고 사용하기 쉽게 만든 것은 없었고 사용자들이 원하는 기능을 간단하지만 획기적인 아이디어로 구현하였습니다.
Q2. Docker image와 container란?
Container
- 컨테이너는 격리된 공간에서 프로세스가 동작하는 기술
- 가상화 기술의 하나지만 기존방식과는 차이가 있음
- 하나의 서버에 여러개의 컨테이너를 실행하면 서로 영향을 미치지 않고 독립적으로 실행되어 마치 가벼운 VMVirtual Machine을 사용하는 느낌을 줌
- "다양한 OS에 여러 application이 올려져 있는 것"을 의미하는 거고 그런 컨테이너를 도커 위에 올리는구나
Image
- 이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있는 것으로 상태값을 가지지 않고 변하지 않습니다(Immutable).
- 컨테이너는 이미지를 실행한 상태라고 볼 수 있고 추가되거나 변하는 값은 컨테이너에 저장됩니다.
- 같은 이미지에서 여러개의 컨테이너를 생성할 수 있고 컨테이너의 상태가 바뀌거나 컨테이너가 삭제되더라도 이미지는 변하지 않고 그대로 남아있습니다.
docker & docker-compose 설치
brew install cask docker
brew install cask docker-compose
docker & docker-compose 설치확인
shinysilver@jeong-eungyeong-ui-MacBookPro ~ % docker -v
Docker version 24.0.7, build afdd53b4e3
shinysilver@jeong-eungyeong-ui-MacBookPro ~ % docker-compose -v
Docker Compose version 2.23.0
shinysilver@jeong-eungyeong-ui-MacBookPro ~ %
Reference
Reference