웹사이트 검색

Ubuntu 18.04에서 개인 Docker 레지스트리를 설정하는 방법


저자는 Write for DOnations 프로그램을 선택했습니다.

소개

프로덕션 및 개발 중에 이미지를 원활하게 업데이트하는 TravisCI.

Docker에는 사용자 지정 Docker 이미지를 호스팅할 수 있는 무료 공용 레지스트리인 Docker Hub도 있지만 이미지를 공개적으로 사용할 수 없도록 해야 하는 상황이 있습니다. 이미지에는 일반적으로 응용 프로그램을 실행하는 데 필요한 모든 코드가 포함되어 있으므로 독점 소프트웨어를 사용할 때는 개인 레지스트리를 사용하는 것이 좋습니다.

이 자습서에서는 개인 Docker 레지스트리를 설정하고 보호합니다. Docker Compose를 사용하여 Docker 애플리케이션을 실행하기 위한 구성을 정의하고 Nginx를 사용하여 HTTPS에서 실행 중인 Docker 컨테이너로 서버 트래픽을 전달합니다. 이 자습서를 완료하면 사용자 지정 Docker 이미지를 개인 레지스트리에 푸시하고 원격 서버에서 이미지를 안전하게 가져올 수 있습니다.

전제 조건

이 가이드를 시작하기 전에 다음이 필요합니다.

  • 루트가 아닌 sudo 사용자 및 방화벽을 포함하여 Ubuntu 18.04 초기 서버 설정 가이드에 따라 설정된 두 개의 Ubuntu 18.04 서버. 한 서버는 개인 Docker 레지스트리를 호스팅하고 다른 서버는 클라이언트 서버가 됩니다.
  • Ubuntu 18.04에 Docker-Compose를 설치하는 방법 자습서에 따라 두 서버에 Docker 및 Docker-Compose를 설치했습니다. Docker Compose를 설치하려면 이 자습서의 첫 번째 단계만 완료하면 됩니다. 이 자습서에서는 필수 구성 요소의 일부로 Docker를 설치하는 방법을 설명합니다.
  • Ubuntu 18.04에 Nginx를 설치하는 방법에 따라 개인 Docker 레지스트리 서버에 Nginx를 설치했습니다.
  • Let's Encrypt로 Nginx를 보호하는 방법에 따라 비공개 Docker 레지스트리용 서버에서 Let's Encrypt로 Nginx를 보호합니다. 4단계에서 HTTP에서 HTTPS로 모든 트래픽을 리디렉션해야 합니다.
  • 개인 Docker 레지스트리에 사용 중인 서버로 확인되는 도메인 이름입니다. 이를 Let’s Encrypt 전제 조건의 일부로 설정합니다.

1단계 - Docker 레지스트리 설치 및 구성

Docker 명령줄 도구는 하나 또는 두 개의 Docker 컨테이너를 시작하고 관리하는 데 유용하지만 전체 배포를 위해서는 Docker 컨테이너 내에서 실행되는 대부분의 애플리케이션이 병렬로 실행되는 다른 구성 요소가 필요합니다. 예를 들어, 많은 웹 애플리케이션은 애플리케이션 코드를 제공하는 Nginx와 같은 웹 서버, PHP와 같은 해석된 스크립팅 언어, MySQL과 같은 데이터베이스 서버로 구성됩니다.

Docker Compose를 사용하면 하나의 .yml 파일을 작성하여 각 컨테이너의 구성 및 컨테이너가 서로 통신하는 데 필요한 정보를 설정할 수 있습니다. 그런 다음 docker-compose 명령줄 도구를 사용하여 애플리케이션을 구성하는 모든 구성 요소에 명령을 실행할 수 있습니다.

Docker Registry는 그 자체로 여러 구성 요소가 있는 애플리케이션이므로 Docker Compose를 사용하여 구성을 관리합니다. 레지스트리 인스턴스를 시작하려면 docker-compose.yml 파일을 설정하여 레지스트리가 데이터를 저장할 위치를 정의합니다.

