[Docker] 이미지와 컨테이너(이미지 메타 데이터부터 컨테이너의 생명주기까지..)

yoonthegarden·2024년 4월 19일
1

Docker

목록 보기
3/9

Part2. 이미지와 컨테이너

이미지는 컨테이너를 만드는 재료이다. 이미지가 정확하게 무엇인지, 이미지와 컨테이너의 관계가 어떻게 되는지에 알아보자. 추가로 컨테이너의 라이프 사이클(실행부터 삭제)까지 알아보자.

이미지

서버에서 프로그램 실행

서버에서 프로그램을 실행하기 위한 과정에선 우선 하드웨어가 필요하고, 하드웨어에서 실행할 소프트웨어가 필요하다. 소프트웨어는 Nginx 웹서버처럼 소프트웨어를 다운받아 실행할수도, 직접 개발한 애플리케이션을 실행할수도 있다.
but 이러한 소프트웨어는 소프트웨어 하나만 가지고 실행할 수 없다. 소프트웨어가 하드웨어의 자원을 사용할 수 있도록 필수 기능을 제공해주는 OS가 필요하다. 일반적으로 소프트웨어는 특정 패키지나 라이브러리의 의존성을 가지고 있으며, 실행시키기 위해 런타임 언어를 설치해야하기도 한다. (우리의 예시로는 OS에 자바 소프트웨어를 실행하기 위한 자바 런타임이 설치되어야 한다.)

프로그램 실행을 위해선

  1. 기본 OS
  2. 필요한 구성 요소(Config)
  3. 실행시킬 프로그램

하지만 docker에서 Nginx 웹서버를 컨테이너로 실행 하기 위해서는 소프트웨어에 필요한 의존 요소를 설치하는 과정이 없이 Nginx라는 이미지 이름만 지정한다. 그렇다면 어떻게 서버를 구성하는 과정이 없이 Nginx를 실행시킬 수 있었을까?
→ Nginx 이미지를 통해 컨테이너를 실행했기 때문이다.

이미지(Image)란?

파일 시스템에 특정 시점을 저장해 놓은 압축 파일을 말한다. (like 중간 저장)

이미지는 제작 단계에서부터 소프트웨어뿐만 아니라 소프트웨어가 실행되기 위해 필요한 모든 요소들을 미리 준비해서 압축한다.
Nginx 이미지의 경우는 Nginx 개발사가 OS 위에 Nginx와 의존성 요소들을 미리 준비하고 Nginx를 실행할 준비가 되어 있는 상태 자체를 이미지로 저장한 뒤에 공유한다.
이렇게 이 이미지 안에는 OS와 구성요소, 프로그램이 포함되어 있다. 따라서 우리가 docker run 에 Nginx 이미지를 입력하면 이미지를 다운 받아 격리된 공간에 컨테이너가 실행될 수 있었던 것이다.
컨테이너를 실행할 때 이미지 안에 있던 Nginx 프로그램들이 같이 실행된 것이다.

즉, 이미지는 백업 기능과 비슷하다. 컴퓨터에 윈도우 OS와 프로그램을 설치하고 그 상태를 백업으로 저장해 놓으면 언제든지 해당 프로그램을 실행할 수 있는 시점으로 만들 수 있기 때문이다. 또한, 이러한 백업 파일을 다른 컴퓨터에도 공유할 수 있기 때문이다.
비슷하게 가상 머신에서는 스냅샷이라는 기능을 제공한다. 하지만 컨테이너의 이미지는 백업이나 스냅샷보다 압축파일의 사이즈가 아주 작다. 따라서 인터넷을 통해 공유, 저장하기가 훨씬 쉽다.

이미지는 컨테이너를 사용하는데 있어 가장 중요한 기능 중 하나이며, 이미지는 Nginx 처럼 다른 사람이 만든 이미지를 다운받을 수도, 직접 제작할 수도 있다.

이미지를 다운받고 공유하는 공간인 레지스트리와 이미지가 구성되는 원리와 직접 만들어 보는 건 추후에 강의에서 진행한다하니 추후 벨로그로 돌아오겠다....

도커는 가상 환경의 서버를 운영하는 기술이며, 컨테이너 내에서 웹서버, 웹 애플리케이션 같은 소프트웨어를 운영하는 것이 도커의 사용 목적이다. 컨테이너는 이미지를 통해 실행할 수 있으며, 이미지는 특정 소프트웨어를 실행하기 위해 OS, 의존 요소, 소프트웨어가 포함되어 있는 파일 시스템의 상태를 저장해 놓은 압축 파일이다.

