docker private registry

docker private registry

docker를 주로 사용하는 개발자분이라면 한번쯤은 docker hub를 사용하여 public images를 주로 사용하거나, 직접 이미지를 만들어서 사용해보았을 것이다.
docker hub와 같은 공개된 이미지 사용이아닌, 나만의 docker hub를 구축하는 방법에 대해 소개하려한다.
회사내부 서비스를 개발하거나, 공개되어선 안될 이미지를 나만의 저장소에 보관하고있다가 필요할때 사용할수있는 아주 유용한 방법이다.
docker 에서는 이런 저장소를 registry라고 표현하며 어떻게 docker private registry를 구축하는지 알아보자.

ssl

docker private registry는 보안상 http를 지원하지않는다. local에서 단순히 테스트용도로 사용한다면 문제없지만, 인증관련하여 remote docker private registry에 접근하고자하면 http로는 불가능하다.
따라서 https 를 사용하기위한 ssl을 생성하자 .
필자는 이전포스트 vagrant 로 환경구성한 centos 2대의 가상환경으로 구성, 테스트를 진행하였다.
사설 ssl을 사용해도 무방하지만, 필자는 self signed ssl을 을 사용할것이기에 다음과 같이 생성하였다 .

1
2
3
4
5
6
7
$ mkdir -p ~/docker-registry/cert
$ cd ~/docker-registry/cert
$ openssl genrsa -des3 -out server.key 2048
$ openssl req -new -key server.key -out server.csr
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
$ cp server.key server.key.origin
$ openssl rsa -in server.key.origin -out server.key

필자는 다음과 같이 진행하였다 .

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
32
33
34
35
36
37
38
39
40
$ openssl genrsa -des3 -out server.key 2048
Generating RSA private key, 2048 bit long modulus
..+++
............................................................+++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
$ openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:setyourmindpark
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@server1 cert]# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd/CN=setyourmindpark
Getting Private key
Enter pass phrase for server.key:
[root@server1 cert]# ls
server.crt server.csr server.key
[root@server1 cert]# cp server.key server.key.origin
[root@server1 cert]# openssl rsa -in server.key.origin -out server.key
Enter pass phrase for server.key.origin:
writing RSA key
[root@server1 cert]#

여기서 반드시 짚고 넘어가야할 점은 전자서명 파일 생성시 기입하게 되는 정보중
Common Name (eg, your name or your server’s hostname) []:
해당정보를 반드시 registry에서 사용하게될 도메인 name명과 같아야한다는 점이다.
필자는 setyourmindpark로 기입하였다.

전자서명 시스템 업데이트

docker private registry에 로그인하려면 로그인하는 시스템에서 docker private registry를 구성할때 사용한 ssl server.crt 전자서명 시스템을 업데이트해야한다.
docker private registry를 구축한 현재의 서버에서도 당연히 로그인을 할것이기에 update를 해준다.
( remote client 에서 해당 docker private registry를 사용하려면 당연히 현재의 작업을 똑같이 수행햐주어야한다 . )
참고해야할 점은 시스템에따라 전자서명 update하는 방식이 조금씩은 다르다는 점이다 .

ubuntu

1
2
3
$ cp ~/docker-registry/cert/server.crt /usr/share/ca-certificates/
$ echo server.crt >> /etc/ca-certificates.conf
$ update-ca-certificates

centos

1
2
$ cp ~/docker-registry/cert/server.crt /etc/pki/ca-trust/source/anchors/
$ update-ca-trust

mac os ( client local 개발 환경시 )

1
$ security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/docker-registry/cert/server.crt

마지막으로 docker를 재시작한다

1
$ service docker restart

docker private registry login password

docker private registry에서 사용할 인증정보 ( username과 password ) 를 생성한다.

1
2
3
4
5
$ mkdir -p ~/docker-registry/auth
$ cd ~/docker-registry/auth
$ docker run \
--entrypoint htpasswd \
registry -Bbn setyourmindpark 0000 > htpasswd

필자는 username setyourmindpark
password 0000로 생성하였다.
사용하고자하는 인증정보를 기입하면 되겠다.

execute docker private registry

ssl과 , 인증정보를 생성하였으니 이제 docker registry를 container로 실행시켜보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ mkdir -p ~/docker-registry/volume
$ docker run -d \
-p 5000:5000 \
--restart=always \
--name registry \
-v ~/docker-registry/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data \
-v ~/docker-registry/volume:/data \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v ~/docker-registry/cert:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/server.key \
registry

