Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Container (컨테이너) #149

Open
JoisFe opened this issue Apr 20, 2023 Discussed in #21 · 0 comments
Open

Container (컨테이너) #149

JoisFe opened this issue Apr 20, 2023 Discussed in #21 · 0 comments
Assignees
Labels
Docker Docker 관련 라벨입니다.

Comments

@JoisFe
Copy link
Member

JoisFe commented Apr 20, 2023

Discussed in https://github.com/orgs/cs-collections/discussions/21

Originally posted by JoisFe December 31, 2022

Container (컨테이너)

컨테이너 실행하기

$docker container run diamol/ch02-hello-diamol
image
  • docker container run : 컨테이너로 애플리케이션을 실행하라는 도커 명령어
  • diamol/ch02-hello-diamol : 해당 애플리케이션은 미리 도커로 실행하도록 패키징돼 누구나 내려받을 수 있도록 공유된 것 --> 이 컨테이너 패키지를 도커에서는 이미지 라고 부름

위의 명령어는 이미지를 이용해 컨테이너를 실행하는 도커 명령어 이다.

실행 결과

  • Unable to find image 'diamol/ch02-hello-diamol:latest' locally : 이미지를 이용해 컨테이너를 실행하려면 이미지가 존재해야 하는데 명령어를 실행하는 시점에 이미지를 가지고 있지 않았기 때문에 해당 메시지가 출력
  • latest: Pulling from diamol/ch02-hello-diamol : 도커가 해당 이미지를 내려받는(도커에서 이미지를 내려받는 것을 pull 이라 함)

이미지를 사용해 컨테이너를 실행 -> 해당 이미지에 실린 애플리케이션은 간단한 스크립트로 Hello from Chapter 2! 라는 메시지와 함께 컨테이너가 실행 중인 환경 출력

다시 똑같은 명령어를 실행해보자

image

이번에는 Unable to find image 'diamol/ch02-hello-diamol:latest' locally 같은 명령어는 발견되지 않는다.
당연히 이전에 이미지를 pull 해왔기 때문에 해당 메시지는 나오지 않는다.

같은 컴퓨터에서 같은 명령어를 입력했지만

  1. 다른 컴퓨터 이름이 나옴
  2. 다른 IP 주소가 나옴
  • 컴퓨터 이름은 컨테이너를 실행할 때마다 매번 바뀜
  • IP 주소 역시 매번 바뀔 확률이 높음

이러한 이유가 일어나는 이유는 ???

앞으로 알아나게 될 것임.

컨테이너란?

컨테이너 :

도커에서 컨테이너는 물건을 담는 컨테이너와 다를 것이 없음I

image
  • 호스트 명, IP 주소, 파일 시스템까지 읻르은 모두 도커가 만들어낸 가상 리소스
  • 이들이 서로 엮여 애플리케이션이 동작할 수 있는 환경이 만들어짐
  • 상자 안은 상자 밖의 환경을 볼 수 없음
  • 그러나 해당 상자는 어떤 컴퓨터상에서 동작하는 것이고, 이 컴퓨터는 이 상자 말고도 다른 상자를 여러 개 실행 가능
  • 도커가 관리하는 이들 상자는 서로 독립적인 환경을 갖지만 상자가 실행되는 컴퓨터의 CPU와 메모리, OS를 공유

컨테이너의 구조

image

위의 구조도가 중요한 이유 --> 격리(isolation)과 밀집 (density)라는 모순돼 보이는 조건을 동시에 만족할 수 있기에

  • 밀집 : 컴퓨터에 CPU와 메모리가 허용하는 한 되도록 많은 수의 애플리케이션을 실행하는 것을 의미

제약 사항

  1. 자바나 닷넷 등 필요로 하는 런타임의 버전이 서로 다를 수도
  2. 서로 호환되지 않는 버전의 라이브러리를 사용하는 경우
  3. 어느 한 애플리케이션이 과다한 리소스를 필요해 다른 애플리케이션의 리소스가 부족해지는 경우

해결책

  • 애플리케이션은 서로 독립된 환경에서 실행되야 함

또 다른 문제점

  • 그럴 경우 한 컴퓨터에서 여러 애플리케이션을 실행할 수 없게 됨. --> 밀집을 달성할 수 없음

위의 모순된 조건을 동시에 달성하는 방법

  1. 가상 머신을 사용 하는 것

가상 머신

  • 애플리케이션이 실행될 독립적인 환경이 생긴다는 점에서 컨테이너와 큰 차이가 없음
  • 다만 가상 머신은 컨테이너와 달리 호스트 컴퓨터의 운영체제를 공유하지 않고 별도의 운영체제를 필요로 함

