Docker 좀더 활용하기

이재홍 http://www.pyrasis.com 2014.08.02 ~ 2014.09.20

기본 인증 사용하기

Docker 레지스트리에는 로그인 기능이 없습니다. 따라서 Nginx의 기본 인증(Basic Authentication) 기능을 사용해야 합니다. 또한, HTTP 프로토콜에서는 인증을 지원하지 않으므로 반드시 HTTPS 프로토콜을 사용해야 합니다.

먼저 /etc/hosts 파일을 편집하여 테스트용 도메인을 추가합니다. 이 파일은 root 권한으로 수정해야 합니다. 도메인을 구입하지 않았을 때는 이 부분을 반드시 설정해주어야 하며, 도메인을 구입하여 DNS를 설정했다면 이 부분은 건너뛰어도 됩니다.

/etc/hosts

127.0.0.1       localhost
127.0.1.1       ubuntu
<레지스트리 서버 IP 주소>    registry.example.com

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

여러분의 레지스트리 서버 IP 주소를 registry.example.com으로 설정합니다. 이 책에서는 registry.example.com을 기준으로 설명하겠습니다.

이제 SSL 사설 인증서(Self Signed)를 생성하겠습니다. SSL 공인 인증서를 구입했다면 이 부분은 건너뛰어도 됩니다.

다음 명령을 입력하여 개인 키 파일을 생성합니다.

$ openssl genrsa -out server.key 2048

인증서 서명 요청(Certificate signing request) 파일을 생성합니다.

  • Country Name: 국가 코드입니다. 대문자로 KO를 입력합니다.
  • State or Province Name: 주 또는 도입니다. 자신의 상황에 맞게 입력합니다.
  • Locality Name: 도시입니다. 자신의 상황에 맞게 입력합니다.
  • Organization Name: 회사 이름을 입력합니다.
  • Organizational Unit Name: 조직 이름을 입력합니다.
  • Common Name: Docker 레지스트리를 실행하는 서버의 도메인입니다. 이 부분을 정확하게 입력하지 않으면 인증서를 사용해도 로그인할 때 에러가 발생합니다. /etc/hosts 파일에 설정한대로 registry.example.com를 입력합니다.
  • Email Address: 이메일 주소입니다.
$ openssl req -new -key server.key -out server.csr
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) [AU]:KO
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Company
Organizational Unit Name (eg, section) []:Example Company
Common Name (e.g. server FQDN or YOUR name) []:registry.example.com
Email Address []:exampleuser@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:<아무것도 입력하지 않음>
An optional company name []:<아무것도 입력하지 않음>

서버 인증서 파일을 생성합니다.

$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

이제 server.crt 인증서 파일을 시스템에 설치를 해주어야 합니다(인증서 파일을 설치하지 않으려면 --insecure-registry 옵션을 사용해야 합니다. 이 부분은 뒤에 따로 설명하겠습니다).

우분투

$ sudo cp server.crt /usr/share/ca-certificates/
$ echo "server.crt" | sudo tee -a /etc/ca-certificates.conf
$ sudo update-ca-certificates

CentOS

$ sudo cp server.crt /etc/pki/ca-trust/source/anchors/
$ sudo update-ca-trust enable
$ sudo update-ca-trust extract

/etc/hosts에 도메인을 추가하고, 인증서 파일을 설치했으면 Docker 서비스를 재시작합니다. Docker 서비스를 재시작해야 추가된 도메인과 설치된 인증서가 적용됩니다.

$ sudo service docker restart

Docker 레지스트리에 접속할 다른 시스템에도 server.crt 인증서 파일을 복사하여 같은 방식으로 설치를 하고 Docker 서비스를 재시작합니다. 그리고 도메인을 구입하지 않았다면 /etc/hosts에 레지스트리 서버(registry.example.com)의 IP 주소를 설정합니다.

--insecure-registry 옵션
server.crt 인증서 파일을 시스템에 설치하지 않으려면 Docker 데몬을 실행할 때 --insecure-registry 옵션을 사용해야 합니다.

