DevOps/Docker & Kubernetes

[Docker] Image Ship

나죽못고나강뿐 2023. 7. 13. 01:08
📕 목차

1. Registry, Repository, Image tag
2. Image push
3. Own docker registry
4. efficient Image tag
5. 공식 Image → 골든 Image
6. 연습 문제

1. Registry, Repository, Image tag

 

📌 이미지 참조(Image reference)

docker.io/jayang/golang:latest
  1. Registry 도메인
    • default : docker.io
  2. 계정(단체)명
    • Image 작성자의 계정 이름.
  3. Repository 이름
    • 일반적으로 애플리케이션 이름
    • 하나의 Repository는 여러 버전의 Image를 담을 수 있다.
  4. Image tag
    • default : latest
    • 버전 혹은 변종
    • 직접 패키징할 때는 명시해주는 것이 좋다.

 

✒️ Docker Hub 대규모 Registry Platform 대신에 Cloud를 사용하는 이유?

1. 서비스 되는 Image의 보안 문제
2. CI/CD 파이프라인 구축 편리성

 


2. Image push

 

1️⃣  Docker hub 계정 이름을 환경 변수에 설정

$dockerId="계정명" # poswershell
export dockerId="계정명" # linux or macOS

echo $dockerId # (계정명)
  • 운영체제에 상관없이 환경 변수 정의 가능한 명령어

 

2️⃣ Docker Hub에 Login

docker login --username $dockerId

  • "Login Succeeded"라고 뜨면 로그인에 성공한 것이다.
  • 내 계정에 대한 push 권한을 부여받은 상태다.

 

3️⃣ 기존 Image에 새로운 Image reference 부여

docker image tag image-gallery $dockerId/image-gallery:v1

docker image ls --filter reference=image-gallery --filter reference='*/image-gallery'

  • 이전 포스팅에서 "docker image build -t image-gallery ."로 빌드했지만, 해당 이미지 참조에는 계정이름이 지정돼 있지 않다. (push 불가능)
  • Image는 여러 개의 reference를 가질 수 있다. Image reference를 새로 부여하기 위해 다시 빌드할 필요는 없다.
    • 별도의 참조를 가지긴 하지만 Layer를 공유하므로, 용량은 일정하다. 
    • Image ID를 확인하면 두 Image reference가 같은 Image를 가리키는 것을 알 수 있다.

 

4️⃣ push

docker image push $dockerId/image-gallery:v1

  • 실제로 업로드 대상이 되는 것은 Image Layer다.
  • Registry 또한 Docker engine과 같은 방식으로 Image Layer를 다루기에 Dockerfile 최적화가 중요하다.
    • Registry에서도 Cache상에 Layer와 Hash와 일치하는 Layer가 없을 경우만 실제 업로드가 진행된다. 
    • Docker engine과 같은 방식이지만 Registry 상의 전체 Image를 대상으로 한다는 차이가 있다.
    • Layer가 기존 cache의 90%를 재활용 가능하다면, push된 Image의 Layer 90%는 Registry의 cache를 재사용할 수 있다.

 

✒️ Docker engine's Layer cache VS. Registry's Layer cache

1. 범위
    • Docker engine의 Layer cache는 Docker Host내에서 Image build하는 동안 사용되는 cache
    • Registry 상의 cache는 Image를 push할 때 Registry Server에 의해 관리되는 cache
    • 즉, Docker engine은 로컬 cache, Registry는 Image 공유 및 배포를 위한 중앙 서버 cache다.
2. Cache 유무에 따른 업로드
    • Registry 상의 cache 또한 Docker engine의 Layer cache처럼 Image의 Layer cache를 이용한다.
    • 만약 Image Layer 중 90%가 이전에 push된 Image와 동일한 hash값을 가지면, 해당 90%는 업로드를 수행하지 않고 재사용한다.

 

5️⃣ Docker Hub 확인

echo "https://hub.docker.com/r/$dockerId/image-gallery/tags"

  • 기존의 repository가 없는 Image를 push하면 Docker Hub에서 public repository를 새로 생성한다.
  • Registry는 개방형 API 명세다.
    • Docker Hub 외에도 클라우드, 데이터 센터의 Docker Trusted Registry 등이 있다.
    • 단순 Container 형태의 Registry 운영도 가능하다.

 


3. Own docker registry

 

📌 Local Registry 장점
  • 인터넷 회선 사용량과 전송 시간을 절약할 수 있다.
  • 데이터를 공개하지 않아도 된다.
  • 공개 Registry가 다운되었을 때, 신속하게 전환할 수 있다.
  • 인증 수단은 따로 구축해야 하나, 소규모 팀에서 상당히 유효하고, 자신만의 Image reference 명명 체계를 만들 수 있다.

 