가상 머신의 구조

image

컨테이너 VS 가상 머신

두 구조는 크게 차이가 없어보이나 작은 차이가 의미하는 차이는 매우 큼.

  • 각각의 가상 머신은 자신만의 운영체제를 별도로 가짐
  • 이 운영체제는 애플리케이션이 사용해야 할 CPU와 메모리 자원을 상당량 차지
  • 운영체제의 라이선스 비용과 운영체제 업데이트 설치 부담이 추가로 발생

결국 가상 머신은 격리를 달성할 수 있지만 밀집을 제공하지 못함

해결책

컨테이너는 가상 머신의 단점을 해결 가능!!

  1. 컨테이너를 사용
  • 각각의 컨테이너는 호스트 컴퓨터의 운영체제를 공유하므로 필요한 리소스가 크게 경감
  • 그만큼 실행도 빠르고 같은 호스트 컴퓨터에서 가상 머신에 비해 더 많은 수 (일반적으로 약 다섯 배)의 애플리케이션을 실행 가능
  • 컨테이너 역시 외부와 독립된 환경을 제공하므로 밀집과 격리가 동시에 달성

컨테이너는 밀집, 격리 두가지 모두 달성할 수 있음!!

컨테이너를 원격 컴퓨터처럼 사용하기

한 스크립트 안에서 여러 도구를 사용해 필요한 일을 처리하는 경우를 생각해보면

  • 대부분 특정한 도구가 필요하므로 스크립트 외에 이들 도구를 함께 공유해야 함
  • 도구를 설치하고 사용하는 방법을 담은 문서도 전달해야함
  • 이들 도구를 전달받아 설치하는 데 또 시간이 필요

매우 불편하기 짝이 없다...

위 불편함을 도커를 이용하면 매우 편안해짐

  • 도구와 스크립트를 하나의 이미지로 패키징해 추가적인 설치나 설정 작업 없이 컨테이너로 스크립트를 바로 실행할 수 있음

컨테이너를 실행하고 실행된 컨테이너에 마치 원격 컴퓨터에 접속하듯 터미널을 통해 접근해보기

  • 이전과는 다른 방식으로 컨테이너를 활용해보자
  • 이번에도 docker container run 명령을 사용하지만 터미널 세션으로 조작할 수 있는 대화식 컨테이너를 실행하도록 몇 가지 플래그를 추가
$docker container run --interactive --tty diamol/base
  • --interactive 플래그 : 컨테이너에 접속된 상태가 됨
  • --tty : 터미널 세션을 통해 컨테이너를 조작하겠다는 의미.
image

출력된 메시지를 보면

  1. 이미지를 내려받음 (이미 존재한다면 그대로 땡겨옴)
  2. diamol/base 이미지로부터 대화식 컨테이너를 실행함
  • 위 명령은 윈도우 환경에서도 똑같이 동작
  • 하지만 위 결과와 다르게 윈도 명령 프롬프트가 뜸 (ex C:> )
  1. 어떤 명령 프롬프트가 뜨든 이제 컨테이너 내부에서 해당 운영체제의 명령행 인터페이스를 사용하듯 명령을 실행 가능
image - 위는 hostname과 date 명령을 사용해서 컨테이너 내의 환경을 확인하는 예시임

위 결과를 통해 확인할 수 있는 사실

  • 원격 컴퓨터에 접속한 것과 같은 로컬 터미널 세션이 열려 있다는 점
  • 연결된 컴퓨터가 현재 실행 중인 컨테이너라는 것
    • 보안 쉘 (SSH)를 통해 원격 리눅스 컴퓨터에 연결하거나 원격 데스크톱을 통해 다른 윈도 컴퓨터에 연결했다면 지금 컨테이너에 연결한 것과 같은 결과를 얻음
  • 이전에 설명하였 듯 도커 컨테이너는 호스트 컴퓨터의 OS를 공유함
  • 따라서 호스트 컴퓨터가 리눅스 머신이면 리눅스 쉘이 뜨고, 윈도 머신이면 윈도 명령 프롬프트가 뜨는 것임
  • 도커 자체는 호스트 컴퓨터의 아키텍처나 운영체제와 상관없이 동일하게 동작하지만 컨테이너에 들어 있는 애플리케이션은 OS나 아키텍처를 가릴 수 있는 문제가 있음
  • 결국 컨테이너의 내용물이 무엇이든 컨테이너를 다루는 방법은 환경과 상관없이 동일함