또는 docker-compose를 사용할경우 다음과 같이 docker-compose.yml을 기술하여 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ vi docker-compose.yml
version: '2'
services:
docker-registry:
image: registry
restart: always
ports:
- "5000:5000"
volumes:
- ~/docker-registry/auth:/auth
- ~/docker-registry/cert:/certs
- ~/docker-registry/data:/data
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.crt
- REGISTRY_HTTP_TLS_KEY=/certs/server.key
container_name: registry
$ docker-compose up -d

주의할점은 위에서 차례대로 생성한 ssl 전자서명 과 htpasswd 파일들의 경로를 volume 으로 guest os 에 mount되기에
-v ~/docker-registry/auth:/auth \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v ~/docker-registry/cert:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/server.key \
host os 에 mount 될 경로를 정확히 적어주어야한다. ( -v host os path : guest os path )

host 추가

이제 docker private registry에 login할 dns를 등록하자.
docker private registry에 로그인시 일반 ip 정보로는 로그인할수없기에 이것또한 반드시 수행되어야할 작업이다 .
( remote client 해당 docker private registry를 사용하려면 당연히 현재의 작업을 똑같이 수행햐주어야한다 . )

1
2
$ vi /etc/hosts
10.10.10.11 setyourmindpark

docker private registry login

이제 모든 실제로 docker private registry에 로그인해보자 .

1
2
3
4
$ docker login setyourmindpark:5000
Username (setyourmindpark):
Password:
Login Succeeded

docker private registry custom image push

docker private registry 구축을 완료하였으니 사용하고자하는 이미지를 만들어 push 해보자 .
테스트용도로 간단한 이미지를 만들어서 private registry에 push 한다.

1
2
From setyourmindpark/debian-utf8
CMD ["echo","my private image"]

1
2
3
$ docker build --tag my-private-image .
$ docker tag my-private-image setyourmindpark:5000/my-private-image
$ docker push setyourmindpark:5000/my-private-image

이미지를 build 한후, 생성된 이미지를 tag로 alias준후 최종적으로 registry에 push 한다.

docker private registry image 확인

위에서 my-private-image를 registry에 push하였다.
정상적으로 registry에 push가 되었는지 curl 로 확인해보자.

1
2
$ curl -k -u 'setyourmindpark:0000' -X GET https://setyourmindpark:5000/v2/_catalog
{"repositories":["my-private-image"]}

정상적으로 push가 된것을 확인할수있다.

remote client에서 docker private registry 이용

이제 remote client에서 방금 구축한 docker private registry를 이용하여 이미지 pull 또는 push 하기위해 remote client 설정을 진행한다.
위에서 진행한 docker private registry server를 server1으로 지칭하고,
remote client 를 server2 라고 지칭하도록한다 .
일단 위에서 언급한바와같이 docker private registry가 사용중인 전자서명정보가 똑같이 remote client 에도 존재해야한다.
ftp를 사용하든지, scp를 통해 파일을 client에 파일을 넘겨주도록 한다.
필자는 scp 명령어를 사용하였다.
server1에서 다음 명령어를 사용하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[server1]
$ scp ~/docker-registry/cert/server.crt root@10.10.10.12:[전송받을경로]
[server2]
$ cp server.crt /etc/pki/ca-trust/source/anchors/
$ update-ca-trust
$ vi /etc/hosts
10.10.10.11 setyourmindpark
$ service docker restart
$ docker login setyourmindpark:5000
Username (setyourmindpark):
Password:
Login Succeeded

참고로 필자는 remote client도 centos를 사용하였기에 전자서명 업데이트를 server1에서 update한 방법과 같다.
remote client 가 ubuntu, centos, mac os ( local 개발 환경시 )등은 위의 전자서명 설정 부분에 기술해두었으니 참고하도록한다.
정상적으로 remote docker private registry 에 로그인되었다.

docker private registry image pull and execute

정상적으로 remote docker private registry에 로그인되었다면 아까 만든 my-private-image를 pull 하여 실행해보자

1
2
3
4
5
$ docker pull setyourmindpark:5000/my-private-image
$ docker run --name my-private-image setyourmindpark:5000/my-private-image
my private image
[root@server2 ~]#

견해

docker private registry 를 구축하는 방법에대해서 알아보았다.
개인서버가 없다면 amazone s3에 올리는 방법도 있으니 참고하도록 하자 .
필자는 실 서버가 없기에 vagrant환경 centos 2대로 테스트를 진행하였으며, 서비스가 존재하는 회사나 이미지 버전관리가 필요하다면 docker private registry를 직접 구축하여 사용하는것이 좋을것 같다.

참고사이트

http://longbe00.blogspot.kr/2015/03/docker_55.html
https://docs.docker.com/registry/deploying/#restricting-access
https://docs.docker.com/engine/security/certificates/#creating-the-client-certificates
http://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html