웹사이트 검색

Rocky Linux 8에서 개인 Docker 레지스트리를 설정하는 방법


이 페이지에서

  1. 전제 조건
  2. 1단계 - 방화벽 구성\n
  3. 2단계 - Docker 및 Docker Compose 설치
  4. 3단계 - Docker 레지스트리 구성
    1. 사용자 디렉토리 생성
    2. Amazon S3 버킷 생성
    3. Docker Compose 파일 만들기
    4. 인증 설정

    1. Dhparam 파일을 컨테이너에 복사

    조직에서 일하고 있고 빠른 배포를 위해 Docker 이미지를 사내에 유지하려는 경우 개인 Docker 리포지토리를 호스팅하는 것이 완벽합니다. 프라이빗 도커 레지스트리를 사용하면 이미지 배포 파이프라인을 소유하고 이미지 저장 및 배포를 보다 엄격하게 제어할 수 있습니다. 레지스트리를 CI/CD 시스템과 통합하여 작업 흐름을 개선할 수 있습니다.

    이 자습서에서는 Amazon S3를 스토리지 위치로 사용하여 Rocky Linux 8 기반 서버에서 개인 Docker 레지스트리를 설정하고 사용하는 방법을 알려줍니다.

    전제 조건

    • Rocky Linux 8이 설치된 두 개의 Linux 서버. 한 서버는 레지스트리 호스트 역할을 하고 다른 서버는 호스트에서 요청을 보내고 이미지를 받는 클라이언트로 사용됩니다.\n
    • 호스트 서버를 가리키는 등록된 도메인 이름. 튜토리얼에서는 registry.example.com을 사용할 것입니다.\n
    • 두 시스템 모두에서 sudo 권한을 가진 루트가 아닌 사용자.\n

    1단계 - 방화벽 구성

    첫 번째 단계는 방화벽을 구성하는 것입니다. Rocky Linux는 Firewalld Firewall을 사용합니다. 방화벽 상태를 확인하십시오.

    $ sudo firewall-cmd --state
    running
    

    방화벽은 다른 영역에서 작동하며 공개 영역은 우리가 사용할 기본 영역입니다. 방화벽에서 활성화된 모든 서비스와 포트를 나열합니다.

    $ sudo firewall-cmd --permanent --list-services
    

    다음 출력이 표시되어야 합니다.

    cockpit dhcpv6-client ssh
    

    HTTP 및 HTTPS 포트를 허용합니다.

    $ sudo firewall-cmd --permanent --add-service=http
    $ sudo firewall-cmd --permanent --add-service=https
    

    방화벽의 상태를 다시 확인하십시오.

    $ sudo firewall-cmd --permanent --list-services
    

    비슷한 출력이 표시되어야 합니다.

    cockpit dhcpv6-client http https ssh
    

    변경 사항을 적용하려면 방화벽을 다시 로드하십시오.

    $ sudo firewall-cmd --reload
    

    2단계 - Docker 및 Docker Compose 설치

    이 단계는 서버와 클라이언트 시스템 모두에서 필요합니다.

    공식 Docker 저장소를 설치합니다.

    $ sudo dnf install yum-utils
    $ sudo yum-config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo
    

    도커를 설치합니다.

    $ sudo dnf install docker-ce docker-ce-cli containerd.io
    

    Docker 데몬을 활성화하고 실행합니다.

    $ sudo systemctl enable docker --now
    

    sudo를 사용하여 Docker 명령을 실행하지 않도록 시스템 사용자를 Docker 그룹에 추가하십시오.

    $ sudo usermod -aG docker $(whoami)
    

    변경 사항을 적용하려면 로그아웃 후 서버에 다시 로그인하십시오.

    Docker Compose의 안정적인 최신 릴리스를 다운로드하여 설치합니다.

    $ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    

    다운로드한 바이너리 파일에 실행 권한을 적용합니다.

    $ sudo chmod +x /usr/local/bin/docker-compose
    

    Docker-compose Bash Completion 스크립트를 설치합니다.

    $ sudo curl \
        -L https://raw.githubusercontent.com/docker/compose/1.29.2/contrib/completion/bash/docker-compose \
        -o /etc/bash_completion.d/docker-compose
    

    bash 완료가 작동하도록 프로필 설정을 다시 로드합니다.

    $ source ~/.bashrc
    

    3단계 - Docker 레지스트리 구성

    사용자 디렉토리 생성

    레지스트리 구성을 위한 디렉터리를 만듭니다.

    $ mkdir ~/docker-registry
    

    docker-registry 디렉터리로 전환합니다.

    $ cd ~/docker-registry
    

    HTTP 인증 암호, Nginx 구성 파일 및 SSL 인증서를 저장할 디렉터리를 만듭니다.

    $ mkdir auth
    

    Nginx 로그를 저장할 다른 디렉터리를 만듭니다.

    $ mkdir logs
    

    Amazon S3 버킷 생성

    레지스트리 데이터와 이미지를 서버에 저장하거나 클라우드 호스팅 서비스를 사용할 수 있습니다. 자습서에서는 Amazon S3 클라우드 서비스를 사용합니다.

    다음 단계는 몇 가지 중요한 설정으로 구성 파일을 설정하는 것입니다. 이러한 설정은 docker-compose.yml 파일에서도 정의할 수 있지만 별도의 파일이 있는 것이 훨씬 좋습니다.

    다음 설정으로 버킷을 생성합니다.

    • ACL을 비활성화해야 합니다.\n
    • 버킷에 대한 공개 액세스를 비활성화해야 합니다.\n
    • 버킷 버전 관리를 비활성화해야 합니다.\n
    • Amazon S3 관리 키를 사용하여 버킷 암호화를 활성화합니다. (SSE-S3)
    • 객체 잠금을 비활성화해야 합니다.\n

    다음 정책으로 IAM 사용자를 생성합니다.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "s3:ListBucket",
            "s3:GetBucketLocation",
            "s3:ListBucketMultipartUploads"
          ],
          "Resource": "arn:aws:s3:::S3_BUCKET_NAME"
        },
        {
          "Effect": "Allow",
          "Action": [
            "s3:PutObject",
            "s3:GetObject",
            "s3:DeleteObject",
            "s3:ListMultipartUploadParts",
            "s3:AbortMultipartUpload"
          ],
          "Resource": "arn:aws:s3:::S3_BUCKET_NAME/*"
        }
      ]
    }
    

    S3_BUCKET_NAME을 S3 버킷의 이름으로 바꿉니다.

    비밀 키, 비밀 값, 나중에 사용할 버킷의 버킷 리전을 기록해 둡니다.

    Docker Compose 파일 생성

    docker-compose.yml 파일을 만들고 편집을 위해 엽니다.

    $ nano docker-compose.yml
    

    다음 코드를 붙여넣습니다.

    version: '3.3'
    services:
      registry:
        image: registry:2 
        restart: always
        environment:
          - REGISTRY_STORAGE=s3
          - REGISTRY_STORAGE_S3_REGION=us-west-2
          - REGISTRY_STORAGE_S3_BUCKET=hf-docker-registry
          - REGISTRY_STORAGE_S3_ENCRYPT=true
          - REGISTRY_STORAGE_S3_CHUNKSIZE=5242880
          - REGISTRY_STORAGE_S3_SECURE=true
          - REGISTRY_STORAGE_S3_ACCESSKEY=AKIA3FIG4NVFCJ6STMUA
          - REGISTRY_STORAGE_S3_SECRETKEY=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
          - REGISTRY_STORAGE_S3_V4AUTH=true
          - REGISTRY_STORAGE_S3_ROOTDIRECTORY=/image-registry
          - REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=inmemory
          - REGISTRY_HEALTH_STORAGEDRIVER_ENABLED=false
      nginx:  
        image: "nginx:alpine"
        ports:
          - 443:443
        links:
          - registry:registry
        volumes:
          - ./auth:/etc/nginx/conf.d
          - ./auth/nginx.conf:/etc/nginx/nginx.conf:ro
          - ./logs:/var/log/nginx
          - /etc/letsencrypt:/etc/letsencrypt
    

    Ctrl + X를 누르고 메시지가 표시되면 Y를 입력하여 파일을 저장합니다.

    작성 파일에서 설정한 내용을 살펴보겠습니다.

    <시작>

  5. 첫 번째 단계는 허브에서 Docker 레지스트리 버전 2의 최신 이미지를 가져오는 것입니다. 최신 태그는 메이저 버전 업그레이드 시 문제가 발생할 수 있어 사용하지 않습니다. 2로 설정하면 모든 2.x 업데이트를 가져오면서 주요 변경 사항을 도입할 수 있는 다음 주 버전으로 자동 업그레이드되는 것을 방지할 수 있습니다.\n
  6. 레지스트리 컨테이너는 오류 또는 예기치 않은 종료의 경우 항상 다시 시작하도록 설정됩니다.\n
  7. Amazon S3 스토리지에 대한 다양한 환경 변수를 설정했습니다. 빠르게 살펴보겠습니다.
    • REGISTRY_STORAGE는 스토리지 유형을 설정합니다. Amazon S3를 사용하고 있으므로 s3를 선택했습니다.\n
    • REGISTRY_STORAGE_S3_REGION은 S3 버킷의 지역을 설정합니다.\n
    • REGISTRY_STORAGE_S3_BUCKET은 S3 버킷의 이름을 설정합니다.\n
    • REGISTRY_STORAGE_S3_ENCRYPT - 버킷 암호화를 활성화한 경우 true로 설정합니다.\n
    • REGISTRY_STORAGE_S3_CHUNKSIZE는 업로드 청크의 크기를 설정합니다. 5MB(5 * 1024 * 1024)보다 커야 합니다.\n
    • REGISTRY_STORAGE_S3_SECURE - HTTPS를 사용하려는 경우 true로 설정합니다.\n
    • REGISTRY_STORAGE_S3_ACCESSKEY 및 REGISTRY_STORAGE_S3_SECRETKEY - IAM 사용자를 생성한 후 가져온 사용자 자격 증명입니다.\n
    • REGISTRY_STORAGE_S3_V4AUTH - v4 AWS 인증을 사용하는 경우 true로 설정합니다. S3 로그인과 관련된 오류가 발생하면 false로 설정하십시오.\n
    • REGISTRY_STORAGE_S3_ROOTDIRECTORY - 레지스트리 데이터가 저장될 버킷의 루트 디렉토리를 설정합니다.\n
    • REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR - 캐시 위치를 설정합니다. 우리의 경우 메모리에 저장하고 있습니다. Redis를 사용하도록 설정할 수도 있습니다.\n
    • REGISTRY_HEALTH_STORAGEDRIVER_ENABLED - 레지스트리 저장소 상태 검사 서비스를 비활성화하려면 false로 설정합니다. false로 설정하지 않으면 레지스트리에 문제가 발생할 수 있는 버그가 있습니다.\n
  8. Docker 레지스트리는 서버에서 docker에 노출된 포트 5000을 통해 통신합니다.\n
  9. ./auth:/etc/nginx/conf.d 매핑은 모든 Nginxs 설정을 컨테이너에서 사용할 수 있도록 합니다.\n
  10. ./auth/nginx.conf:/etc/nginx/nginx.conf:ro는 읽기 전용 모드에서 시스템의 Nginx 설정 파일을 컨테이너의 파일로 매핑합니다.\n
  11. ./logs:/var/log/nginx를 사용하면 컨테이너의 Nginx 로그 디렉터리에 매핑하여 시스템의 Nginxs 로그에 액세스할 수 있습니다.\n
  12. Docker 레지스트리 설정은 컨테이너의 /etc/docker/registry/config.yml 파일에 저장되며 config.yml 에 매핑되었습니다. 파일을 현재 디렉터리에 저장합니다. 다음 단계에서 만들 것입니다.\n

