Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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 31
Archives
Today
Total
05-16 20:20
관리 메뉴

nomad-programmer

[DevOps/Docker] Docker Registry를 사용한 Private Docker 저장소 구축 (Local 저장소 서버 & 저장 경로 변경 & 이미지 제거) 본문

DevOps/Docker

[DevOps/Docker] Docker Registry를 사용한 Private Docker 저장소 구축 (Local 저장소 서버 & 저장 경로 변경 & 이미지 제거)

scii 2020. 12. 3. 01:57

Docker 이미지에는 인터넷상에 공개하고 싶지 않은 정보가 포함되는 경우도 있다.  이럴 때  하나의 방법으로 Docker 이미지 관리를 위한 저장소를 로컬 환경에 구축할 수 있다.


Docker 데이터 저장 경로 변경 (선택 사항)

docker 로컬 저장소 주의할 점

private 도커 저장소에서는 Docker 이미지를 영구 데이터로 관리할 필요가 있다는 점이다.

Docker에서는 호스트 머신에 볼륨을 공유함으로써 영구 데이터를 일원 관리할 수 있다. 하지만 이 데이터를 관리하려면 신뢰성이 높고 용량이 충분한 스토리지를 마련해야 한다. 또한 만일의 장애에 대비해 다중화 구성을 검토할 필요가 있으며, 정기적으로 데이터 백업이나 서버 감시 등과 같은 운용도 필요하다.

로컬 환경에 Docker 저장소를 구축하기전, 도커 데이터의 저장 경로를 변경할 수 있다. 이렇게 하는 이유는 도커 데이터의 안정성을 확보하기 위함이다. 보통 도커를 로컬에 구축하면 하나의 서버에 구축을한다. 그런데 그 서버는 단지 서버용이므로 용량은 부족할 수 있다. 따라서 이미지, 컨테이너 등 도커 데이터를 용량이 큰 스토리지에 저장할 필요가 있다.

이럴 때는 daemon.json 파일을 작성하면 된다. CentOS7 기준으로 /etc/docker 디렉토리안에 daemon.json 파일이 존재한다면 다음과 같이 data-root를 추가해주고 파일이 존재하지 않는다면 새롭게 생성한 후 내용을 적어주면된다.

// CentOS7 기준

vim /etc/docker/daemon.json
// daemon.json 내용

{
    "data-root": "<도커 데이터를 저장할 디렉토리 경로>"
}

daemon.json 작성 완료했다면 docker 서비스를 재시작한다.

// docker 정지
# systemctl stop docker

// 데몬 리로드
# systemctl daemon-reload

// docker 시작
# systemctl start docker

이와 같이 data-root를 지정해주고 docker 데몬을 재시작해주면 해당 디렉토리에 자동으로 도커 데이터 디렉토리들이 생성되었을 것이다. 

만약 원래 가지고 있던 도커 데이터를 사용하고 싶다면 /var/lib/docker 안에 있는 데이터들을 해당 디렉토리로 옮겨주면 된다. data-root를 다른 디렉토리로 지정했다면 더이상 /var/lib/docker 경로를 사용하지 않으므로 /var/lib/docker 안의 데이터들은 지워도 된다.

위의 셋팅을 모두 완료했다면, 이제부터는 지정한 디렉토리 경로로 이미지라든지, 컨테이너라든지 모든 도커 데이터를 해당 경로에 저장한다. 

따라서 추후 도커 데이터를 백업할 일이 있다면 이것을 백업하면 되고, 복원한다면 도커 설치 후 daemon.json의 data-root를 변경하여 도커 데이터가 저장된 디렉토리를 잡아주면 된다.


로컬 환경에 Docker 저장소 구축하기

Docker의 공식 저장소인 Docker Hub에는 Ubuntu나 CentOS와 같은 Linux 배포판의 기본 기능을 제공하는 공식 베이스 이미지나 여러 뜻있는 사람들이 작성한 다양한 용도의 이미지 등이 많이 배포되어 있다.

이러한 Docker 저장소를 Private 네트워크 안에서 구축하려면 Docker Store에 공개되어 있는 공식 이미지인 'registry' 를 사용한다.

hub.docker.com/_/registry?tab=description&page=1&ordering=last_updated

registry는 Version 0 계열과 Version 2 계열, 이 두 개의 버전이 있다. Version 0 계열은 Python, Version 2 계열은 Go 언어로 구축되어 있으며, 이 둘은 호환성이 없으므로 주의해야 한다. 특별한 요구사항이 없는 경우는 Version 2 계열(Go)을 이용하는 것이 좋다.