이미지를 컨테이너로 실행시키면 호스트 OS 안에서 완전히 격리된 공간인 컨테이너가 만들어지며, 이 안에서 소프트웨어가 실행된다. 이런 이미지는 다른 사람이 만든 것을 다운받아 사용할 수도, 직접 만들어 사용할 수도 있다.



이미지와 컨테이너

이미지와 컨테이너의 관계를 알아보자.

프로그램과 프로세스의 차이

노트북에 크롬을 깔면 C드라이브 특정 경로에 설치된다. 이는 프로그램이 파일 시스템의 공간을 차지하도록 설치한 것이다. 프로그램인 상태에서는 CPU나 메모리 같은 컴퓨터의 리소스를 사용하지 않고 오직 스토리지의 디스크 공간만 차지한다.
설치된 파일 형태의 프로그램을 실행하면 프로세스가 된다. 크롬 창을 여러 창 띄울 수 있으며, 많이 띄우게 되면 컴퓨터가 느려진다. 이는 각각의 크롬 프로세스들이 CPU와 메모리를 사용하고 있기 때문이다.
따라서 프로그램은 디스크에 저장되어서 실행 가능한 상태인 파일이며, 프로세스는 프로그램을 실행해서 실행 중인 상태를 말한다.

이미지와 컨테이너프로그램과 프로세스의 관계와 같다.

즉, 이미지는 프로그램이 실행되기 위한 환경이 모두 포함되어 있는 파일 시스템이며, 컨테이너는 이미지를 실행한 것이다.

컨테이너를 실행시키기 위해서는 해당하는 이미지를 가지고 있어야 하며, 이미지는 압축 파일의 형태로 호스트 머신의 특정 경로에 위치한다.
하나의 이미지로 여러 개의 컨테이너를 실행할 수 있으며, 동일한 이미지에서 실행한 컨테이너는 내부에서 모두 동일한 프로세스로 실행된다.
이미지인 상태에서는 디스크 공간만 차지하며, 이미지 컨테이너를 실행하는 순간부터 CPU와 메모리를 사용하게 된다.

이미지와 일반적인 프로세스와의 차이

→ 컨테이너는 가상화 기술이기 떄문에 이미지를 컨테이너로 실행할 때는 격리된 공간이 만들어 진다. (이 격리된 공간에서 이미지에서 사전에 지정해 높은 프로그램이 실행된다. )

따라서 이미지를 컨테이너로 실행시키는 것은 이미지에 저장되어 있는 모든 요소들을 격리된 공간으로 만든 다음에 격리된 공간 안에서 프로그램을 프로세스로 실행시키는 단계를 거치는 것이다.

이미지의 메타데이터

메타 데이터는 데이터에 대한 데이터를 말한다. 이미지가 실제 압축된 데이터라면, 메타데이터는 이 이미지에 대한 정보를 기술하는 데이터이다. (식물의 이름부터, 물 주는 횟수, 온도 등.. 다양한 정보를 정리해둔 라벨이 이에 해당된다고 생각하면 좋다.)

하나의 이미지는 실제로 압축된 파일과 이 파일의 정보가 저장되어 있는 메타데이터로 구성되어 있다.

메타 데이터에 어떤 정보들이 있을까?

위 사진은 Nginx의 메타데이터를 표시했다. 이 메타데이터는 이미지의 아이디, 이름, 파일 사이즈와 같은 정보들이 들어있다.

여기서 중요한 것은 Env와 Cmd 필드이다.

Env는 애플리케이션이 사용하는 환경 설정의 값을 말한다. 키와 값으로 이뤄졌으며 =의 기준으로 왼쪽이 키 오른쪽이 값에 해당한다. Nginx 이미지에는 위처럼 소프트웨어 버전과 Nginx 프로그램을 실행할 때 필요한 파일의 경로 같은 정보가 Env에 작성되어 있다. 실제 이 값들이 변경되면 Nginx도 다른 방식으로 동작할 수 있다.

즉, Env 는 소프트웨어가 실행할 때 사용할 정보가 들어있다고 생각하면 된다.

Cmd는 이미지를 컨테이너로 실행할 때 명령어를 지정할 수 있다. 예를 들면 윈도우에서 프로그램을 실행할 때 바탕화면에서 클릭을 하듯 리눅스에서는 일반적으로 명령어를 통해 프로그램을 실행한다. 이미지를 컨테이너로 실행할 때 Cmd에 있는 명령어를 통해서 어떤 프로그램을 실행할지를 메타 데이터에서 결정한다.