인증 설정

HTTP 인증을 설정하려면 httpd-tools 패키지를 설치해야 합니다.

$ sudo dnf install httpd-tools

~/docker-registry/auth 디렉터리에 암호 파일을 만듭니다.

$ htpasswd -Bc ~/docker-registry/auth/nginx.htpasswd user1
New password:
Re-type new password:
Adding password for user user1

-c 플래그는 명령에 새 파일을 생성하도록 지시하고 -B 플래그는 Docker에서 지원하는 bcrypt 알고리즘을 사용하도록 지시합니다. user1을 선택한 사용자 이름으로 바꿉니다.

더 많은 사용자를 추가하려면 -c 플래그 없이 명령을 다시 실행하십시오.

$ htpasswd -B ~/docker-registry/auth/registry.password user2

이제 파일이 인증을 위해 레지스트리 컨테이너에 매핑됩니다.

4단계 - SSL 설치

Lets Encrypt를 사용하여 SSL 인증서를 설치하려면 Epel 저장소에서 사용할 수 있는 Certbot 도구를 다운로드해야 합니다.

EPEL 저장소와 Certbot을 설치합니다.

$ sudo dnf install epel-release 
$ sudo dnf install certbot

SSL 인증서를 생성합니다.

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m  -d registry.example.com

위의 명령은 서버의 /etc/letsencrypt/live/registry.example.com 디렉토리에 인증서를 다운로드합니다.