$ sudo docker -d --insecure-registry registry.example.com
  • --insecure-registry 옵션에 Docker 레지스트리의 도메인을 설정합니다. 도메인 여러 개를 설정하려면 --insecure-registry 옵션을 여러 번 사용하면 됩니다.

보통 Docker 데몬을 직접 실행하지 않고 서비스 형태로 실행합니다. 이때는 /etc/init.d/docker 파일의 DOCKER_OPTS 부분을 다음과 같이 설정합니다(이 파일은 root 권한으로 수정해야 합니다).

/etc/init.d/docker

DOCKER_OPTS=--insecure-registry registry.example.com

/etc/init.d/docker 파일을 수정했으면 Docker 서비스를 재시작합니다.

$ sudo service docker restart

Docker 레지스트리에 접속할 다른 시스템에도 같은 방식으로 --insecure-registry 옵션을 사용하여 Docker 데몬을 실행합니다.

이제 사용자 계정과 비밀번호를 저장할 .htpasswd 파일을 생성해야 합니다. 먼저 다음 패키지를 설치합니다.

우분투

$ sudo apt-get install apache2-utils

CentOS

$ sudo yum install httpd-tools

htpasswd 명령으로 .htpasswd 파일을 생성하고 hellouser라는 예제 사용자를 추가합니다. 비밀번호 입력 부분에는 사용할 비빌번호를 입력합니다.

$ htpasswd -c .htpasswd hellouser
New password:<비밀번호 입력>
Re-type new password:<비밀번호 입력>
Adding password for user hellouser

이번에는 Nginx 이미지를 따로 생성하지 않고 공식 이미지를 그대로 사용하겠습니다. 다음 내용을 nginx.conf 파일로 저장합니다.

nginx.conf

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    server {
        listen       443;
        server_name  registry.example.com;

        ssl on;
        ssl_certificate /etc/server.crt;
        ssl_certificate_key /etc/server.key;

        proxy_set_header Host           $http_host;
        proxy_set_header X-Real-IP      $remote_addr;
        proxy_set_header Authorization  "";

        client_max_body_size 0;

        chunked_transfer_encoding on;

        location / {
            proxy_pass          http://docker-registry:5000;
            proxy_set_header    Host  $host;
            proxy_read_timeout  900;

            auth_basic            "Restricted";
            auth_basic_user_file  .htpasswd;
        }
    }
}
  • server_name: Docker 레지스트리 서버의 도메인을 설정합니다. 여기서는 registry.example.com을 설정합니다.
  • ssl_certificate, ssl_certificate_key: /etc/server.crt, /etc/server.key를 설정합니다.
  • proxy_pass: 리버스 프록시 설정입니다. Docker 레지스트리 컨테이너와 포트인 docker-registry:5000을 설정합니다.
  • auth_basic: 인증 설정입니다. “Restricted”를 설정하여 기본 인증을 사용합니다.
  • auth_basic_user_file: 사용자 정보가 저장된 .htpasswd 파일을 설정합니다.

daemon off; 옵션
Nginx 공식 이미지 1.7.5 버전부터는 다음과 같이 Nginx 실행 파일을 실행할 때 옵션에 직접 daemon off;를 설정해줍니다. 따라서 nginx.conf 파일에는 daemon off; 옵션을 넣지 않아도 됩니다.

CMD ["nginx", "-g", "daemon off;"]

다음 명령을 실행하여 Docker 레지스트리 컨테이너를 먼저 생성합니다. 컨테이너의 이름은 nginx.conf 파일에서 설정한 대로 docker-registry로 지정합니다.

$ sudo docker run -d --name docker-registry \
    -v /tmp/registry:/tmp/registry \
    registry:0.8.1
  • Nginx를 통해서 사용자 인증을 하고 이미지를 주고 받을 것이기 때문에 Docker 레지스트리는 5000번 포트를 외부에 노출하지 않습니다.

Nginx 공식 이미지 1.7.5 버전으로 컨테이너를 생성하고 docker-registry 컨테이너와 연결합니다.