개인 Docker 레지스트리를 호스팅하기 위해 생성한 서버에서 docker-registry 디렉토리를 생성하고 이 디렉토리로 이동한 후 다음 명령을 사용하여 data 하위 폴더를 생성할 수 있습니다. :

  1. mkdir ~/docker-registry && cd $_
  2. mkdir data

텍스트 편집기를 사용하여 docker-compose.yml 구성 파일을 만듭니다.

  1. nano docker-compose.yml

Docker 레지스트리의 기본 구성을 설명하는 다음 콘텐츠를 파일에 추가합니다.

version: '3'

services:
  registry:
    image: registry:2
    ports:
    - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./data:/data

environment 섹션은 /data 경로를 사용하여 Docker 레지스트리 컨테이너에 환경 변수를 설정합니다. Docker Registry 애플리케이션은 시작할 때 이 환경 변수를 확인하고 결과적으로 데이터를 /data 폴더에 저장하기 시작합니다.

그러나 volumes: - ./data:/data 줄을 포함했기 때문에 Docker는 해당 컨테이너의 /data 디렉터리를 /data에 매핑하기 시작합니다. 는 레지스트리 서버에 있습니다. 최종 결과는 Docker Registry의 데이터가 모두 레지스트리 서버의 ~/docker-registry/data에 저장된다는 것입니다.

구성 5000:5000이 있는 ports 섹션은 Docker가 서버의 포트 5000을 포트 5000에 매핑하도록 지시합니다. 실행 중인 컨테이너에서 이를 통해 서버의 포트 5000에 요청을 보내고 요청을 레지스트리 응용 프로그램으로 전달할 수 있습니다.

이제 Docker Compose를 시작하여 설정을 확인할 수 있습니다.

  1. docker-compose up

Docker가 Docker 자체 레지스트리에서 Docker 레지스트리 이미지를 다운로드하는 것을 보여주는 다운로드 막대가 출력에 표시됩니다. 1~2분 내에 다음과 유사한 출력이 표시됩니다(버전은 다를 수 있음).

Output of docker-compose up
Starting docker-registry_registry_1 ... done Attaching to docker-registry_registry_1 registry_1 | time="2018-11-06T18:43:09Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="redis not configured" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="Starting upload purge in 20m0s" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2 registry_1 | time="2018-11-06T18:43:09Z" level=info msg="listening on [::]:5000" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2

이 자습서의 뒷부분에서 제공된 HTTP 비밀 없음 경고 메시지를 해결할 것입니다. 출력에는 컨테이너가 시작되고 있음이 표시됩니다. 출력의 마지막 줄은 포트 5000에서 성공적으로 수신을 시작했음을 보여줍니다.

기본적으로 Docker Compose는 입력을 대기하므로 CTRL+C를 눌러 Docker 레지스트리 컨테이너를 종료합니다.

포트 5000에서 수신하는 전체 Docker 레지스트리를 설정했습니다. 이 시점에서 레지스트리를 수동으로 불러오지 않으면 레지스트리가 시작되지 않습니다. 또한 Docker Registry에는 인증 메커니즘이 내장되어 있지 않으므로 현재는 안전하지 않으며 완전히 공개되어 있습니다. 다음 단계에서는 이러한 보안 문제를 해결합니다.

2단계 - Nginx 포트 포워딩 설정

Nginx를 사용하여 Docker 레지스트리 서버에 HTTPS가 이미 설정되어 있으므로 이제 Nginx에서 포트 5000으로 포트 전달을 설정할 수 있습니다. 이 단계를 완료하면 example.com에서 직접 레지스트리에 액세스할 수 있습니다.

Let's Encrypt로 Nginx를 보호하는 방법 전제 조건의 일부로 서버 구성이 포함된 /etc/nginx/sites-available/example.com 파일을 이미 설정했습니다. .

텍스트 편집기로 이 파일을 엽니다.

  1. sudo nano /etc/nginx/sites-available/example.com