Diffie-Hellman 그룹 인증서를 생성합니다.

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

인증서 갱신을 테스트합니다.

$ sudo certbot renew --dry-run

테스트 실행이 성공하면 인증서가 자동으로 갱신됩니다.

컨테이너에 Dhparam 파일 복사

컨테이너에 매핑될 ~/docker-registry/auth 디렉터리에 Diffie-Hellman 그룹 인증서를 복사합니다.

$ sudo cp /etc/ssl/certs/dhparam.pem ~/docker-registry/auth

5단계 - Nginx 구성

다음 단계는 Nginx 서버를 Docker 레지스트리 서버의 프런트 엔드 프록시로 구성하는 것입니다. Docker 레지스트리는 포트 5000에서 작동하는 내장 서버와 함께 제공됩니다. Nginx 뒤에 배치하겠습니다.

편집을 위해 ~/docker-registry/auth/nginx.conf 파일을 만들고 엽니다.

$ sudo nano ~/docker-registry/auth/nginx.conf

다음 코드를 붙여넣습니다.

events {
    worker_connections  1024;
}

http {

  upstream docker-registry {
    server registry:5000;
  }

  ## Set a variable to help us decide if we need to add the
  ## 'Docker-Distribution-Api-Version' header.
  ## The registry always sets this header.
  ## In the case of nginx performing auth, the header is unset
  ## since nginx is auth-ing before proxying.
  map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
    '' 'registry/2.0';
  }

  server {
    listen 443 ssl http2;
    server_name registry.example.com;

    # SSL
    ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/registry.example.com/chain.pem;

    access_log  /var/log/nginx/registry.access.log;
    error_log   /var/log/nginx/registry.error.log;

    # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
    ssl_session_cache shared:SSL:10m;
    ssl_dhparam /etc/nginx.d/conf.d/dhparam.pem;
    resolver 8.8.8.8;

    # disable any limits to avoid HTTP 413 for large image uploads
    client_max_body_size 0;

    # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486)
    chunked_transfer_encoding on;

    location /v2/ {
      # 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;
      }

      # To add basic authentication to v2 use auth_basic setting.
      auth_basic "Registry realm";
      auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd;

      ## If $docker_distribution_api_version is empty, the header is not added.
      ## See the map directive above where this variable is defined.
      add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;

      proxy_pass                          http://docker-registry;
      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;
    }
  }
}

