SOPT 34기 서버파트/Docker 스터디

[Docker] 이미지 레이어구조와 커밋

softmoca__ 2024. 4. 28. 12:21
목차

- 이미지를 효율적으로 저장하는 레이어드 구조

- 이미지가 저장되는 두가지 원리 중 하나인 커밋

 

 

이미지와 레이어(Layer)

이미지컨테이너를 실행하기 위한 읽기 전용 파일이다.

커 이미지는 저장소를 효율적으로 사용하기 위해서 레이어드 파일 시스템으로 구성되어 있다.

 

NGINX를 실행 했을 때 이미지를 다운 받는 과정에서 여러단계에 걸쳐서 Pull이 실행되고 있다.

여기서의 한줄이 하나의 레이어를 의미하고 이 레이어들이 모여서 하나의 이미지로 구성된다.

 

천축 설계도면을 예시로 한 이해

이미지의 레이어 구조는 재활용에 유리

설계도 A에서 조경 부분을 수정해야 한다고 생각할 때 설계도 A가 한장의 도면으로 되어있다면 전체도면에 영향을 받게 된다.

하지만 레이어 구조로 되어 있으면 조경 부분만 수정하면 나머지 전기, 토목,구조는 변경의 영향을 받지 않게 된다.

 

효율적인 데이터 저장과 전송

설계도 A와 구조,토목, 조경 부분이 동일하고 전기 배선만 다른 건물 B가 있을 경우.

레이어드 구조가 아니였다면 설계도 ,A,B를 통째로 관리해야 한다.

하지만 레이어 구조를 활용하면 겹치는 레이어를 재사용할 수 있다.

 

 

서버에 간단한 페이지를 출력하는 NGINX를 설치하는 예시

 

 

 

이미지의 레이어는 도면과 약간 다르게 바로 직전 단계 레이어에서 변경된 내용들만 저장된다.

 

 

위 순서의 1,2, 번 이미지의 레이어를 구성할 때

OS를 준비 한 뒤 OS 위에 Nginx소프트웨어를 설치해야한다.

소프트웨어를 설치하면 이 OS의 특정 폴더에 Nginx 소프트웨어와 관련된 파일들이 추가가 된다.

그래서 Nginx를 설치 한다는것은 기존 OS 파일 시스템에서 추가가 되는 부분이다.

이렇게 기존 레이어에서 변경되는 것들은 이 기존의 레이어를 수정하는것이 아니기존 레이어 위에 변경된 내용들이 새로운 레이어로 저장이 된다.

그래서 두번쨰 Nginx 설치 레이어에는 이전 레이어인 OS 레이어에서 NGINX소프트웨어가 추가된 부분만 따로 가지고 있는 것이다.

 

정리하자면 이미지의 레이어는 순차적으로 쌓이며 각각의 레이어는 이전 레이어에서 변경된 부분을 저장하고 있다.

그리고 같은 변경이 일어난 레이어는 공유해서 재사용할 수 있다.

 

 

이미지들로 실행시킨 컨테이너들 예시

 

docker run 명령어로 컨테이너를 실행하면 이미지의 가장 마지막 레이어 위에서 새로운 읽기 쓰기 전용 레이어가 추가 된다.

추가된 컨테이너 레이어는 애플리케이션 로그가 쌓이거나 실행중에 생기는 모든 변경 사항들을 저장한다.

 

수정이 불가능한 읽기 전용  이미지 레이어는 컨테이너를 실행하기 위한 세이브 포인트 역할을 한다.

읽기/쓰기 컨테이너 레이어는 프로세스가 변경하는 내용을 기록하는 레이어 이다.

즉, 컨테이너 레이어 한장이 읽기 전용 레이어들인 이미지의 상단에 추가되어 컨테이너 실행 중에 변경 되는 내용만 기록한다.

 