현재 실행 중인 모든 컨테이너에 대한 정보 확인하기

$docker container ls
$docker container ps
$docker ps

위 3가지 명령어 모두 현재 실행 중인 모든 컨테이너에 대한 정보를 확인하는 것임
왜 이렇게 같은 역할을 하는 명령어가 많지??

image

=> #146 참고!

image
image

  • 컨테이너 ID와 컨테이너 내부에서 확인한 호스트명과 동일
  • 도커는 컨테이너를 실행할 때마다 무작위로 생성한 ID 값을 부여
  • 그리고 해당 ID 값 중 일부분이 호스트 명이 됨

컨테이너에서 실행 중인 프로세스의 목록 보기

$ docker container top 35

image

  • 컨테이너 ID 값을 전체를 (355615c3e2b4) 입력하지 않고 앞 두개만 입력해도 괜찮음
  • 컨테이너를 특정할 때 컨테이너 ID의 처음 몇 글자를 지정해도 됨 (만약 처음 몇글자에 해당하는 것이 여러 프로세스가 있다면 모두 출력됨)
  • 컨테이너 ID를 지정하는 여러 명령어에 모두 해당

컨테이너에 수집된 모든 로그 출력

$ docker container logs {container id}

(해당 글 작성하면서 컨테이너를 바꾸었으니 container Id 가 달라졌어도 오해 없으시길!)

  • container Id가 6f~로 한 작업
    image
    image

  • log 확인
    image

  • 도커는 애플리케이션의 표준 출력으로부터 로그 수집

  • 이전에 터미널 세션에서는 입력한 명령과 출력된 내용을 모두 볼 수 있었지만 실제 애플리케이션이 실행된 컨테이너에서는 애플리케이션이 출력하는 로그만 보임 (ex : 특정 컨테이너에서 모든 HTTP 요청마다 로그를 생성하는 웹 애플리케이션 동작 중이면 이 컨테이너는 이들 HTTP 요청에 대한 로그를 출력)

컨테이너의 상세한 정보 보기

$ docker container inspect {container id}
  • docker ID, 컨테이너 생성날짜, 컨테이너의 가상 파일 시스템상의 경로, 컨테이너에서 실행 중인 명령, 해당 컨테이너가 접속된 가상 도커 네트워크 정보 등 애플리케이션에 발생한 문제를 추적하는 데 유용한 정보 제공
  • 이 정보는 JSON 포맷이라 포맷팅 하기에도 편리

위 도커 명령어들의 사용 상황

  • 해당 명령어들 대부분 CPU 사용량 확인 혹은 도커 가상 네트워크 상태를 확인하는 등의 컨테이너를 다루거나 애플리케이션에 일어난 문제를 찾고 해결하기 위해 사용할 명령어

지금까지 명령어들을 통해 본 도커의 장점

  • 컨테이너가 모두 똑같다는 점!
  • 도커를 적용하면 애플리케이션 위에 관리를 위한 계층이 하나 추가
  • 리눅스 컨테이너에서 동작하는 아주 오래된 레거시 자바 애플리케이션이거나 윈도 컨테이너에서 동작하는 닷넷 애플리케이션 이거나 최신의 Go로 작성된 애플리케이션 등 모두 똑같은 방법으로 관리가 가능
  • run 명령으로 애플리케이션 실행, logs 명령으로 로그를 출력, 프로세스 목록을 보려면 top 명령 실행, 컨테이너 상세 정보를 보고싶으면 inspect 명령어를 사용함 --> 모든 애플리케이션은 동일

상태와 상관없이 모든 컨테이너의 목록 보기

docker container ls -all

image

  • 컨테이너를 종료 후 $ docker container ls로 확인해 보면 현재 실행 중인 컨테이너가 없다고 나옴
  • 하지만 '$ docker container ls -all`로 확인 시 상태와 상관없이 모든 컨테이너 목록을 확인할 수 있음
  1. 컨테이너 내부의 애플리케이션이 실행 중이어야 컨테이너의 상태도 실행 중이됨
  • 애플리케이션 프로세스가 종료되면 컨테이너의 상태도 Existed가 됨
  • 종료된 컨테이너는 CPU 자원이나 메모리를 사용하지 않음
  1. 컨테이너가 종료되도 컨테이너는 사라지지 않음
  • 종료된 컨테이너는 사라지지 않고 그대로 남아 있음
  • 따라서 나중에 컨테이너를 다시 실행하거나 로그를 확인하거나 컨테이너 파일 시스템에 새로운 파일을 복사하거나 외부로 복사해 올 수 있음
  • 즉 종료된 컨테이너도 명시적으로 삭제하지 않는다면 그대로 남아 있음
  • 컨테이너의 파일 시스템이 그대로 남아 있는 것이므로 호스트 컴퓨터의 디스크 공간을 계속 점유