완료되면 Ctrl + X를 누르고 프롬프트가 표시되면 Y를 입력하여 파일을 저장합니다.

Private Docker Registry에 대한 네트워크 연결을 허용하도록 SELinux를 구성합니다.

$ sudo setsebool -P httpd_can_network_connect on

6단계 - Docker 레지스트리 실행

Docker Registrys 디렉터리로 전환합니다.

$ cd ~/docker-registry

도커 컨테이너를 시작합니다.

$ docker-compose up -d

컨테이너의 상태를 확인합니다.

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                                           NAMES
88d6addc1687   nginx:alpine   "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   docker-registry_nginx_1
2b112edc1c72   registry:2     "/entrypoint.sh /etc…"   5 minutes ago   Up 5 minutes   5000/tcp                                        docker-registry_registry_1

Docker 레지스트리에 로그인합니다.

$ docker login -u=testuser -p=testpassword https://registry.example.com

또한 브라우저에서 https://registry.example.com/v2/ URL을 열면 사용자 이름과 암호를 묻습니다. {}가 있는 빈 페이지가 표시되어야 합니다.

curl을 사용하여 단말기에서 URL을 확인할 수 있습니다.

$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/
Enter host password for user 'testuser':
{}

최신 Ubuntu 도커 이미지를 다운로드합니다.