Docker 저장소는 Private 네트워크 안에서만 이미지를 공개할 수 있다. docker search 명령으로 registry를 확인하면 다음과 같다.

$ docker search registry

NAME                                 DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
registry                             The Docker Registry 2.0 implementation for s…   3121                [OK]                

이 registry를 docker image pull 명령을 사용하여 로컬 환경에 다운로드한다.

$ docker image pull registry:latest

다운로드한 registry 이미지를 바탕으로 저장소용 컨테이너를 시작한다. 컨테이너를 시작하려면 docker container run 명령을 사용한다.

registry는 5000번 포트를 사용하므로 -p 옵션을 사용하여 포트를 전송한다.

// registry 컨테이너 시작
$ docker container run --restart always -d -p 5000:5000 --name registry registry

// registry 컨테이너 확인
$ docker container ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
123458abrukf        registry            "/entrypoint.sh /etc…"   12 seconds ago      Up 11 seconds       0.0.0.0:5000->5000/tcp   registry

이것으로 private 저장소 구축이 완료되었다.


Docker 이미지 업로드

업로드하기 위한 이미지를 만들려면 다음과 같은 Dockerfile을 만든다. 샘플에서는 Jupyter Notebook의 베이스 이미지에 Numpy / Scipy / Sympy / Matplotlib 라는 4개의 라이브러리를 설치하고 있다.

# Base Image
FROM jupyter/base-notebook

# Maintainer
LABEL maintainer "scii"

# Configure environment
ENV CONDA_DIR=/opt/conda \
    NB_USER="scii"

# Install Jupyter Notebook and Hub
RUN conda install --quiet --yes \
    'numpy' \
    'scipy' \
    'sympy' \
    'matplotlib' \
    && conda clean -tipsy \
    && fix-permissions ${CONDA_DIR}

# Install Sample Notebook
COPY sample_notebook/CavityFlow_with_Navier-Stokes.ipynb /home/${NB_USER}

이 Dockerfile을 다음의 명령으로 빌드하여 docker-science 라는 이름의 이미지를 만든다.

$ docker build -t docker-science .

private 네트워크 안의 Docker 저장소에 업로드하려면 다음 규칙을 사용하여 이미지에 태그를 붙여야 한다.

// 태그 이름 (Docker 저장소)

docker image tag [로컬의 이미지명] [업로드할 저장소의 주소:포트 번호]/[이미지명]

예를 들어 로컬에 작성한 'docker-science' 라는 이름의 이미지를 localhost의 5000번 포트에서 작동하는 도커 저장소에 'docker-jupyter' 라는 이름으로 업로드하고 싶다면 다음과 같이 설정한다.

// 태그 설정 예
$ docker image tag docker-science localhost:5000/docker-jupyter

$ docker image ls

REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
docker-science                    latest              4372a0be010d        6 minutes ago       873MB
localhost:5000/docker-jupyter     latest              4372a0be010d        6 minutes ago       873MB

docker image ls 명령으로 이미지를 확인하면 'localhost:5000/docker-jupyter' 라는 태그가 붙은 이미지가 만들어진 것을 확인할 수 있다. 그리고 이 이미지의 IMAGE ID는 원래의 'docker-science' 와 똑같다는 것을 알 수 있다. 즉, 실체가 동일한 이미지를 가리킨다는 것이다.

그 다음 이 이미지를 docker image push 명령을 사용하여 private 저장소에 업로드한다.

// 이미지 업로드

$ docker image push localhost:5000/docker-jupyter

이것으로 이미지 업로드가 완료되었으므로 로컬에 저장되어 있는 이미지를 다음의 명령을 사용하여 삭제한다.

$ docker image rm localhost:5000/docker-jupyter
$ docker image rm docker-science

이제 로컬 환경에서는 이미지가 없어지고 localhost의 5000번 포트에서 작동하는 저장소에 이미지가 등록되었다.


Docker 이미지의 다운로드와 작동 확인

private 저장소상에 있는 이미지를 로컬 환경으로 다운로드하려면 docker image pull 명령을 실행한다. 예를 들어 localhost의 5000번 포트에서 작동하는 도커 저장소로부터 'docker-jupyter' 라는 이름의 이미지를 다운로드할 때는 다음의 명령을 실행한다.

// 이미지 다운로드

$ docker image pull localhost:5000/docker-jupyter

다운로드가 끝나면 docker image ls 명령을 사용하여 확인해보자.