컨테이너를 실행하여 백그라운드에서 계속 동작시키기

  • 도커 사용의 주목적이 웹 사이트, 배치 프로세스, DB 같은 서버 애플리케이션 실행임
  • 즉 백그라운드에서 계속 실행시킬 수 있어야 함
  • 웹 사이트를 호스팅하는 예시로 확인해 볼 것임

컨테이너를 사용해 웹 사이트 호스팅

$ docker container run --detach --publish 8088:80 {image name}

image

  • $docker container run --detach --publish 8088:80 diamol/ch02-hello-diamol-web를 실행하니 컨테이너 id만 출력됨
  • 그러고 $ docker container ls를 실행하니 특정 container가 실행되고 있음
  • 즉 해당 컨테이너가 종료되지 않고 백그라운드에서 계속 동작 중

diamol/ch02-hello-diamol-web 이미지

  • 해당 이미지는 아파치 웹 서버와 간단한 HTML 페이지를 담고 있음
  • 해당 이미지로 컨테이너를 실행하면 실제 웹 서버를 통해 웹 페이지가 제공

컨테이너가 백그라운드에서 동작하면서 네트워크를 주시(listen) 하게 하는 방법

  • 두 개의 플래그를 적용해야 함
  1. --detach : 컨테이너를 백그라운드에서 실행하며 컨테이너 ID를 출력
  • 해당 플래그를 적용하여 실행한 컨테이너는 마치 리눅스 데몬 혹은 윈도 서비스처럼 백그라운드로 동작하며 겉으로 보이지 않음
  1. --publish : 컨테이너의 포트를 호스트 컴퓨터에 공개
  • 컨테이너의 포트를 호스트 컴퓨터에 공개하는 원리는 아래와 같음
  • 도커를 설치하면 호스트 컴퓨터의 네트워크 계층에 도커가 끼어듬
  • 그러면 호스트 컴퓨터에서 들고나는 네트워크 트래픽을 모두 도커가 가로채서 그 중 필요한 것을 컨테이너에 전달할 수 있음
  • 컨테이너는 기본적으로 외부 환경에 노출되지 않음
  • 각 컨테이너는 고유의 IP 주소를 가지지만 해당 IP 주소는 도커가 관리하는 내부 가상 네트워크 주소이지 호스트 컴퓨터가 연결된 물리 네트워크에 연결된 것이 아님
  • 컨테이너의 포트를 공개한다는 것은 도커가 호스트 컴퓨터의 포트를 주시하다가 해당 포트로 들어오는 트래픽을 컨테이너로 전달해주는 것

image

  • 위 그림은 호스트 컴퓨터의 물리 네트워크와 컨테이너의 가상 네트워크 관계를 보여줌
  • 호스트 컴퓨터의 8080포트로 들어온 트래픽이 컨테이너의 80 포트로 전달
  • 내 컴퓨터는 도커를 실행하는 호스트 컴퓨터가 되고 IP 주소는 192.168.2.150
  • 이 주소는 내가 사용하는 물리 네트워크의 주소 (나의 집 공유기가 부여)
  • 172.0.5.1 는 컨테이너의 IP 주소로 도커가 부여한 도커 가상 네트워크 주소
  • 호스트 컴퓨터가 연결된 물리 네트워크의 컴퓨터는 컨테이너의 IP 주소에 접근할 수 없음
  • 이 주소는 도커 내부에서만 존재하는 주소이기 때문
  • 하지만 컨테이너의 포트가 공개됐으므로 컨테이너로 트래픽을 전달 가능

웹 페이지에 접근해보기

image

  • http:localhost:8088 페이지에 접근
  • 해당 HTTP 요청은 로컬 컴퓨터에서 보낸 요청
  • HTTP 응답은 컨테이너로 부터 나온 것

도커를 이용한 웹사이트 호스팅으로 알아본 도커의 장점

  • 도커의 이식성과 효율성을 알 수 있음
  • 해당 웹 페이지는 웹 서버와 함께 이미지로 패키징 됨
  • 이미지 외에 별도로 필요한 요소가 없음
  • 웹 개발자는 자신이 작업하는 컴퓨터에서 컨테이너 하나만 실행했을 뿐인데 전체 애플리케이션 스택이 실행 됨 (HTML, 웹서버 등등)
  • 만약 운영 환경에서 여러 물리 서버에 나눠진 100개의 컨테이너를 실행하여 전체 애플리케이션을 실행하는 경우도 마찬가지!