$ docker pull ubuntu:latest

개인 레지스트리에 대해 이 이미지에 태그를 지정하십시오.

$ docker tag ubuntu:latest registry.example.com/ubunt4

이미지를 레지스트리에 푸시합니다.

$ docker push registry.example.com/ubunt4

푸시가 성공했는지 테스트합니다.

$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/_catalog
Enter host password for user 'testuser':
{"repositories":["ubunt4"]}

메시지가 표시되면 Nginx 인증 비밀번호를 입력하면 레지스트리를 통해 사용 가능한 리포지토리 목록이 표시됩니다.

현재 사용 가능한 Docker 이미지 목록을 확인하십시오.

$ docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
registry                              2         d3241e050fc9   5 days ago    24.2MB
nginx                                 alpine    53722defe627   5 days ago    23.4MB
httpd                                 2         118b6abfbf55   5 days ago    144MB
ubuntu                                latest    ff0fea8310f3   2 weeks ago   72.8MB
registry.nspeaks.xyz/ubunt4       latest    ff0fea8310f3   2 weeks ago   72.8MB

7단계 - 클라이언트 시스템에서 Docker 레지스트리 액세스 및 사용

클라이언트 서버에 로그인하십시오. 1단계에서는 클라이언트 시스템에 Docker를 설치했습니다.

클라이언트 머신에서 프라이빗 Docker 레지스트리에 로그인합니다.

$ docker login -u=testuser -p=testpassword https://registry.example.com

레지스트리에서 Ubuntu 이미지를 가져옵니다.

$ docker pull registry.example.com/ubunt4

클라이언트 시스템의 모든 이미지를 나열합니다.

$ docker images
REPOSITORY                        TAG        IMAGE ID       CREATED         SIZE
registry.nspeaks.xyz/ubunt4   latest     ff0fea8310f3   2 weeks ago     72.8MB

다운로드한 이미지를 사용하여 컨테이너를 생성하고 시작합니다.

$ docker run -it registry.example.com/ubunt4 /bin/bash

Ubuntu 컨테이너 내부의 Shell에 로그인됩니다.

:

다음 명령을 실행하여 Linux 버전을 확인하십시오.

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.4 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

이제 클라이언트 머신에서 Docker 레지스트리를 사용할 수 있습니다.

결론

이것으로 Amazon S3를 스토리지로 사용하는 Rocky Linux 8 기반 서버에서 개인 Docker 레지스트리를 설정하는 방법에 대한 자습서를 마칩니다. 질문이 있으시면 아래 의견에 게시하십시오.