기존 location 줄을 찾습니다. 다음과 같이 표시됩니다.

...
location / {
  ...
}
...

레지스트리가 실행될 포트 5000으로 트래픽을 전달해야 합니다. 또한 각 요청 및 응답과 함께 서버에서 추가 정보를 제공하는 레지스트리에 대한 요청에 헤더를 추가하려고 합니다. location 섹션의 콘텐츠를 삭제하고 해당 섹션에 다음 콘텐츠를 추가합니다.

...
location / {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    proxy_pass                          http://localhost:5000;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
}
...

$http_user_agent 섹션은 클라이언트의 Docker 버전이 1.5 이상인지 확인하고 UserAgentGo<가 아닌지 확인합니다. /코드> 응용 프로그램입니다. 레지스트리 버전 2.0을 사용하고 있으므로 이전 클라이언트는 지원되지 않습니다. 자세한 내용은 Docker의 레지스트리 Nginx 가이드에서 nginx 헤더 구성을 찾을 수 있습니다.

파일을 저장하고 종료합니다. Nginx를 다시 시작하여 변경 사항을 적용합니다.

  1. sudo service nginx restart

레지스트리를 실행하여 Nginx가 포트 5000으로 트래픽을 전달하는지 확인할 수 있습니다.

  1. cd ~/docker-registry
  2. docker-compose up

브라우저 창에서 다음 URL을 엽니다.

https://example.com/v2

빈 JSON 개체가 표시되거나 다음과 같습니다.

{}

터미널에 다음과 유사한 출력이 표시됩니다.