1️⃣ Container 형태의 Docker Registry 실행

docker container run -d -p 5000:5000 --restart always diamol/registry
  • --restart : docker 재시작하면 해당 Container도 자동으로 재시작된다.
  • Local에 전용 registry가 생겼으며, 5000 port를 통해 Image tag를 부여하면 새로운 Registry에 Image를 push 할 수 있다.
  • Local 환경에서만 접속할 수 있다.

 

2️⃣ Domain 추가하기

# powershell
Add-Content -Value "127.0.0.1 registry.local" -Path C:\Windows\System32\drivers\etc\hosts

# linux or macOS
echo $'\n127.0.0.1 registry.local' | sudo tee -a /etc/hosts
  • Local PC에 registry.local라는 도메인 네임을 별명으로 hosts 파일에 추가하였다.
    • hosts 파일 : 도메인-주소 쌍의 정보를 기록한 작은 텍스트 파일

 

ping registry.local

  • ping이 정상적으로 찍힌다면 Local PC에 대한 Network 별명이 등록된 상태다.

 

 

3️⃣ Local registry 기반 image-gallery Image reference 변경

docker image tag image-gallery registry.local:5000/gallery/ui:v1

위의 방식을 이용해서 이전 포스팅에서 다룬 3개의 애플리케이션을 모두 gellery 프로젝트로 묶어야 한다.

  • Go Application : registry.local:5000/gallery/ui:v1
  • Java API : registry.local:5000/gallery/api:v1
  • Node.js API : registry.local:5000/gallery/logs:v1

 

4️⃣ 비보안 레지스트리 목록 수정

{
  "insecure-registries" : ["registry.local:5000"]
}
  • 현재 생성된 Local registry container는 HTTP를 사용하는데, Docker는 기본적으로 비보안 프로토콜이 적용된 registry를 사용할 수 없게 되어 있다.
  • daemon.json : Docker engine의 모든 설정이 저장된 파
    • Image Layer 저장 경로
    • Docker API가 주시하는 포트 번호
    • 허용된 비보안 레지스트리 목록 설정 등
  • Docker Daemon 탭에서 위의 JSON을 추가하고 Docker engine을 재시작하면 된다.

 

5️⃣ Docker engine setting information 

docker info

  • default registry는 Docker Hub로 고정되어 있다.
  • Insecure Registries에 등록된 IP로만 HTTP 통신이 가능하다.

 

✒️ Insecure Registries 주의 사항

• Docker engine과 registry 통신 내용을 제 3자가 엿볼 수 있다.
• Image push 과정에서 Layer가 유출될 수 있다.
• Registry에서 Image를 받아올 때 위조된 가짜 Image를 받아올 수도 있다.

하지만 Local 환경에서 Demo 용도라면 걱정할 필요 없다.

 

6️⃣ push

docker image push registry.local:5000/gallery/ui:v1

  • 처음에는 모든 Layer가 local registry에 push 된다.
  • 한 번 더 실행하면 아무것도 업로드되지 않는다.

 


4. efficient Image tag

 

📌 tag 표현법
[major].[minor].[patch]
  • Image tag는 어떤 문자열도 포함 가능하며, 기본적인 방법은 위의 형태다.
    • major : 완전히 다른 기능
    • minor : 추가된 기능은 있으나 기존 기능은 모두 유지
    • patch : 버그 픽스, 기능은 동일

 

📌 여러 버전으로 image reference 생성
docker image tag image-gallery registry.local:5000/gallery/ui:latest
docker image tag image-gallery registry.local:5000/gallery/ui:2
docker image tag image-gallery registry.local:5000/gallery/ui:2.1
docker image tag image-gallery registry.local:5000/gallery/ui:2.1.106
  • latest 태그 이동이 가장 잦고, major만 표기한 태그가 가장 느리다.
  • 클라이언트들에게 최신 버전을 얼마나 빠르게 따라갈지 선택권을 제공한다.
    • 특정 patch 버전을 유지할 수도 있다.

 


5. 공식 Image → 골든 Image

 

