Rocky Linux 8에서 개인 Docker 레지스트리를 설정하는 방법
이 페이지에서
- 전제 조건
- 1단계 - 방화벽 구성\n
- 2단계 - Docker 및 Docker Compose 설치
- 3단계 - Docker 레지스트리 구성
- 사용자 디렉토리 생성
- Amazon S3 버킷 생성
- Docker Compose 파일 만들기
- 인증 설정
- Dhparam 파일을 컨테이너에 복사
조직에서 일하고 있고 빠른 배포를 위해 Docker 이미지를 사내에 유지하려는 경우 개인 Docker 리포지토리를 호스팅하는 것이 완벽합니다. 프라이빗 도커 레지스트리를 사용하면 이미지 배포 파이프라인을 소유하고 이미지 저장 및 배포를 보다 엄격하게 제어할 수 있습니다. 레지스트리를 CI/CD 시스템과 통합하여 작업 흐름을 개선할 수 있습니다.
이 자습서에서는 Amazon S3를 스토리지 위치로 사용하여 Rocky Linux 8 기반 서버에서 개인 Docker 레지스트리를 설정하고 사용하는 방법을 알려줍니다.
첫 번째 단계는 방화벽을 구성하는 것입니다. 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를 입력하여 파일을 저장합니다.
작성 파일에서 설정한 내용을 살펴보겠습니다.
<시작>
- 첫 번째 단계는 허브에서 Docker 레지스트리 버전 2의 최신 이미지를 가져오는 것입니다. 최신 태그는 메이저 버전 업그레이드 시 문제가 발생할 수 있어 사용하지 않습니다. 2로 설정하면 모든 2.x 업데이트를 가져오면서 주요 변경 사항을 도입할 수 있는 다음 주 버전으로 자동 업그레이드되는 것을 방지할 수 있습니다.\n
- 레지스트리 컨테이너는 오류 또는 예기치 않은 종료의 경우 항상 다시 시작하도록 설정됩니다.\n
- 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
- Docker 레지스트리는 서버에서 docker에 노출된 포트 5000을 통해 통신합니다.\n
-
./auth:/etc/nginx/conf.d
매핑은 모든 Nginxs 설정을 컨테이너에서 사용할 수 있도록 합니다.\n -
./auth/nginx.conf:/etc/nginx/nginx.conf:ro
는 읽기 전용 모드에서 시스템의 Nginx 설정 파일을 컨테이너의 파일로 매핑합니다.\n -
./logs:/var/log/nginx
를 사용하면 컨테이너의 Nginx 로그 디렉터리에 매핑하여 시스템의 Nginxs 로그에 액세스할 수 있습니다.\n - Docker 레지스트리 설정은 컨테이너의
/etc/docker/registry/config.yml
파일에 저장되며config.yml에 매핑되었습니다. code> 파일을 현재 디렉터리에 저장합니다. 다음 단계에서 만들 것입니다.\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 레지스트리를 설정하는 방법에 대한 자습서를 마칩니다. 질문이 있으시면 아래 의견에 게시하십시오.