Output of docker-compose up
registry_1 | time="2018-11-07T17:57:42Z" level=info msg="response completed" go.version=go1.7.6 http.request.host=cornellappdev.com http.request.id=a8f5984e-15e3-4946-9c40-d71f8557652f http.request.method=GET http.request.remoteaddr=128.84.125.58 http.request.uri="/v2/" http.request.useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.125995ms http.response.status=200 http.response.written=2 instance.id=3093e5ab-5715-42bc-808e-73f310848860 version=v2.6.2 registry_1 | 172.18.0.1 - - [07/Nov/2018:17:57:42 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7"

브라우저에서 요청을 보낸 엔드포인트인 /v2/GET 요청이 이루어진 것을 마지막 줄에서 확인할 수 있습니다. 컨테이너는 포트 전달에서 사용자가 만든 요청을 수신하고 {} 응답을 반환했습니다. 출력의 마지막 줄에 있는 코드 200은 컨테이너가 요청을 성공적으로 처리했음을 의미합니다.

이제 포트 포워딩을 설정했으므로 레지스트리의 보안을 개선할 수 있습니다.

3단계 - 인증 설정

Nginx 프록시 요청을 올바르게 사용하면 이제 HTTP 인증으로 레지스트리를 보호하여 Docker 레지스트리에 액세스할 수 있는 사람을 관리할 수 있습니다. 이를 위해 htpasswd를 사용하여 인증 파일을 만들고 여기에 사용자를 추가합니다. HTTP 인증은 레지스트리에서 사용할 HTTPS 연결을 통해 빠르게 설정하고 보호합니다.

다음을 실행하여 htpasswd 패키지를 설치할 수 있습니다.

  1. sudo apt install apache2-utils

이제 인증 자격 증명을 저장할 디렉터리를 만들고 해당 디렉터리로 변경합니다. $_는 이전 명령의 마지막 인수(이 경우 ~/docker-registry/auth)로 확장됩니다.

  1. mkdir ~/docker-registry/auth && cd $_

다음으로 username을 사용하려는 사용자 이름으로 대체하여 다음과 같이 첫 번째 사용자를 생성합니다. -B 플래그는 기본 암호화보다 더 안전한 bcrypt 암호화를 지정합니다. 프롬프트가 표시되면 비밀번호를 입력하십시오.

  1. htpasswd -Bc registry.password username

참고: 더 많은 사용자를 추가하려면 -c 옵션(c는 만들기용임) 없이 이전 명령을 다시 실행하십시오.

  1. htpasswd registry.password username

다음으로 docker-compose.yml 파일을 편집하여 사용자를 인증하기 위해 만든 파일을 사용하도록 Docker에 지시합니다.

  1. cd ~/docker-registry
  2. nano docker-compose.yml

docker-compose.yml 파일을 편집하여 Docker에 사용자 인증 방법을 알려줌으로써 생성한 auth/ 디렉터리에 대한 환경 변수 및 볼륨을 추가할 수 있습니다. 다음 강조 표시된 콘텐츠를 파일에 추가합니다.

version: '3'

services:
  registry:
    image: registry:2
    ports:
    - "5000:5000"
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./auth:/auth
      - ./data:/data

REGISTRY_AUTH의 경우 사용 중인 인증 체계인 htpasswd를 지정하고 REGISTRY_AUTH_HTPASSWD_PATH를 인증 파일의 경로로 설정했습니다. 마지막으로 REGISTRY_AUTH_HTPASSWD_REALMhtpasswd 영역의 이름을 나타냅니다.

이제 레지스트리를 실행하고 사용자에게 사용자 이름과 암호를 묻는 메시지가 표시되는지 확인하여 인증이 올바르게 작동하는지 확인할 수 있습니다.

  1. docker-compose up

브라우저 창에서 https://example.com/v2를 엽니다.

사용자 이름과 해당 암호를 입력하면 {}가 다시 한 번 표시됩니다. 기본 인증 설정을 확인했습니다. 레지스트리는 올바른 사용자 이름과 비밀번호를 입력한 후에만 결과를 반환했습니다. 이제 레지스트리를 보호했으며 레지스트리를 계속 사용할 수 있습니다.

4단계 — Docker Registry as a Service 시작

시스템이 부팅될 때마다 레지스트리가 시작되는지 확인하려고 합니다. 예상치 못한 시스템 충돌이 있는 경우 서버가 재부팅될 때 레지스트리가 다시 시작되는지 확인하려고 합니다. docker-compose.yml을 엽니다.

  1. nano docker-compose.yml

registry: 아래에 다음 콘텐츠 줄을 추가합니다.

...
  registry:
    restart: always
...

레지스트리를 백그라운드 프로세스로 시작하면 ssh 세션을 종료하고 프로세스를 유지할 수 있습니다.

  1. docker-compose up -d

레지스트리를 백그라운드에서 실행하면 이제 파일 업로드를 위해 Nginx를 준비할 수 있습니다.

5단계 - Nginx용 파일 업로드 크기 늘리기

이미지를 레지스트리에 푸시하기 전에 레지스트리에서 대용량 파일 업로드를 처리할 수 있는지 확인해야 합니다. Docker는 큰 이미지 업로드를 별도의 레이어로 분할하지만 경우에 따라 1GB를 초과할 수 있습니다. 기본적으로 Nginx는 파일 업로드에 대한 제한이 1MB이므로 nginx에 대한 구성 파일을 편집하고 최대 파일 업로드 크기를 2GB<로 설정해야 합니다. /코드>.

  1. sudo nano /etc/nginx/nginx.conf

http 섹션을 찾아 다음 줄을 추가합니다.

...
http {
        client_max_body_size 2000M;
        ...
}
...

마지막으로 Nginx를 다시 시작하여 구성 변경 사항을 적용합니다.

  1. sudo service nginx restart

이제 Nginx 오류 없이 Docker 레지스트리에 큰 이미지를 업로드할 수 있습니다.

6단계 - 개인 Docker 레지스트리에 게시

이제 프라이빗 Docker 레지스트리에 이미지를 게시할 준비가 되었지만 먼저 이미지를 생성해야 합니다. 이 자습서에서는 Docker 허브의 ubuntu 이미지를 기반으로 간단한 이미지를 만듭니다. Docker Hub는 애플리케이션을 빠르게 Dockerize하는 데 활용할 수 있는 미리 구성된 많은 이미지가 있는 공개 호스팅 레지스트리입니다. ubuntu 이미지를 사용하여 레지스트리로 푸시 및 풀링을 테스트합니다.

클라이언트 서버에서 작고 비어 있는 이미지를 생성하여 새 레지스트리에 푸시합니다. -i-t 플래그는 컨테이너에 대한 대화형 셸 액세스를 제공합니다.

  1. docker run -t -i ubuntu /bin/bash

다운로드가 완료되면 Docker 프롬프트 안에 있게 됩니다. root@ 다음의 컨테이너 ID는 다를 수 있습니다. SUCCESS라는 파일을 만들어 파일 시스템을 빠르게 변경합니다. 다음 단계에서 이 파일을 사용하여 게시 프로세스의 성공 여부를 확인할 수 있습니다.

  1. touch /SUCCESS

Docker 컨테이너를 종료합니다.

  1. exit

다음 명령은 이미 실행 중인 이미지와 변경 사항을 기반으로 test-image라는 새 이미지를 만듭니다. 이 경우 /SUCCESS 파일 추가가 새 이미지에 포함됩니다.

변경 사항을 커밋합니다.

  1. docker commit $(docker ps -lq) test-image

이 시점에서 이미지는 로컬에만 존재합니다. 이제 생성한 새 레지스트리로 푸시할 수 있습니다. Docker 레지스트리에 로그인합니다.

  1. docker login https://example.com

이전의 사용자 이름과 해당 암호를 입력합니다. 다음으로 이미지에 푸시하기 위해 개인 레지스트리의 위치로 이미지에 태그를 지정합니다.

  1. docker tag test-image example.com/test-image

새로 태그가 지정된 이미지를 레지스트리에 푸시합니다.

  1. docker push example.com/test-image

출력은 다음과 유사합니다.

Output
The push refers to a repository [example.com/test-image] e3fbbfb44187: Pushed 5f70bf18a086: Pushed a3b5c80a4eba: Pushed 7f18b442972b: Pushed 3ce512daaf78: Pushed 7aae4540b42d: Pushed ...

레지스트리가 사용자 인증을 처리하고 인증된 사용자가 레지스트리에 이미지를 푸시할 수 있도록 허용하는지 확인했습니다. 다음으로 레지스트리에서도 이미지를 가져올 수 있는지 확인합니다.

7단계 — 개인 Docker 레지스트리에서 가져오기

클라이언트 서버에서 이미지 가져오기를 테스트할 수 있도록 레지스트리 서버로 돌아갑니다. 세 번째 서버에서 이를 테스트하는 것도 가능합니다.

이전에 설정한 사용자 이름과 비밀번호로 로그인합니다.

  1. docker login https://example.com

이제 이미지를 가져올 준비가 되었습니다. 이전 단계에서 태그를 지정한 도메인 이름과 이미지 이름을 사용합니다.

  1. docker pull example.com/test-image

Docker가 이미지를 다운로드하고 프롬프트로 돌아갑니다. 레지스트리 서버에서 이미지를 실행하면 이전에 만든 SUCCESS 파일이 있는 것을 볼 수 있습니다.

  1. docker run -it example.com/test-image /bin/bash

bash 셸 내부에 파일을 나열합니다.

  1. ls

이 이미지에 대해 생성한 SUCCESS 파일이 표시됩니다.

SUCCESS  bin  boot  dev  etc  home  lib  lib64  media   mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

사용자가 사용자 정의 이미지를 푸시하고 풀할 수 있는 보안 레지스트리 설정을 완료했습니다.

결론

이 자습서에서는 개인용 Docker 레지스트리를 설정하고 Docker 이미지를 게시했습니다. 소개에서 언급했듯이 프로세스를 설명하는 Docker 자습서를 사용할 수도 있습니다.


판권 소유. © Linux-Console.net • 2019-2024