실행 중인 컨테이너 상태 확인

$ docker container stats {container id 혹은 image name 혹은 container name}

image

image

  • 실시간으로 해당 컨테이너의 CPU, 메모리, 네트워크, 디스크 사용량을 볼 수 있음
  • 단 해당 명령은 리눅스와 윈도우 에서 출력 내용이 약간 다름

도커가 컨테이너를 실행하는 원리

  • 빌드 - 공유 - 실행 워크플로우를 적용하면 소프트웨어 배포가 매우 쉬워짐
  • 컨테이너의 이미지를 만들어 공유하면 다른 사람들이 도커에서 이 이미지로 컨테이너를 실행하기만 하면 됨
  • 그렇다면 도커가 컨테이너를 실행하는 원리는?

도커를 구성하는 컴포넌트

image

도커 엔진 (Docker Engine)

  • 도커의 관리 기능을 맡은 컴포넌트
  • 로컬 이미지 캐시를 담당하므로 새로운 이미지가 필요하면 이미지를 내려받고, 기존 이미지가 있다면 전에 내려받은 이미지를 사용
  • 호스트 운영체제와 함께 컨테이너와 가상 네트워크 등 도커 리소스를 만드는 일도 담당
  • 도커 엔진은 항상 동작하는 백그라운드 프로세스 (리눅스 데몬 또는 윈도우 서비스와 같음)
  • 도커 엔진은 도커 API를 통해 맡은 기능을 수행
  • 도커 API는 표준 HTTP 기반 REST API
  • 도커 엔진의 설정을 수정하면 이 API를 네트워크를 경유해 외부 컴퓨터로부터 호출할 수 없도록 차단 (기본 설정) 하거나 허용할 수 있음

도커 명령행 인터페이스 (Docker command-line interface, 도커 CLI)

  • 도커 명령행 인터페이스 (Docker command-line interface, 도커 CLI)는 도커 API의 클라이언트 임
  • docker 명령을 사용할 때 실제로 도커 API를 호출하는 것이 바로 도커 CLI

도커의 설계

  • 도커 엔진과 상호 작용할 수 있는 유일한 방법은 API를 통한 방법 뿐
  • API 접근 허용 범위를 몇가지로 선택 가능
  • 도커 CLI는 API에 요청을 전달하는 역할

도커 CLI가 요청을 전달하는 곳을 변경하기

  • 위 예시를 보면 한 대의 물리 머신에서 컨테이너를 실행하고 관리하기 위한 목적으로 CLI를 사용
  • 원격 컴퓨터에서 실행 중인 도커를 조작할 수 있도록 CLI가 요청을 전달하는 곳을 변경 가능
  • 빌드 환경, 운영 환경, 테스트 환경 등 서로 다른 환경에서 동작하는 컨테이너를 관리하기 위해 이러한 방식을 사용해야 함
  • 도커 API는 운영체제와 상관없이 동일하므로 라즈베리 파이, 클라우드 환경, 리눅스 서버 등 어느 곳에 위치한 도커 엔진이라도 맥 OS가 설치된 컴퓨터에서 이들을 제어 가능

도커 API 클라이언트

  • 도커 API는 명세가 공개되어 있음
  • 따라서 도커 CLI 외의 다른 클라이언트를 사용할 수 있음
  • 이미 그래픽 인터페이스를 통해 시각적으로 컨테이너를 관리할 수 있는 클라이언트가 몇가지 있음
  • API를 통해 컨테이너나 이미지 등 도커가 관리하는 모든 리소스에 대한 정보를 얻을 수 있음 (대시보드도 만들어짐)
  • UCP(Universal Control Plane)
    • 도커에서 만든 상업용 도커 API 클라이언트

containerd

  • CNCF에서 관리하는 오픈 소스 프로젝트
  • 컨테이너는 Open Container Initiative(컨테이너는 개방형 컨테이너 이니셔티브) 라는 이름으로 공개된 개방형 표준임!
  • 도커는 가장 널리 쓰이는 컨테이너 플랫폼임 즉 컨테이너 플랫폼이 도커만 있는 것은 아님
@JoisFe JoisFe added the Docker Docker 관련 라벨입니다. label Apr 20, 2023
@JoisFe JoisFe self-assigned this Apr 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docker Docker 관련 라벨입니다.
Projects
None yet
Development

No branches or pull requests

1 participant