[Docker] Private Registry 구축하기 in k8s


Private Registry를 구축하게 된 이유는 딱 하나였다.

you have reached your pull rate limit

개발을 하면서 Docker의 Base Image들을 Docker hub에서 당겨오는데 이게 limit에 걸린 것 같다.

6시간내에 100번 당겨오면 정책에 걸리는 것 같은데 IP 기반으로 제한되기에, 장비 하나에서 많은 서비스들을 빌드하다보니 이렇게 된 것이다.

그렇다고 계속 IP를 바꾸기도 뭐하고, 6시간동안 가만히 있자니 뭐하고 해서 차라리 Private Registry를 구축해서 Docker Image를 넣어놓고 사용하고자 했다.




Kubernetes에 Registry 구축하기

Registry는 StatefulSet으로 올라면 되게 간단하게 구성할 수 있다.

registry.yaml

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: docker-registry
  namespace: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: docker-registry
  template:
    metadata:
      labels:
        app: docker-registry
    spec:
      containers:
      - name: docker-registry
        image: registry:2.7.1
        ports:
        - containerPort: 5000
        volumeMounts:
        - mountPath: /var/lib/registry
          name: registry-storage
  volumeClaimTemplates:
  - metadata:
      name: registry-storage
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 50Gi
      storageClassName: standard-rwo
---
apiVersion: v1
kind: Service
metadata:
  name: docker-registry
  namespace: registry
spec:
  type: ClusterIP
  selector:
    app: docker-registry
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 5000

위처럼 yaml을 작성하고 kubectl apply로 설치해주면 끝이다.




Registry에 Image Push하기

Registry에 Push하기 전에 먼저 포트포워딩이 필요하다.

kubectl port-forward service/docker-registry 5000:5000 -n registry

docker-registry 서비스를 localhost에 5000 포트로 포워딩한 다음 아래 명령어를 순서대로 작성한다.

docker pull nginx:alpine
docker tag nginx:alpine localhost:5000/nginx:alpine
docker push localhost:5000/nginx:alpine

이렇게 되면 nginx:alpine의 이미지를 docker hub에서 당겨오고 docker-registry에 push하게 된다.




Registry Image 확인하기

apk add curl

registry는 cli를 지원하지 않고 API로 통신하기 때문에 curl을 설치해줘야한다.

curl localhost:5000/v2/_catalog
- 내부 Repo(Image) 리스트

curl localhost:5000/v2/nginx/tags/list
- nginx 이미지의 tag 리스트

다른 API들은 https://github.com/opencontainers/distribution-spec/blob/v1.0.1/spec.md#api 여기에 있는 것 같은데 뭔가 엉성하다…
(registry 공식문서 – https://docs.docker.com/registry/)

그렇기에 다른 블로그들을 참조하는게 더 편해보인다.




Dockerfile 수정하기

변경 전:
FROM nginx:alpine

변경 후:
FROM docker-registry.registry.svc.cluster.local:5000/nginx:alpine

Dockerfile에서 FROM으로 사용했던 Base Image에 docker-registry 서비스 명만 작성해주면 된다.

물론 Ingress를 붙여서 https 도메인을 통한 Pull도 되지만 Kubernetes에서 Pod의 Image로 사용하는 경우라면 서비스명이 더 좋다고 생각한다.

현재는 위처럼 적용해서 limit 자체를 피하고 있는데 추후에는 Cache 적용을 통해 빌드 속도를 개선해봐야겠다.