이미지 A로 두번째 컨테이너인 Continer2를 실행 하면 Continer2에 읽기 쓰기 레이어가 생성된다.

두개의 컨테이너는 이미지가 같기 때문에 동일한 읽기 전용 레이어를 공유하게 된다.

그러면 컨테이너를 실행할 때 전체 레이어를 복사하는것이 아니라 읽기 전용 레이어인 이미지 위에 새로운 컨테이너 레이어만 하나씩 추가 하는것이다. 실제로 큰 부분을 차지하는 이미지를 하나로 유지할 수 있기 때문에 컨테이너를 생성할 때 속도가 빨라 지며 저장소를 효율적으로 사용할 수 있다.

 

 

정리하자면 모든 컨테이너는 각자 자기만의 읽기 쓰기 레이어 한장을 가진다.

그리고 컨테이너를 만들 때 사용된 이미지에 따라서 이미지의 읽기 전용 레이어 전체를 공유할 수도있고 일부만 공유할 수도 있다.

이렇게 이미지의 읽기 전용 레이어를 활용하면 컨테이너를 실행할 때 전체 공간을 복사하지 않아도 되기 때문에 컨테이너를 빠르게 실행 시킬수 있으며 컨테이너가 늘어나면서 사용하는 공간을 최대한 작게 관리할 수 있다.

 

또한 하나의 이미지로 여러개의 컨테이너를 실행해도 이 컨테이너가 수행하는 근본적인 기능은 동일하다.

 

 

Dokcer History 명령어 실습

docker pull devwikirepo/hello-nginx
docker pull devwikirepo/config-nginx
docker pull devwikirepo/pre-config-nginx

위 3개의 이미지는 모두 hello nginx라는 페이지를 출력하는 nginx 이미지 이다.

 

 

docker image history 이미지명

이미지의 레이어를 구성한 순서를 확인하기 위해 위 명령어를 사용해보자.

 

docker image history devwikirepo/hello-nginx

 

hello-nginx 이미지는 nginx 오피셜 이미지를 다운한 다음 index.html 파일을 hello-nginx  텍스트가 있는 파일로 덮어 쓰기 했다.

COPY는 내가 가지고 있느 파일을 기존 레이어로 붙여넣기하는 방법이다.

COPY 명령어를 사용해서 내가 가지고 있는 index.html 파일을 이 hello-nginx 이미지 경로의 index.html 파일로 덮어쓰게 한것을 의미한다.

그래서 위 이미지를 사용해서 서버에 요청을 보내면 덮어 쓰기한 hello-nginx라는 문자가 출력된다.

 

config-nginx의 이미지는 hello-nginx와 거의 비슷하지만 한줄이 더 추가 되어있다.

config-nginx 이미지 index.html 파일을 덮어쓰기 한 후 etc/nginx/conf파일도 덮어 쓰기 하였다.

 

pre-config-nginx는 config-nginx와 비슷하지만 순서가 다르다.

config-nginx는 index.html을 먼저 수정하고 conf를 수정 했지만

pre-config-nginx는 conf를 수정하고 index.html을 수정했다.

 

 

이미지 레이어의 해시값 확인

이미지의 레이어가 고유한 ID값이 있다.

3개의 이미지 모두 같은 NIGNX 1.24 버전으로 만들어 졌기 때문에 최상단 6개 레이어의 해시값은 NGINX의 이미지의 해시값과 완전히 동일하다.

 

이미지의 레이어는 이전 파일에서 변경된 사항을 저장하기 때문에 결과적으로 conf와 pre-conf를 보면 같은 내용이더라도 구성한 순서가 달라 완전히 다른 레이어로 구성이 된다.

 

 

 

 

 

 

이미지와 커밋(commit)

 

이미지를 만드는 방법에는 크게 두가지가 있다.

커밋 방식 : 실행중인 컨테이너를 그 상태 그대로 이미지로 만듬

빌드 방식 : DockerFile이라는 명세서를 통해 이미지를 만듬