$ docker image ls

REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
localhost:5000/docker-jupyter     latest              4372a0be010d        16 minutes ago      873MB

작동 확인을 위해 다음의 명령을 실행하고 private 도커 저장소로부터 다운로드한 이미지를 사용하여 컨테이너를 시작한다.

// 컨테이너 시작

$ docker container run -it -p 8888:8888 localhost:5000/docker-jupyter

브라우저에서 localhost:8888을 접속하면 Jupyter Notebook에 접근할 수 있는 것을 알 수 있다.


이미지 업로드 / 다운로드 중 아래와 같은 오류가 발생한 경우

$ docker image push 172.10.2.10:5000/gitlab-ce

// 오류 메시지
The push refers to repository [172.10.2.10:5000/gitlab-ce]
Get https://172.10.2.10:5000/v2/: http: server gave HTTP reponse to HTTPS client

오류의 원인은?

클라이언트에서 docker push / pull 명령어로 registry의 이미지를 받을 때 기본적으로 클라이언트는 접속을 https로 접속한다. 하지만 현재 registry에 https 프로토콜이 구성되어 있지 않아 발생하는 오류이다.

해결 방법

http 프로토콜에서 이미지를 받을 수 있도록 클라이언트의 /etc/docker/daemon.json 파일을 수정한다.

Step 1. /etc/docker/daemon.json 파일에 아래 내용을 추가한다. (파일이 없을 경우 생성)

{
    "insecure-registries": ["172.10.2.10:5000"]
}

Step 2. 내용 추가 후 docker 데몬을 재시작한다.

# systemctl stop docker
# systemctl daemon-reload
# systemctl start docker

위의 작업을 마치고 다시 push나 pull 명령을 실행해보면 명령이 잘 수행되는 것을 확인할 수 있다.


Docker Registry Dashboard

여기서부터는 GUI를 지원하는 Docker Registry Web을 설치하는 과정이다. registry 컨테이너가 실행중인 server에서 제공하도록 해야 한다.

hub.docker.com/r/hyper/docker-registry-web

 

Docker Hub

 

hub.docker.com

docker-registry-web을 설치하기 위한 yaml 파일 작성

$ cd $HOME/workspace/docker/docker_registry_dashboard
$ vim config.yml
// config.yml 파일의 내용

registry:
  # 설치한 docker private registry
  url: http://172.10.2.10:5000/v2
  # docker registry name
  name: 172.10.2.10:5000
  # docker 권한 부여
  readonly: false
  auth:
    # disable authentication
    enabled: false

container 실행

$ docker container run -it -d --restart always -p 8080:8080 --name <컨테이너명> --link <registry 컨테이너명> -v <작성한 config.yml 경로>:/conf/config.yml:ro hyper/docker-registry-web

// 실제 사용의 예
$ docker containre run -it -d --restart always -p 8080:8080 --name registry-web --link registry -v $HOME/workspace/docker/docker_registry_dashboard/config.yml:/conf/config.yml:ro hyper/docker-registry-web

--restart always 옵션을 붙여서 OS가 재가동되도 docker 데몬이 자동으로 registry-web 컨테이너를 실행하도록하였다.

위의 명령이 완료되면, 서버IP:8080 에 접속해보자. 그러면 아래와 같은 모습을 볼 수 있다.

docker registry web dashboard


Docker Private Registry에 등록된 이미지 제거

이미지 조회

$ curl -X GET [registry address]/v2/_catalog

// 실제 예
$ curl -X GET 172.10.2.10:5000/v2/_catalog

이미지 태그 조회

$ curl -X GET [registry address]/v2/[image name]/tags/list

docker digest 얻기

$ curl -v --slient -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET [registry address]/v2/[image name]/manifests/[tags] | grep Docker-Content-Digest

이미지 삭제

$ curl -v --silient -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE [registry address]/v2/[image name]/manifests/[sha256:]

가비지 콜렉션 실행

$ docker exec -it [registry] bin/registry garbage-collect /etc/docker/registry/config.yml

문제는 이렇게 해도 조회했을 때 이미지가 나타난다...

이럴때는 registry 서버에 접속하여 물리적으로 삭제해주면 해결된다.

// registry 컨테이너 서버 접속
$ docker exec -it [registry] /bin/bash

# cd /var/lib/registry/docker/registry/v2/repositories
# ls
// image 목록이 나온다.

# rm -rf [image]
# exit

이렇게 하면 해당 이미지가 registry에서 말끔하게 지워진다.

Comments