여기서 지정한 Nginx 이미지의 이미지 압축파일과 이미지 메타데이터를 사용해서 격리된 공간인 컨테이너가 만들어진다. 이 시점에서 컨테이너에 있는 파일 시스템과 메타 데이터는 새로 격리되어 있는 공간이다. 이 이미지가 컨테이너로 실행될 때 Cmd 필드에 있는 nginx -g deamon off라는 명령어가 실행된다.

이 Nginx 같은 프로세스가 실행되면서 Env 필드에 있는 환경설정 값을 사용할 수 있다. 그리고 이 메타데이터는 컨테이너를 실행할 때 새로운 값으로 덮어쓰기 할 수도 있다.

(ex. 실제 실행시 cmd 필드를 덮어쓰기해서 다른 프로세스를 실행할 수도 있다.)



이미지, 컨테이너 메타데이터 관련 명령어

이미지의 세부 정보 조회

docker image inspect 이미지명

해당 명령어를 작성하면 Nginx의 이미지의 ID를 확인할 수 있고, 이미지를 다운 받을 때 사용하는 태그, 생성 시간..부터 "Config"에선 Env와 Cmd 필드까지 확인할 수 있다.

(Env에선 Nginx 버전과 패스 환경변수를 확인할 수 있으며, Cmd에선 nginx -g deamon off라는 명령어가 있다. 이 Cmd는 띄어쓰기 인식이 안돼서 띄어쓰기를 기준으로 배열로 저장되어있다. 배열을 합치면 저 위의 명령어가 된다.)

컨테이너의 세부 정보 조회

docker container inspect 컨테이너명

컨테이너 실행 시 메타데이터의 cmd 덮어쓰기

docker run 이미지명 (실행명령)

컨테이너 실행 시 메타 데이터의 env 덮어쓰기

docker run --env KEY=VALUE 이미지명 

이렇게 명령어들을 통해 이미지를 컨테이너로 실행하면서 이미지의 메타데이터에 있는 Cmd와 Env 필드를 덮어쓰기 할 수 있다.
이미지로 컨테이너를 실행시키면 이미지에 있는 Cmd, Env들을 그대로 복사해서 컨테이너로 가져온다.



변경 예시

docker run --name customCmd nginx cat usr/share/nginx/html/index.html 를 실행하면 기본 이미지의 메타데이터를 사용해 컨테이너를 실행할 수 있다.

실제로 위 명령어를 실행할 경우 index.html이 cat(출력)된다.

이 customCmd 컨테이너에서 실행한 cat 명령어는 파일의 내용을 출력하고 종료하는 일회성 프로세스이기 때문에 Cmd에서 지정한 cat 명령어가 종료되는 순간 컨테이너도 함께 종료된다. 따라서 CustomCmd는 종료된 상태의 컨테이너이기 때문에 일반적인 docker ps로는 조회가 되지 않는다.

docker ps -a 를 통해 종료된 컨테이너까지 확인할 수 있다.

exited 된 이 컨테이너는 이미지의 데이터를 복사해서 만들어지기 때문에 실제로 컨테이너의 메타데이터를 바꾼다고 해서 이미지의 메타데이터가 바뀌지는 않는다. (즉, custoCmd의 메타 데이터를 바꾼다해서 기존의 nginx 이미지가 바뀌진 않는다는 소리이다. docker image inspect nginx 로 확인 가능)

→ 즉, 우리가 변경할 수 있는 것은 이미지를 복사해오면서 실행하는 시점에서 컨테이너의 메타 데이터만 변경할 수 있다.

이미지는 실제 압축파일과 메타데이터로 구성되어 있다. 이미지를 컨테이너로 실행하면 이미지의 파일과 메타데이터가 컨테이너로 만들어지면서 메타데이터의 Env에 정의되어 있는 환경 변수가 사용된다. 또한, Cmd에 정의되어 있는 명령어로 프로그램을 실행한다.

또한, Env와 Cmd는 컨테이너를 실행할 때 덮어쓰기가 가능하기 때문에 이 내용을 수정해서 같은 이미지에서 다른 결과를 확인할 수도 있다.

이렇게 실행 시 메타데이터를 변경하는 것이 일반적인 방법은 아니다. 보통 이미지를 디버깅할 때 많이 사용되는 방법이다. 하지만 직접 메타데이터를 수정하면서 메타 데이터의 개념을 익히는 것도 좋은 방법이다.