대부분 빌드 방식을 이용하지만 이 빌드 방식이 커밋 방식으로 동작하기 떄문에 커밋 방식을 먼저 알아보자.

 

 

 

먼저 공식 NGINX 이미지를 컨테이너로 실행 시키고 이 컨테이너 위에서 새로운 작업을 수행해서 이미지를 만들 것이다.

 

공식 NGINX 이미지에는 Nginx가 이미 설치 되어 있고 기본으로 default.index.html파일이 있다.

이제 이 index.html 파일의 내용을 welcom to nginx가 아닌 hello.nginx로 수정해 볼것이다.

먼저 docke run 명령을 사용해서 이미지를 실행 시키면 nigix 이미지 위에 읽기 쓰기 레이어인 컨테이너 레이어가 만들어 진다.

실행 중인 컨테이너에서 index.html 파일의 내용을 수정하면 이 이미지에 원래 있던 파일을 컨테이너 레이어에 카피해온 다음 수정된 파일의 내용을 wirte(덮어쓰기)한다.

마지막으로 이 상태에서 도커의 commit 기능을 사용해서 컨테이너 레이어 까지 포함한 모든 레이어의 상태를 이미지로 저장할 수 있다.

 

 

지금까지는 이미지에서 컨테이너로 실행만 했지만, 이번에는 반대로 Commit을 사용해서 컨테이너의 상태를 이미지로 저장하는것이다.

이렇게 새로운 이미지로 저장을 하게되면 기존에 있던 레이어들의 맨위에서 사용되던 컨테이너 레이어까지 포함해서 한장이 추가된 상태로 새로운 이미지로 만들어 진다.

 

docker run -it --name 컨테이너명 이미지명 bin/bash

-it 옵션을 입력하면 커맨트 창을 통해 실행할 컨테이너와 직접 상호 작용할 수 있다.

예를 들어 Nginx 컨테이너 안에 직접 접속해서 명령어를 실행할수 있다.

위와 같이 명령어로 cmd에 들어가는 실행 명령에 리눅스 shell을 명령어로 지정을 하면된다.

보통 이미지 내부의 파일 시스템을 확인해보거나 디버깅 용도로 많이 사용된다.

 

docker commit -m 커밋명 실행중인컨테이너명 생성할이미지명

새로운 이미지로 저장

nginx에 shell로 접근

 

docker ps로 컨테이너가 잘 생성됨을 확인

 

 

index.html파일 수정

 

커밋 메세지, 새로 생성될 컨테이너의 CMD("nginx","-g", "daemon off"),  실행중인 컨테이너 명(officialNginx), 생성할 이미지명(commitnginx)

 

이미지가 잘 생성된것을 확인

 

 

이미지 history에 새로운 이미지 레이어가 하나 추가된것을 확인

이 레이어는 커밋 전까지는 컨테이너의 읽기 쓰기 레이어였지만 커밋을 통해 기존에 있던 nginx 이미지들의 맨 위에 한장을 더 추가해서 새로운 이미지로 생성한것이다.

 

 

새로만든 이미지로 새로운 컨테이너가 잘 실행 됨을 확인

 

그럼 위 과정에서 수정한대로 hello-my-nginx가 잘 나온다 !

 

docker push softmoca/commitnginx

최종적으로 나의 개인 레지스트리에 이미지 push까지 완료 

 

 

 

https://www.inflearn.com/course/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%89%AC%EC%9A%B4-%EB%8F%84%EC%BB%A4

 

개발자를 위한 쉬운 도커 | 데브위키 - 인프런

데브위키 | 현업 개발자가 도커를 사용한 경험을 녹여낸 새로운 커리큘럼으로 기존 교재 및 강의와 차별된 강의를 제공합니다. 단순한 명령어 사용법이 아닌 도커를 왜 사용해야하는지 대한 근

www.inflearn.com