📌 신뢰할 수 있는 Registry?
  • Docker Hub는 해커의 멀웨어 배포에 제격인 조건이기 때문에 보안상 취약할 수 있다.
  • Docker Hub에서는 검증된 퍼블리셔(verified publisher)와 공식 이미지(official image) 제도를 사용한다.
    • 검증된 퍼블리셔
      • MS, Oracle, IBM 같은 신뢰할 수 있는 큰 기업들
      • 취약점 탐지 등의 승인 절차를 거친 Image만 배포된다.
    • 공식 이미지
      • 주로 open source software다.
      • 해당 프로젝트 개발 팀과 Docker가 함께 Image를 관리한다.
      • 취약점 탐색을 거치고 주기적으로 업데이트되며, 잘 최적화된 Dockerfile로 구성된다.
      • 대부분 공식 Image를 기반 Image로 사용하다가 점차 자신만의 기반 Image로 전환하게 된다. (Golden Image)

 

📌 Golden Image

 

 

  • Golden Image : 공식 Image를 기반으로 자신만의 인증서나 환경 설정값을 custome한 정형화된 Image
    • Docker Hub의 Oraganization repository나 local repository에서 관리된다.
    • 해당 기업이나 자신의 모든 애플리케이션의 Base Image가 된다.
  • 공식 Image는 매달 새 버전이 release되지만, Golden Image 업데이트 주기는 개인이 컨트롤할 수 있다.
  • CI/CD 파이프라인에서도 Dockerfile을 확인하는 방법으로 Golden Image 사용을 강제하는 것도 좋은 방법이다.
  • 인스턴스 프로비저닝 시간 최소화와 보안 측면 이점 또한 취할 수 있다.
  • 단, 특정 버전 취약점 이슈 발생과 같은 상황에는 새로 Image를 build 해야하는 부지런함을 요구한다.

 


6. 연습 문제

 

  • Docker registry API v2 명세가 담긴 문서를 읽고 조사하라.
  • REST API를 통해서만 Local docker registry에 접근하여, gallery/ui Image의 모든 tag를 local registry에 push하라.
  • 모든 tag가 push된 것을 확인하고, 삭제하라. (삭제된 것까지 확인하라)
  • Hint
    • 한 번의 image push 명령만으로 모든 tag를 push하라
    • local pc registry API 주소는 http://registry.local:5000/v2
    • 대상 repository(gallery/ui)의 tag 목록을 먼저 확인하라.
    • Image manifest를 확인하라.
    • API를 통해 Image를 삭제하라. (이때 manifest 사용)
    • 참조 문서를 참고하라. HEAD 요청에서 꼭 필요한 request header가 있다.

 

docker image push registry.local:5000/gallery/ui

일단 image를 로컬 registry에 올려놓고 문서를 한참동안 뒤졌다.

힌트에서 tag를 먼저 확인하라길래 문서에서 tag를 검색했더니

 

어, 이건가?

뭐가 뭔지는 모르겠지만 하라는 대로 해보자.

HTTP 요청을 위해서 가장 첫 포스팅에서 조사했었던 curl.exe를 통해 Network 요청을 진행할 것이다.

 

curl.exe http://registry.local:5000/v2/gallery/ui/tags/list

빙고.

그 다음 이미지 매니패스트도 확인하라고 하니 다시 공식 문서를 뒤져보자

 

대충 url 경로는 비슷한 거 같은데, reference에는 tag나 digest를 넣으면 된다고 한다.

latest 바로 넣고 돌려보자.

curl.exe http://registry.local:5000/v2/gallery/ui/manifests/latest

공식 문서 밑에 있는 JSON이 뭔가 했더니, 해당 url로 GET 요청을 보내면 돌려주는 정보였다.

 

이 다음에 완전히 막혀서 뭘 하라는 건지 헤매다가 답안을 참고했다.

curl.exe --head http://registry.local:5000/v2/gallery/ui/manifests/latest -H 'Accept: application/vnd.docker.distribution.manifest.v2+json'

이게 왜 필요한건가 했는데, 공식문서에 이렇게 적혀있다.

이따 delete 요청할 때 digest 정보 요구할 건데, registry 버전이 2.3 이상 부터는 위의 Header를 덧붙여야 올바른 정보를 내준다는 거였다.

그렇게 얻은 결과값이 위에 있는데, 이제 삭제해야 하니까 Docker-Content-Digest의 value값을 복사하자.

 

curl.exe -X DELETE http://registry.local:5000/v2/gallery/ui/manifests/sha256:27fa54df4058a59cc1e5a34344e45b7dc3ff0668c4dd6cd2df2196af40ea5d51

HTTP 요청 형식을 바꾸기 위해서 X 옵션을 걸고 DELETE 요청으로 바꿨다.

 

curl.exe http://registry.local:5000/v2/gallery/ui/tags/list

다시 확인해보면 Image가 모두 제거된 것을 알 수 있다.