이미지
서버에서 프로그램이 실행되려면 하드웨어가 필요하고, 그 하드웨어에서 실행할 소프트웨어가 필요하다. 소프트웨어는 Nginx 웹서버처럼 소프트웨어를 다운받아서 실행할 수도 있다. 아니면 직접 개발한 애플리케이션을 실행할 수 있다. 그런데 이 소프트웨어는 소프트웨어 하나만 가지고는 실행할 수 없다.
먼저 소프트웨어가 하드웨어의 자원을 사용할 수 있도록 필수 기능을 제공해주는 OS가 필요하다. 그리고 일반적으로 소프트웨어는 특정 패키지나 라이브러리의 의존성을 가지고 있어 실행시키기 위해서 런타임 언어를 설치해야 하는 경우도 있다.
예를 들어서 자바로 개발된 애플리케이션은 OS에 자바 소프트웨어를 실행하기 위한 자바 런타임이 설치되어 있어야 한다.
정리하면 서버에서 프로그램을 실행하기 위해서 소프트웨어적으로 세가지가 필요하다.
먼저 기본 OS와 프로그램이 실행하기 위해서 필요한 구성 요소, 그리고 실행시킬 프로그램이 필요하다.
Nginx 이미지를 컨테이너로 실행하면 소프트웨어에 필요한 의존 요소를 설치하는 과정 없이 실행이 가능하다.
그 이유는 Nginx 이미지를 통해서 컨테이너를 실행했기 때문이다.
이미지는 파일 시스템에 특정 시점을 저장해 놓은 압축 파일이다. 마치 게임을 하다가 중간 저장을 한 것과 같다.
이미지는 제작 단계에서부터 소프트웨어뿐만 아니라 소프트웨어가 실행하기 위해서 필요한 모든 요소들을 미리 준비해서 압축한다.
Nginx 이미지 같은 경우는 Nginx 개발사가 OS 위에 Nginx와 의존성 요소들을 미리 준비하고 Nginx를 실행할 준비가 되어 있는 상태 자체를 이미지로 저장한 뒤에 공유합니다. 이 이미지 안에는 OS와 구성요소, 프로그램이 포함되어 있다.
그래서 도커 run 명령에 nginx라는 이미지 이름을 입력했을 때 이 이미지를 다운받아서 격리된 공간에 컨테이너가 실행된 것이고 컨테이너를 실행할 때 이미지 안에 있던 nginx 프로그램이 함께 실행된 것이다.
도커는 가상 환경의 서버를 운영하는 기술이다.
도커를 사용한다는 것은 컨테이너 내에서 웹서버나 웹 애플리케이션 같은 소프트웨어를 운영하는 것이 목적이다.
컨테이너는 이미지를 통해서 실행할 수 있다. 이미지는 특정 소프트웨어를 실행하기 위해서 OS와 의존 요소, 소프트웨어가 포함되어 있는 파일 시스템의 상태를 저장해 놓은 압축 파일이다.
이 이미지를 컨테이너로 실행시키면 호스트 OS 안에서 완전히 격리된 공간인 컨테이너가 만들어진다.
그리고 이 컨테이너 안에서 소프트웨어가 실행된다.
그리고 이 이미지는 다른 사람이 만든 것을 사용할 수도 있고 직접 이미지를 만들어서 사용할 수도 있다.
이미지와 컨테이너 실행
이미지를 컨테이너로 실행해 보고 실행하는 과정에서 이미지와 컨테이너의 차이에 대해 알아보자
프로그램 vs 프로세스
크롬 설치
- 크롬 애플리케이션이 C드라이브의 특정 경로에 설치됨
- 프로그램이 파일 시스템의 공간을 차지하도록 설치한 거다.
- 프로그램인 상태에서는 CPU나 메모리 같은 컴퓨터의 리소스를 사용하지 않음
- 오직 스토리지의 디스크 공간만 차지한 상태
프로그램 실행
- 파일 형태의 프로그램을 실행 시 프로세스가 된다.
- 이때는 CPU나 메모리 같은 컴퓨터의 리소스를 사용
크롬창 여러 개 실행
- 각각의 크롬 프로세스들이 CPU와 메모리를 사용하고 있기 때문에 여러 개의 크롬 브라우저 사용 시 컴퓨터가 느려진다.
프로그램
디스크에 저장되어서 실행 가능한 상태인 파일
프로세스
프로그램을 실제로 실행해서 실행 중인 상태
프로그램 한 개는 여러 개의 프로세스를 실행할 수 있다
각각의 프로세스는 OS에서 CPU와 메모리를 할당받아서 사용한다.
이미지와 컨테이너 관계도 프로그램과 프로세스의 관계와 동일하게 이해하면 된다.
이미지
프로그램이 실행되기 위한 환경이 모두 포함되어 있는 파일 시스템
이미지는 압축 파일의 형태로 호스트 머신의 특정 경로에 위치한다.
컨테이너
이미지를 실행한 것이 컨테이너다.
컨테이너를 실행시키려면 해당하는 이미지를 가지고 있어야 한다.
하나의 이미지로 여러 개의 컨테이너를 실행할 수 있다.
동일한 이미지에서 실행한 컨테이너는 내부에서 모두 동일한 프로세스로 실행된다.
이미지인 상태에서는 디스크 공간만 차지하고 이미지를 컨테이너로 실행하는 순간부터 CPU와 메모리를 사용하게 된다.
일반적인 프로세스와 차이가 있다면 컨테이너는 가상화 기술이기 때문에 이미지를 컨테이너로 실행할 때는 격리된 공간이 만들어진다는 것이다. 그리고 이 격리된 공간에서 이미지에서 사전에 지정해 놓은 프로그램이 프로세스로 실행된다.
정리하면 이미지를 컨테이너로 실행시키는 것은 이미지에 저장되어 있는 모든 요소들을 격리된 공간으로 만든 다음에 격리된 공간 안에서 프로그램을 프로세스로 실행시키는 단계를 거치는 것이다.
docker image ls
이미지 리스트 조회
docker image ls nginx
nginx 이미지 조회
docker run -d --name {컨테이너 명} 이미지명
-d 옵션: 백그라운드 실행
--name {컨테이너 명}: 컨테이너의 이름 지정
docker ps
실행 중인 컨테이너 리스트 조회
docker rm -f
실행 중인 컨테이너 삭제
rm 으로는 실행 중인 컨테이너 삭제 불가능
-f: 실행 중인 컨테이너 삭제 가능
컨테이너 실행 및 조회
이름이 다른 3개의 컨테이너 실행
- docker run -d --name multinginx1 nginx docker run -d --name multinginx2 nginx docker run -d --name multinginx3 nginx
실행 중인 컨테이너 리스트 조회
- docker ps
다수의 컨테이너 삭제
- docker rm -f multinginx1 multinginx2 multinginx3
혹은 아래처럼 컨테이너 ID 앞 부분에서 일부만 가져와서 쓸 수도 있다.
- docker rm -f 267 fe4 62d
메타데이터
메타데이터는 데이터에 대한 데이터를 의미한다.
이미지가 실제로 압축된 데이터라면, 메타데이터는 이 이미지에 대한 정보를 기술하는 데이터이다.
이 이미지의 이름이 무엇인지, 사이즈가 어떻게 되는지에 대한 정보를 저장하고 관리해야 한다.
이미지 파일 데이터에 대한 데이터, 메타데이터라고 부른다.
하나의 이미지는 실제로 압축된 파일과 이 파일의 정보가 저장되어 있는 메타데이터로 구성되어 있다.
위 사진에 보이는 것처럼 메타데이터에는 많은 정보들이 저장되어 있다.
사진에는 NGINX 이미지의 메타데이터를 표시했다.
이 메타데이터를 보면 이미지의 아이디와 이미지의 이름, 파일 사이즈 같은 정보가 있고 유심히 봐야 할 부분이 env와 cmd 필드이다.
ENV는 애플리케이션이 사용하는 환경 설정 값을 의미한다. ENV는 키와 값으로 이루어져 있다.
ENV는 소프트웨어가 실행할 때 사용할 설정 정보라고 생각하면 된다.
CMD는 이미지를 컨테이너로 실행할 때 프로세스 실행 명령어를 지정할 수 있다.
이미지를 컨테이너로 실행할 때 CMD에 있는 명령어를 통해서 어떤 프로그램을 실행할지를 메타데이터에서 결정한다.
여기서 지정한 Nginx 이미지의 압축 파일과 이미지의 메타데이터를 사용해서 격리된 공간인 컨테이너가 만들어진다.
이 시점에서 이제 컨테이너에 있는 파일 시스템과 메타데이터는 새롭게 격리되어 있는 공간이다.
docker image inspect 이미지명
이미지의 세부 정보 조회
docker container inspect 컨테이너명
컨테이너의 세부 정보 조회
docker run 이미지명 (실행명령)
컨테이너 실행 시 메타데이터의 cmd 덮어쓰기
run 이미지명 옆에 덮어쓰기 할 실행 명령을 입력한다.
docker run --env KEY=VALUE 이미지명
컨테이너 실행 시 메타데이터의 env 덮어쓰기
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
cmd 필드는 띄어쓰기가 인식이 안 되기 때문에 띄어쓰기를 기준으로 위와 같이 배열로 저장이 되어 있다.
이 세 개의 배열 값들을 하나로 합치면 nginx -g daemon off라는 명령어가 완성된다.
컨테이너 실행 및 메타데이터 조회
nginx 이미지의 메타데이터 확인
- docker image inspect nginx
설정 변경사항 없이 컨테이너 실행
- docker run -d --name defaultCmd nginx
실행된 컨테이너의 메타데이터 확인
- docker container inspect defaultCmd
메타데이터 덮어쓰기로 이미지의 파일 출력
docker run 명령의 옵션 확인
- docker run --help
메타데이터를 수정할 cmd 명령을 포함한 컨테이너 실행, cat 명령으로 컨테이너 내 파일 내용 출력
- docker run --name customCmd nginx cat usr/share/nginx/html/index.html
실행된 컨테이너의 메타데이터 확인
- docker container inspect customCmd
docker ps -a 명령으로 종료된 컨테이너 조회
- docker ps -a
docker run -d --name defaultCmd nginx
nginx 이미지의 기본 메타데이터로 컨테이너를 실행한다.
그러면 이미지의 메타데이터에 있는 nginx -g daemon off 명령어가 컨테이너의 메타데이터로 복사된다.
그리고 컨테이너는 nginx 프로세스를 실행했다.
docker run --name customCmd nginx cat usr/share/nginx/html/index.html
nginx 이미지의 메타데이터는 그대로 유지되지만 실행되는 컨테이너의 메타데이터가 덮어쓰기 후 실행된다.
그래서 customCmd 컨테이너는 웹서버가 아니라 파일의 내용을 출력하고 종료된다.
실행된 nginx 컨테이너의 Cmd 부분을 보면 cat usr/share/nginx/html/index.html로 덮어져 있다.
docker run -d 이미지명
-d 옵션: 컨테이너를 백그라운드에서 실행
-d 옵션은 detach의 약자이다.
-d 옵션 추가 시
- 지속적으로 실행되는 소프트웨어(데몬 프로그램)를 실행할 때 적합하다.
-d 옵션 제거 시
- 실행 후 종료되는 프로그램에 적합하다.
- 컨테이너의 출력이 사용자의 커맨드 창과 연결돼서 실시간으로 로그를 확인할 경우에 사용
정리
이미지는 실제 압축파일과 메타데이터로 구성되어 있다.
이미지를 컨테이너로 실행하면 이미지의 파일과 메타데이터가 컨테이너로 만들어지면서 메타데이터의 ENV에 정의되어 있는 환경 변수가 사용된다. 그리고 CMD에 정의되어 있는 명령어로 프로그램을 실행한다.
그리고 이 ENV와 CMD는 실행할 때 덮어쓰기가 가능하기 때문에 이 내용을 수정해서 같은 이미지에서 다른 결과를 확인할 수도 있었다.
첫 번째 실습에서는 CMD를 두 번째 실습에서는 ENV를 덮어쓰게 했다.
실습을 통해 컨테이너를 실행할 때 메타데이터의 내용을 수정할 수 있고 같은 이미지도 전혀 다른 역할을 수행할 수 있는 컨테이너로 만들 수 있다는 걸 알았다.
컨테이너의 라이프사이클
컨테이너가 가질 수 있는 여러 가지 상태를 실습을 통해서 확인해 보고 컨테이너의 라이프사이클을 학습해 보자.
컨테이너는 이미지에서부터 시작한다.
이미지는 애플리케이션을 실행할 수 있는 모든 환경이 준비되어 있는 압축 파일이다.
첫 번째로 컨테이너가 가질 수 있는 상태는 Created 생성 단계이다.
이 생성 단계에서는 컨테이너를 실행하기 위한 격리된 공간이 만들어지는 상태이다. 하지만 생성 단계에서는 내부에서 프로세스를 실제로 실행하지 않기 때문에 호스트 OS의 CPU와 메모리를 사용하지 않는다.
이 생성 단계에서 docker start 명령을 사용하면 컨테이너의 메타데이터의 cmd 값을 사용해서 컨테이너를 러닝 상태로 만들 수 있다. 그래서 네트워크나 스토리지, 환경 변수 같은 모든 리소스가 격리된 공간인 컨테이너로 분리된 상태이다. docker create 명령을 사용하면 이미지를 컨테이너로 만들 수 있다.
두 번째로 실행 단계이다.
이 실행 상태가 되었다는 것은 컨테이너 내에서 정상적으로 프로세스가 실행 중이라는 것을 의미한다. 그리고 이 프로세스가 실제로 CPU와 메모리를 사용한다. 그래서 docker run 명령을 사용하면 컨테이너를 만드는 것과 동시에 바로 실행할 수 있다. 실행 중인 프로세스에 종료나 재시작 신호를 보내면 10초 뒤에 이 신호가 동작하게 된다. 그래서 리스타트 명령을 보내면 10초 뒤에 프로세스가 재시작하게 된다. 그리고 이 실행 상태에서 docker restart 명령을 하면 프로세스를 재시작시킬 수 있다. 지금까지 실습에 사용했던 docker run 명령은 docker create와 docker start가 하나로 합쳐진 명령이다. 생성 단계에서 docker start 명령을 사용하면 컨테이너의 메타데이터의 cmd 값을 사용해서 컨테이너를 러닝 상태로 만들 수 있다.
세 번째로 정지단계이다.
paused 상태에서는 컨테이너에서 실행 중인 모든 프로세스가 일시 중지된 상태이다. 일시 중지한다는 것은 현재의 상태를 모두 메모리에 저장해 두는 것이다. 그리고 이 상태에서 unpause 명령을 사용하면 프로세스를 일시정지했던 시점부터 재시작할 수 있습니다. 그래서 일시 정지 상태에서는 CPU는 사용하지 않고 메모리만 사용하게 됩니다. 컨테이너에서 실행 중인 프로세스를 일시 정지하거나 종료할 수도 있다.
네 번째로 종료 단계이다.
이 상태에서는 메모리와 CPU 사용이 모두 중단된다. 종료된 컨테이너를 다시 시작하면 컨테이너의 프로세스가 처음부터 다시 실행된다. stopped 상태는 컨테이너에서 실행 중인 프로세스를 완전히 중단시켰다는 것을 의미한다.
그리고 컨테이너는 모든 상태에서 rm 명령을 사용해서 삭제할 수 있다.
다만 실행 중인 컨테이너를 삭제하려면 -f 옵션을 사용해야 한다.
정리하면 컨테이너의 라이프사이클은 크게 생성, 실행, 정지, 종료, 삭제로 나뉜다.
대부분은 이 컨테이너에서 실행되는 프로세스의 상태와 일치한다.
참고
인프런의 개발자를 위한 쉬운 도커 강의를 보고 정리한 글입니다.
'Docker' 카테고리의 다른 글
7. 도커 볼륨 (0) | 2024.08.16 |
---|---|
6. 네트워크 (0) | 2024.08.15 |
5. 컨테이너 애플리케이션 구성 (0) | 2024.08.15 |
4. 이미지 빌드 (0) | 2024.08.14 |
3. 이미지 레지스트리 (0) | 2024.06.29 |