일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 명시적 타입 변환
- JavaScript
- 프로세스
- docker
- webpack
- 타입 단언
- Pull Request
- 프로젝트 구조
- linux 배포판
- Microtask Queue
- 좋은 PR
- 주니어개발자
- TypeScript
- prettier
- next.js
- react
- type assertion
- CS
- Compound Component
- VirtualDom
- Custom Hook
- Sparkplug
- task queue
- prettier-plugin-tailwindcss
- Dockerfile
- Render Queue
- 암묵적 타입 변환
- Event Loop
- Headless 컴포넌트
- AJIT
- Today
- Total
너굴 개발 일지
[리뷰] 도커 교과서 - 이미지 공유, 도커 볼륨 본문
도커 교과서의 5장(레지스트리에 이미지 공유), 6장(도커 볼륨을 이용한 퍼시스턴트 스토리지)을 읽으면서 공부한 것을 정리한 글입니다.
도커의 여러 장점 중에서도 공유는 핵심에 해당됩니다. 공유는 로컬 컴퓨터에서 빌드한 이미지를 다른 사람이 사용할 수 있게끔 하는 기능입니다. 그러면 공유되는 이미지의 구조와 공유 방식에 대해 알아보겠습니다.
이미지 참조
우리가 내려받는 이미지는 도커 레지스트리라는 서버에 저장됩니다.
도커 레지스트리 중 가장 유명한 도커 허브는 도커 엔진에 기본으로 설정된 레지스트리로 로컬에 없는 이미지를 내려받을 경우, 먼저 도커 허브에서 탐색합니다.
이때, 도커 이미지를 구분하기 위해 이미지에는 이미지 참조(전체 이름)이 부여되며 레지스트리에서 이미지 식별자 역할을 합니다.
이미지 참조 구조
도커 이미지는 4가지로 구성되어 있습니다.
- 레지스트리 도메인 : 이미지가 저장된 레지스트리 도메인으로, 미지정시 기본값인 도커 허브 도메인을 사용하고 자사의 별도 도커 레지스트리를 별도로 꾸릴 경우, 인하우스 레지스트리 도메인 지정 가능
- 계정명 : 이미지를 작성한 개인 혹은 단체명
- 리포지토리명 : 일반적으로 애플리케이션명을 사용하며 공개 리포지토리라면 누구나 이미지를 받을 수 있지만 해당 단체의 소속원만이 리포지토리에 push할 수 있음
- tag : 버전 혹은 변종을 의미하며, 미지정시 기본값인 latest를 사용함, 애플리케이션 패키징시 버전 구분을 위해 태그 명시는 필수적임
빌드 이미지 푸시
이미지를 도커 허브에 푸시하는 절차는 다음과 같습니다.
- 도커 허브 계정 생성
- 도커 명령행을 통해 레지스트리에 로그인 (로그인을 통해 레지스트리에 이미지를 푸시할 권한이 부여)
- 이미지에 푸시 권한을 가진 계정명을 포함하는 이미지 참조 생성
먼저 도커 허브 계정을 생성했다면 레지스트리에 로그인을 진행합니다.
docker login --username $dockerId // 계정명을 환경 변수로 정의한 상태
Password:
Login Succeeded
로그인이 완료되었다면 이전에 빌드한 이미지를 레지스트리에 푸시하기 위해 이미지 참조에 계정명을 지정하고 레지스트리에 푸시합니다.
이미지는 여러 개의 이미지 참조를 가질 수 있으며 이미지 참조를 부여하기 위해 다시 빌드할 필요는 없습니다.
// 기존 이미지에 새로운 이미지 참조 부여
docker image tag image-gallery $dockerId/image-gallery:v1
// 해당 이미지를 레지스트리에 푸시
docker image push $dockerId/image-gallery:v1
The push refers to repository [docker.io/qorwjddus96/image-gallery]
14a11dbe5a42: Layer already exists
88a2e62671b6: Layer already exists
1a319d5a1398: Layer already exists
089d7a196fa2: Layer already exists
c087aa3a9887: Layer already exists
20312b574584: Layer already exists
v1: digest: sha256:d2401b1b6fd39c8fc169dcc81ff2a757145aa91a8ac0b399f1a6247cf4e22de8 size: 1574
결과를 보면 이전에 푸시한 이미지라서 기존에 캐시된 레이어를 사용한 것을 확인할 수 있습니다.
실제로 레지스트리에서도 캐시상에 레이어 해시와 일치하는 레이어가 없을 경우에만 실제로 업로드가 이뤄지기에 도커 엔진의 레이어 캐시와 완전히 같은 방식이지만, 레지스트리상의 전체 이미지를 대상으로 한다는 점이 다릅니다.
따라서 캐시 레이어 사용을 위한 최적화된 Dockerfile 스크립트는 빌드 시간, 디스크 용량 등 여러 부분에 영향을 미치는 중요한 요소입니다.
푸시한 이미지는 도커 허브에서 확인할 수 있으며 푸시했을 때 기존 리포지토리가 없다면 도커 허브에서 public 리포지토리를 자동으로 생성합니다.
나만의 도커 레지스트리 운영
로컬 네트워크에 전용 레지스트리가 있다면 인터넷 회선 사용량을 줄이고 전송 시간도 절약하며 공개 레지스트리가 다운된 경우 신속하게 전환할 수 있다는 장점이 있습니다. 또한 실제 도메인명이나 IP 주소를 알려주면 로컬 네트워크상의 다른 사용자에게 이미지를 공유할 수 있습니다.
로컬에 도커 레지스트리를 운영하는 방법은 4단계로 구성됩니다.
- 컨테이너 형태로 레지스트리 실행
- host 설정으로 네트워크 별칭 설정 (선택)
- 도커엔진 설정에 비보안 레지스트리 허용 목록 추가
- 태그 부여한 이미지 푸시
// 패키징한 이미지를 사용해 컨테이너 형태로 도커 레지스트리 실행
docker container run -d -p 6000:6000 --restart always diamol/registry
// hosts 파일 설정에서 IP 주소에 도메인명 설정
# Docker practice
127.0.0.1 registry.local
// 기존에 빌드한 이미지에 생성한 레지스트리 도메인명을 추가해 이미지 참조 부여
docker image tag image-gallery registry.local:6000/gallery/ui:v1
// 도커 데스크탑에서 도커 엔진 비보안 레지스트리 허용 목록 추가 후 도커 엔진 재시작
{
"insecure-registries": [
"registry.local:6000"
]
}
// 도커 엔진 설정 정보를 출력해 비보안 레지스트리 허용 목록 확인
docker info
// 태그 부여한 이미지 푸시
docker image push registry.local:6000/gallery/ui:v1
로컬 컴퓨터의 레지스트리에 이미지를 푸시하고 내려받기 위해선 비보안 프로토콜인 HTTP
를 사용합니다.
도커 기본 설정에서는 비보안 프로토콜이 적용된 레지스트리를 사용할 수 없기에 비보안 레지스트리 허용 목록에 추가해야 합니다.
비보안 레지스트리를 사용할 경우, 도커 엔진과의 통신 내용을 제 3자가 엿볼 수 있고 이미지 푸시 과정에서 레이어가 유출되거나 레지스트리에서 이미지를 받아올 때 위조된 가짜 이미지를 받아올 위험이 존재합니다. 따라서 모든 상업용 레지스트리 서버는 HTTPS가 적용되어 있습니다.
하지만 로컬 컴퓨터에서 데모 용도로 사용한다면 비보안 레지스트리라도 크게 걱정할 필요는 없습니다.
컨테이너는 무상태 애플리케이션에게는 최적의 실행 환경입니다. 사용량이 증가해도 클러스터에 실행 중인 컨테이너의 수를 늘리면 모든 요청을 신뢰성 있게 똑같이 처리합니다.
하지만 애플리케이션에는 전혀 상태가 없을 수 없습니다. 예를 들면 퍼시스턴시나 성능 향상을 위해 디스크를 사용하는 컴포넌트가 존재할 수 있기 때문입니다. 이렇게 유상태 애플리케이션을 도커로 실행하려면 어떻게 해야 할까요?
컨테이너 속 데이터가 사라지는 이유
컨테이너도 단일 드라이브로 된 파일 시스템이 존재합니다. 파일 시스템 내용은 이미지 속 파일로부터 만들어지며 컨테이너 디스크는 이미지 레이어를 순서대로 합쳐 만든 가상 파일 시스템입니다.
모든 컨테이너는 독립된 파일 시스템을 가지며, 같은 이미지에서 실행한 여러 컨테이너는 처음엔 디스크 내용이 같지만 한 컨테이너에서 파일을 수정해도 다른 컨테이너나 이미지는 영향을 받지 않습니다.
컨테이너 파일 시스템 구조
컨테이너의 파일 시스템은 크게 2가지로 이미지 레이어
, 기록 가능 레이어
로 구성됩니다.
이미지 레이어
- 모든 컨테이너가 공유하는 레이어로 읽기 전용
- 생애 주기 : 이미지를 삭제할 때까지 로컬 컴퓨터의 이미지 레이어에 존재
기록 가능 레이어
- 컨테이너마다 따로 가지며 새 파일 생성 혹은 기존 이미지 레이어 수정 가능 (
기록 중 복사
기능 사용) - 생애주기 : 컨테이너와 같은 생애주기로 컨테이너 실행시 생성, 컨테이너 삭제시 삭제 (컨테이너 종료시 유지)
이미지 레이어는 읽기 전용인데 기록 가능 레이어는 이미지 레이어를 어떻게 수정할 수 있을까요?
기록 가능 레이어는 기록 중 복사
라는 방법으로 기존 이미지 레이어에 파일을 수정할 수 있으며 다음과 같은 방식으로 동작합니다.
- 파일을 쓰기 가능 레이어로 복사
- 쓰기 가능 레이어에서 파일 수정
즉, 수정된 파일은 해당 컨테이너의 기록 가능 레이어에만 존재하기에 컨테이너 속 파일 수정시, 이미지를 공유하는 컨테이너나 이미지는 영향을 받지 않습니다.
하지만 컨테이너 파일 시스템은 컨테이너와 같은 생애주기를 가지기에 컨테이너 삭제시 기록 가능 레이어, 수정 데이터도 모두 소멸됩니다.
만약 손실되면 안되는 데이터가 있을 경우, 컨테이너 삭제시 큰 문제가 발생할 수 있습니다. 이런 문제를 어떻게 해결할 수 있을까요?
도커 볼륨을 사용하는 컨테이너
도커 볼륨이란
- 도커에서 스토리지를 다루는 단위로, 컨테이너를 위한 USB 메모리 역할
- 컨테이너와 독립적으로 존재하며 별도의 생애주기를 가짐, 컨테이너에 연결 가능
- 퍼시스턴시가 필요한 유상태 애플리케이션을 컨테이너로 실행시, 사용함
도커 볼륨 사용법
- 수동으로 직접 볼륨 생성 후 컨테이너에 연결
- Dockerfile 스크립트에서
VOLUME
인스트럭션 사용- 이때 이미지에서 볼륨 정의시, 컨테이너 생성 시점마다 새로운 볼륨이 생성되므로
volumes-from
플래그를 사용해 다른 컨테이너 볼륨 연결 가능
- 이때 이미지에서 볼륨 정의시, 컨테이너 생성 시점마다 새로운 볼륨이 생성되므로
아래는 수동으로 볼륨을 직접 생성 후 애플리케이션에서 UI를 통해 데이터 추가 후, 업그레이드된 버전의 애플리케이션에 기존 볼륨을 연결하는 과정입니다.
# 복사 대상 경로를 환경 변수로 정의
target='/data'
# 데이터를 저장할 볼륨 생성
docker volume create todo-list
# 볼륨을 연결해 v1 애플리케이션 실행
docker container run -d -p 8011:80 -v todo-list:$target --name todo-v1 diamol/ch06-todo-list
# 페이지에 접속해 데이터 추가
# http://localhost:8011
# v1 애플리케이션 컨테이너 삭제
docker container rm -f todo-v1
# 같은 볼륨을 사용하도록 v2 애플리케이션 컨테이너를 실행
docker container run -d -p 8011:80 -v todo-list:$target --name todo-v2 diamol/ch06-todo-list:v2
도커 볼륨 사용 목적
- 일부 컨테이너는 자신만이 접근할 수 있는 파일이 필요할 수 있기에 하나의 볼륨을 여러 컨테이너가 사용하며 동시에 접근하면 비정상적인 동작 발생 위험성 존재
- 컨테이너간 파일 공유보다 업데이트간 상태 보존 용도가 더 적합함
- 이미지에 정의하는 것보다는 볼륨에 이름을 부여해 생성하고 다른 컨테이너에 옮겨 연결하는 명시적 관리가 더 나음
VOLUME 인스트럭션, --volume 플래그 차이
- VOLUME : 빌드된 이미지로 컨테이너 생성시 볼륨을 미지정하면 무작위 식별자로 항상 새로운 볼륨 생성되기에, 재사용시 식별자 기억 필수
- volume 플래그 : 이미지에 정의된 볼륨 유무와 상관 없이 지정된 볼륨을 컨테이너에 마운트함
따라서 이미지로 만들 경우, 안전장치 삼아 이미지에 볼륨 인스트럭션 정의를 포함하고 이미지를 사용할 경우, 이미지의 기본 볼륨 설정에 의존하지 않고 명시적으로 볼륨에 이름을 붙여 사용하는 방법이 권장됩니다.
'독서' 카테고리의 다른 글
[리뷰] 도커 교과서 - 멀티 스테이지 빌드 (1) | 2023.08.07 |
---|---|
[리뷰] 도커 교과서 - 컨테이너, 도커 이미지 (0) | 2023.08.03 |
[리뷰] 코어 자바스크립트 4장 - 콜백 함수 (0) | 2023.06.05 |
[리뷰] 코어 자바스크립트 3장 - this (0) | 2023.06.04 |
[리뷰] 코어 자바스크립트 2장 - 실행 컨텍스트 (0) | 2023.06.03 |