$ sudo docker run -d --name nginx-registry \
    -v ~/nginx.conf:/etc/nginx/nginx.conf \
    -v ~/.htpasswd:/etc/nginx/.htpasswd \
    -v ~/server.key:/etc/server.key \
    -v ~/server.crt:/etc/server.crt \
    --link docker-registry:docker-registry \
    -p 443:443 \
    nginx:1.7.5
  • -v 옵션으로 nginx.conf 파일은 컨테이너의 /etc/nginx/nginx.conf로 연결합니다. 마찬가지로 .htpasswd 파일도 /etc/nginx/.htpasswd로 연결합니다. server.key, server.crt 파일은 앞에서 설정한 것처럼 /etc 디렉터리 아래에 연결합니다.
    • 저는 사용자 계정 디렉터리에 설정 파일과 인증서 파일을 생성했으므로 ~/nginx.conf처럼 ~가 붙습니다. 여러분이 생성한 설정 파일과 인증서 파일의 경로를 절대 경로로 지정합니다.
  • --link docker-registry:docker-registry 옵션으로 앞에서 생성한 docker-registry 컨테이너를 docker-registry 별칭으로 연결합니다. 이렇게하면 nginx.confproxy_pass 설정으로 Docker 레지스트리에 트래픽을 보낼 수 있습니다.
  • -p 443:443 옵션으로 443번 포트를 외부에 노출합니다.

docker login 명령으로 https://registry.example.com에 로그인합니다. Username과 Password에는 htpasswd 명령으로 생성한 사용자와 비밀번호를 입력합니다. 이메일은 입력하지 않아도 됩니다.

$ sudo docker login https://registry.example.com
Username: hellouser
Password: <비밀번호 입력>
Email:
Login Succeeded

docker login <Docker 레지스트리 URL> 형식입니다.

주의
도메인 설정이 귀찮다고 그냥 건너뛰고 IP 주소만 사용하면 로그인이 안 됩니다. 인증서에 설정한 도메인과 docker login 명령에 입력한 도메인이 반드시 일치해야 합니다. HTTPS 프로토콜은 IP 주소 접속을 허용하지 않으므로 구입하지 않은 도메인은 /etc/hosts 파일에 등록하여 사용합니다.

이제 앞에서 만든 hello:0.1 이미지를 개인 저장소에 올려보겠습니다.

$ sudo docker tag hello:0.1 registry.example.com/hello:0.1
$ sudo docker push registry.example.com/hello:0.1
The push refers to a repository [registry.example.com/hello] (len: 1)
Sending image list
Pushing repository registry.example.com/hello (1 tags)
511136ea3c5a: Image successfully pushed
bfb8b5a2ad34: Image successfully pushed
c1f3bdbd8355: Image successfully pushed
897578f527ae: Image successfully pushed
9387bcc9826e: Image successfully pushed
809ed259f845: Image successfully pushed
96864a7d2df3: Image successfully pushed
ba3b051655b4: Image successfully pushed
11ae3a0f7f28: Image successfully pushed
e75f421fc19c: Image successfully pushed
507149de4094: Image successfully pushed
ce11bd8322f9: Image successfully pushed
bb5b14a7e9b8: Image successfully pushed
548b98b8a152: Image successfully pushed
e376f7a8e74c: Image successfully pushed
e2626c81818f: Image successfully pushed
7a06b68da607: Image successfully pushed
Pushing tag for rev [7a06b68da607] on {https://registry.example.com/v1/repositories/hello/tags/0.1}

이미지의 태그는 <Docker 레지스트리 URL>/<이미지 이름>:<태그> 형식으로 생성합니다. 우리는 registry.example.com으로 설정했으므로 registry.example.com/hello:0.1이 됩니다.

다른 서버에서는 다음 명령을 실행하여 registry.example.com에 저장된 이미지를 받을 수 있습니다.

$ sudo docker pull registry.example.com/hello:0.1

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

30 November 2014