공유란 로컬 컴퓨터에서 빌드한 이미지를 다른 사람이 사용하게끔 하는것이다.
docker.io/diamol/golang:latest
docker.io: 이미지가 저장된 레지스트리의 도메인. 기본값은 도커 허브이다.
diamol: 이미지 작성자의 계정 이름. 개인 혹은 단체의 이름에 해당한다.
ㄴ 이 리포지터리는 공개 리포지터리 이므로 누구든지 이미지를 내려받을 수 있지만 diamol 단체의 소속원만이 리포지터리에 이미지를 푸시 할 수 있다.
golang: 이미지 리포지터리 이름. 일반적으로 애플리케이션의 이름에 해당한다. 하나의 리포지터리는 여러 버전의 이미지를 담을 수 있다.
latest: 이미지 태그. 애플리케이션의 버전 혹은 변종을 나타낸다. 기본값은 latest다
레지스트리를 통해 다른 사람이 이미지를 사용하게 하려면 좀 더 상세한 정보를 이미지 이름에 포함시켜야한다. 바로 이 이미지 참조가 레지스트리에서 특정한 이미지를 식별하는 식별자 역할을 하기 때문이다.
레지스트리와 태그 등의 정보는 따로 지정하지 않아도 도커가 미리 정해진 기본값을 사용한다.
레지스트리의 기본값 : 도커 허브
태그의 기본값 : latest
규모가 큰 회사는 사내 네트워크나 전용 클라우드 환경에 자사의 도커 레지스트리를 별도로 꾸리는 경우가 많다. 이미지 참조의 첫 부분에 이런 인하우스 레지스트리의 도메인을 기재하면 도커는 도커 허브 대신 해당 레지스트리를 찾아간다.
레지스트리에 이미지를 푸시하려면 두 가지 절차가 필요하다.
첫 번째 도커 명령행을 통해 레지스트리에 로그인을 해야한다. 이 로그인을 통해 레지스트리에 이미지를 푸시할 권한이 부여 된다.
두 번째는 이미지에 푸시 권한을 가진 계정명을 포함하는 이미지 참조를 붙여야한다.
export dockerId="도커허브계정이름"
docker login --username $dockerId
// 기존 이미지에 새로운 이미지 참조를 부여하라. 태그는 v1으로 지정한다.
docker image tag image-gallery $dockerId/image-gallery:v1
//image-gallery 이미지의 이미지 참조 목록을 확인하라.
docker image ls --filter reference=image-gallery --filter reference='*/image-gallery'
이미지 ID가 같은 것으로 보아 두 이미지 참조가 같은 이미지를 가리키는 것을 알 수 있다.
// $dockerId/image-gallery:v1 이미지를 레지스트리에 푸시하라.
docker image push $dockerId/image-gallery:v1
레지스트리 역시 도커 엔진과 같은 방식으로 이미지 레이러를 다루면 그만큼 Dockerfile 스크립트의 최적화가 더욱 중요해진다.
레지스트리에서도 캐시상에 레이어 해시와 일치하는 레이어가 없을 경우에만 실제로 업로드가 이뤄진다.
레이어의 90%가 기존 캐시를 재사용할 수 있도록 이미지를 최적화했다면, 이 이미지를 푸시할 때 90%의 레이어는 레이스트리의 캐시를 재사용할 수 있다.
최적화된 Dockerfile 스크립트는 빌드 시간, 디스크 용량을 넘어 네트워크 대역폭까지 영향을 미치는 중요한 요소다.
기존의 리포지터리가 없는 이미지를 푸시하면 도커 허브에서 리포지터리를 새로 생성하고, 기본적으로 이 리포지터리는 누구나 접근할 수 있는 공개 상태가 된다.
지금 막 푸시한 image-gallery 애플리케이션을 이제 누구나 검색하고 내려받고 실행할 수 있다.
로컬 네트워크에 전용 레지스트리가 있으면 편리한 점
도커 코어 레지스트리 서버는 깃허브 저장소 docker/distribution 에서 개발된다. 코어 레지스트리 서버는 도커 허브와 동일한 캐시 시스템을 통해 이미지를 내려받고 푸시하는 기본적인 기능을 제공한다.
코어 레지스트리 서버는 매우 가볍게 동작하는 서버이다.
ui는 제공하지 않는다.
//저자가 패키징한 이미지를 사용해 컨테이너 형태로 도커 레지스트리를 실행한다.
// --restart 플래그를 부여하면 도커를 재시작 했을 때 해당 컨테이너도 자동으로 재시작 된다.
docker container run -d -p 5000:5000 --restart always diamol/registry
이제 로컬컴퓨터에 전용 레지스트리가 생겼다. 이 명령으로 실행되는 레지스트리 서버의 기본 포트는 5000이다.
이 레지스트리의 도메인 localhost:5000을 사용해 이미지에 태그를 부여하면 새로운 레지스트리에 이미지를 푸시할 수 있다.
그러나 이 레지스트리는 로컬 컴퓨터에서만 접근할 수 있기 때문에 크게 유용하지 않다. 로컬 컴퓨터에 제대로 된 도메인 네임을 붙이면 더 활용도가 높아진다.
도메인 네임을 별명으로 붙여보자.
로컬 컴퓨터에 registry.local 이라는 별명을 추가한다. 별명을 추가하려면, 도메인과 IP 주소의 연결을 기록한 작은 텍스트 파일 hosts 파일에 새로운 도메인-주소 쌍을 추가하면 된다.
echo $'\n127.0.0.1 registry.local' | sudo tee -a /etc/hosts
ping registry.local 명령을 입력 해 로컬 컴퓨터의 IP 127.0.0.1 이 응답하는지 확인해 보자.
registry.local 은 hosts 파일에 추가한 로컬 컴퓨터에 대한 네트워크 별명이다.
127.0.0.1 은 자기자신을 나타내는 IP 주소다.
지금부터 이미지 참조에 도메인 네임 registry.local:5000을 사용할 수 있다.
// image-gallery 이미지에 새로 만든 레지스트리 도메인 네임을 추가해 이미지 참조를 부여해 보자.
docker image tag image-gallery registry.local:5000/gallery/ui:v1
로컬 컴퓨터의 레지스트리에 이미지를 푸시하려면 한 가지 해야 할 일이 더 남아 있다.
이 레지스트리 컨테이너는 이미지를 푸시하고 내려받기 위해 보안 프로토콜인 HTTPS 대신 비보안 프로토콜인 HTTP를 사용한다. 도커의 기본 설정에서는 비보안 프로토콜이 적용된 레지스트리를 사용할 수 없게 돼 있다. 비보안 레지스트리를 사용하려면 로컬 컴퓨터의 레지스트리를 비보안 레지스트리 허용 목록에 추가해야한다.
이미지 레이어의 저장 결로, 도커 API가 주시하는 포트 번호, 허용된 비보안 레지스트리 목록 등 도커 엔진의 모든 설정은 daemon.json이라는 이름의 JSON 포맷으로 된 설정 파일에 들어있따. 이 파일은 윈도에서는 C:\Program Data\docker\config, 리눅수에서는 /etc/docker에 위치한다. 설정 파일을 직접 편집할 수 있지만, 도커 데스크톱을 사용 중이라면 사용자 인터페이스를 통해 설정을 수정할 수 있다.
//태스크 바에 있는 도커 고래 아이콘을 우클릭해 컨텍스트 메뉴에서 Settings(macO에서는 Preference) 를 클릭한다. 그 다음 Deamon 탭을 열어 비보안 레지스트리 목록 (insecure registries)에 registry.local:5000을 추가한다.
Settings > Docker Engine 에 들어가서 json 파일에 insecure-registries 추가
{
"insecure-registries": [
"registry.local:5000"
]
}
//도커 엔진 설정 정보를 출력해 비보안 레지스트리 허용 목록을 확인하라
docker info
HTTP로 통신하는 비보안 레지스트리는 이 목록에 추가되지 않는 한 사용할 수 없다.
비보안 레지스트리를 사용할 때는 주의가 필요하다. 도커 엔진과 레지스트리의 통신 내용을 제삼자가 엿볼 수 있으며 이미지 푸시과정에서 레이어가 유출될 수 있다. 최악의 경우 레지스트리에서 이미지를 받아 올 때 위조된 가짜 이미지를 받아 올 가능성도 있다.
모든 상업용 레지스트리 서버는 HTTPS가 적용돼 있으며, 도커에서 배포하는 오픈 소스 레지스트리도 HTTPS를 사용하도록 설정할 수 있다.
하지만 로컬 컴퓨터에서 데모 용도로 사용한다면 비보안 레지스트리라도 크게 걱정 ㄴㄴ다.
태그가 부여된 이미지를 로컬 컴퓨터의 레지스트리에 푸시할 수 있다. 이미지 참조에 레지스트리의 도메인이 포함돼 있으며 해당 도메인이 비보안 레지스트리 허용 목록에도 들어 있으므로 사용에 문제가 없다.
//태그를 부여한 이미지를 푸시하라
docker image push registry.local:5000/gallery/ui:v1
실제 도메인 네임이나 IP주소를 알려주면 로컬 네트워크상의 다른 사람에게 이미지를 공유할 수 있다.
https://waspro.tistory.com/532 <-참고
대부분의 소프트웨어가 소수점으로 구분된 숫자로 버전을 타나댄다.
[major].[minor].[patch] 형태를 따르는것이 일반적이다.
patch: 변경 내용이 수정뿐이고 기능은 지난 버전과 같다.
minor: 추가된 기능은 있으되 기존 기능은 모두 유지한다.
major: 완전히 다른 기능을 가진다.
이미지 태그에 이런 방식을 적용하면 특정 major 혹은 minor 버전을 유지하거나 최신버전을 계속 따라가는 등의 선택권을 사용자에게 주어야한다.
// 앞서 패키징 했던 Go 애플리케이션에 major.minor.patch 형식의 버전 태그를 부여하라.
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
이런 방식을 사용하는 이유는 사용자들에게 최신 버전을 얼마나 빠르게 따라갈지 선택권을 줄 수 있기 때문이다.
pull 명령이나 FROM 인스트럭션에서 특정한 패치 버전을 콕 집어 사용하면서 항상 같은 버전을 보장받을 수도 있다.
2.1.106 태그는 10월이 지나도 계속 같은 버전을 가리킨다.
만약 패치 업데이트를 자동으로 전달받고 싶다면 2.1 태그를 사용하면 되고, 마이너 업데이트까지 전달받고 싶다면 2태그를 사용하면 된다.
어떤 선택을 하더라도 균형있게 관리하자!
특정 패치 버전을 집어 사용한다면 계속 같은 버전을 사용하지만 보안 패치를 받을 수 없다.
major 버전 태그를 지정하면 지속적인 업데이트를 받겠지만, 예기치 않은 기능 변경을 겪을 수도 있다.
특히 직접 작성한 Dockerfile 스크립트의 기반 이미지는 가능한 한 정확한 버전을 지정하는게 좋다. 개바 ㄹ팀과 동일한 도구로 빌드하고 동일한 런타임을 사용해 실행할 수 있기 때문이다.
버전을 구체적으로 지정하지 않으면 문제가 생기기 쉽다. 빌드용 이미지가 업데이트되면서 빌드가 깨질 수 있고, 런타임의 업데이트로 인해 애플리케이션 실행 과정에서 오류가 발생할 수도있다.
레지스트리에서 제공되는 이미지를 얼마나 신뢰할 수 있을까?
도커 허브에는 누구나 이미지를 푸시할 수 있고 그 이미지를 도 누구나 내려받을 수 있다. (해커의 타겟이 되기 딱 좋다,,)
도커 허브는 검증된 퍼블리셔(마이크로소프트,오라클,IBM 같은 큰기업)와 공식 이미지 제도를 통해 이러한 피해를 방지한다.
이들이 배포하는 이미지는 취약점 탐지 등의 승인 절차를 거쳐 공개된다. 이들의 이미지는 도커와 해당 퍼블리셔의 지원을 받을 수 있다는 의미로 인증을 받는다.
컨테이너에서 새로 나온 최신 버전의 소프트웨어를 실행하고 싶다면 검증된 퍼블리셔가 배포하는 인증된 이미지를 사용하는것이 최선이다.
공식이미지는 주로 오픈소스 소프트웨어로, 새당 프로젝트 개발팀과 도커가 함께 이미지를 관리한다.
역시 취약적 탐색을 거치고 주기적으로 업데이트되며, 잘 최적화된 Dockerfile 스크립트로 구성된다.
공식 이미지의 모든 콘텐츠는 오픈 소스이며 깃헙 저장소에서 Dockerfile 스크립트를 직접 볼 수 있다.
대부분의 경우 이 공식 이미지를 기반 이미지로 삼아 이미지를 빌드하기 시작하지만, 직접 빌드한 이미지를 사용하다 보면 좀 더 많은 것을 통제하고자 하는 시기가온다. 바로 이 시점에 자신이 선호하는 기반 이미지로 전환한다. 이 이미지를 골든 이미지라고 한다.
예시
공식이미지: OpenJDK 의 특정 버전을 제공하는 공식 이미지는 도커 허브를 통해 제공된다.
골든이미지: 우리가 기반 이미지로 쓰는 이미지. 기존 특정 버전의 공식 이미지를 기반으로 하며, 필요에 따라 수정되고 이미지 참조의 명명 체계도 다르다.
직접 빌드한 이미지: 우리가 개발한 자바 애플리케이션은 모두 골든 이미지를 기반 이미지로 삼는다. 신뢰성 있는 공식이미지와 커스터마이징의 장점을 합칠 수 있다.
골든 이미지
아래 스크립트는 닷넷 코어 애플리케이션을 위한 골든 이미지를 빌드할 수 있는 스크립트다.
cd ch05/exercises/dotnet-sdk
docker image build -t golden/dotnetcore-sdk:3.0 .
cd ../aspnet-runtime
docker image build -t golden/aspnet-core:3.0 .
이제 이 골든 이미지를 닷넷 코어 애플리케이션의 멀티 스테이지 빌드에 사용할 수 있다.
// 골든 이미지를 사용한 닷넷 코어 애플리케이션의 멀티 스테이지 빌드 스크립트
FROM golden/dotnetcore-sdk:3.0 AS builder
COPY . .
RUN dotnet bublish -o /out/app app.csproj
FROM golden/aspnet-core:3.0
COPY --from=builder /out /app
CMD ["dotnet", "/app/app.dll"]
일반적인 멀티 스테이지 빌드 스크립트와 같은 구조이지만 그 기반 이미지부터 우리가 만든 이미지라는 차이가 있따.
공식 이미지는 매달 새 버전이 릴리스되지만, 골든 이미지는 업데이트 주기를 마음대로 정할 수 있다. 또한, 지속적 통합 파이프라인에서 Dockerfile 스크립트를 확인하는 방법으로 골든 이미지 사용을 강제하는 것도 좋은 방법이다.