컨테이너의 라이프사이클

컨테이너는 이미지에서부터 시작한다. 이미지는 애플리케이션을 실행할 수 있는 모든 환경이 준비되어 있는 압축 파일이다.

컨테이너가 맨 처음으로 가질 수 있는 상태는 Created, 생성 단계이다. 이 단계는 컨테이너를 실행하기 위한 격리된 공간이 만들어지는 상태이다. 그래서 네트워크나 스토리지, 환경 변수와 같은 모든 리소스가 격리된 공간인 컨테이너로 분리된 상태이다. 또한, 생성 단계에서는 내부에서 프로세스를 실제로 실행하지 않기 때문에 호스트 OS의 CPU나 메모리를 사용하지 않는다.

생성 단계에서 start 명령을 한다면 Running, 실행 단계로 가게된다. 실행 상태가 되었다는 것은 컨테이너 내에서 정상적으로 프로세스가 진행 중이라는 것을 의미한다. 그리고 프로세스가 실제로 CPU와 메모리를 사용한다.

실제 run 명령어는 create와 start가 합쳐진 명령어이다. 그래서 docker run 명령을 사용하면 컨테이너를 만드는 것과 동시에 바로 실행할 수 있다.

또한, 실행 상태에서 restart를 하면 재시작 할 수 있고, 일시정지를 하거나 종료를 할 수도 있다. 실행 중인 프로세스에 종료나 재시작 신호를 보내면 10초 뒤에 이 신호가 동작하게 된다.

일시정지 (Paused) 상태에서는 컨테이너에서 실행 중인 모든 프로세스가 일시 중지된 상태이며, 현재의 상태를 모두 메모리에 저장해 둔다. 따라서 일시정지 상태에서는 CPU는 사용하지 않고 메모리만 사용하게 된다. 그리고 이 상태에서 unpause 명령어를 사용하면 프로세스를 일시정지했던 시점부터 재시작 할 수 있다.

Stopped 상태는 컨테이너에서 실행 중인 프로세스를 완전히 중단시켰다는 것을 의미한다. 이 상태에서는 메모리와 CPU 사용이 모두 중단되고, 종료된 컨테이너를 다시 시작하면 컨테이너의 프로세스가 처음부터 다시 실행된다.

그리고 이 컨테이너는 모든 상태에서 rm 명령을 사용해서 삭제할 수 있다. (실행 중인 컨테이너를 삭제하려면 -f 옵션을 사용해야한다!)

컨테이너의 라이프 사이클은 크게 생성, 실행, 정지, 종료, 삭제로 나눠지며, 대부분은 이 컨테이너에서 실행되는 프로세스의 상태와 일치한다. 이처럼 실제로 컨테이너와 프로세스는 많은 연관성을 가지고 있다.(프로세스가 실행되면 컨테이너가 실행되, 프로세스가 멈추거나 종료되면 컨테이너도 동일하다.) 즉, 프로세스를 잘 설계하고 다루는 것이 컨테이너를 잘 사용하는 것과 방향성이 일치하다.





레퍼런스

  • [2024 NEW] 개발자를 위한 쉬운 도커
profile
https://garden-ying.tistory.com/

7개의 댓글

comment-user-thumbnail
2024년 4월 19일

우와... 도도도돋독스터디 저도 들어가고 싶었는데 후헹. ㅜ 정원님 블로그 정독하면서 혼자 도커스터디할게요.

답글 달기
comment-user-thumbnail
2024년 4월 19일

잘 보고 갑니다 ~

답글 달기
comment-user-thumbnail
2024년 4월 19일

좋은 글 잘보구갑니다~
다음에는 뭘지 기대중입니다!

답글 달기
comment-user-thumbnail
2024년 4월 19일

좋은 글 잘보구갑니다~
다음에는 뭘지 기대중입니다!

답글 달기
comment-user-thumbnail
2024년 4월 19일

이미지와 컨테이너는 들어보기만 했는데 프로그램과 프로세스의 관계로 설명해주시니까 너무 이해가 잘되네요 ~!!~~!

답글 달기
comment-user-thumbnail
2024년 4월 19일

이미지-컨테이너 / 프로그램-프로세스 좋은 비유인거 같네요 ㅎㅎ 저도 잘 인용하겠습니다 ㅎㅎ

답글 달기
comment-user-thumbnail
2024년 4월 20일

야무지게 정리하셨네요 굿 !!

답글 달기