[Docker] Image Ship
📕 목차
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
- Registry 도메인
- default : docker.io
- 계정(단체)명
- Image 작성자의 계정 이름.
- Repository 이름
- 일반적으로 애플리케이션 이름
- 하나의 Repository는 여러 버전의 Image를 담을 수 있다.
- 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가 모두 제거된 것을 알 수 있다.