도커 레지스트리 · 10 min read · Oct 05, 2025
우분투 22.04에서 개인 도커 레지스트리 설정하는 방법

조직에서 일하고 있으며 도커 이미지를 내부에 보관하여 빠른 배포를 원한다면, 개인 도커 레포지토리를 호스팅하는 것이 완벽합니다. 개인 도커 레지스트리를 사용하면 이미지 배포 파이프라인을 소유하고 이미지 저장 및 배포에 대한 더 엄격한 제어를 할 수 있습니다. CI/CD 시스템과 레지스트리를 통합하여 작업 흐름을 개선할 수 있습니다.
이 튜토리얼에서는 Amazon S3를 저장 위치로 사용하여 우분투 22.04 서버에서 개인 도커 레지스트리를 설정하고 사용하는 방법을 배웁니다.
전제 조건
- 우분투 22.04가 설치된 두 개의 리눅스 서버. 하나의 서버는 레지스트리 호스트 역할을 하고, 다른 하나는 요청을 보내고 호스트에서 이미지를 받는 클라이언트로 사용됩니다.
- 호스트 서버를 가리키는 등록된 도메인 이름. 튜토리얼에서는
registry.example.com을 사용할 것입니다. - 두 머신 모두에서 sudo 권한이 있는 비루트 사용자.
- 모든 것이 업데이트되었는지 확인하십시오.
$ sudo apt update $ sudo apt upgrade - 시스템에 필요한 몇 가지 패키지. 일부 패키지는 이미 시스템에 설치되어 있을 수 있습니다.
$ sudo apt install wget curl nano software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y
1단계 - 방화벽 구성
첫 번째 단계는 방화벽을 구성하는 것입니다. 우분투는 기본적으로 ufw(간단한 방화벽)를 제공합니다.
방화벽이 실행 중인지 확인하십시오.
$ sudo ufw status다음과 같은 출력이 표시되어야 합니다.
Status: inactiveSSH 포트를 허용하여 방화벽이 활성화될 때 현재 연결이 끊어지지 않도록 합니다.
$ sudo ufw allow OpenSSHHTTP 및 HTTPS 포트도 허용합니다.
$ sudo ufw allow http
$ sudo ufw allow https방화벽을 활성화합니다.
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup방화벽 상태를 다시 확인하십시오.
$ sudo ufw status유사한 출력을 볼 수 있어야 합니다.
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
443 ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)2단계 - 도커 및 도커 컴포즈 설치
이 단계는 서버와 클라이언트 머신 모두에서 필요합니다.
우분투 22.04는 구버전의 도커를 기본으로 제공합니다. 최신 버전을 설치하려면 먼저 도커 GPG 키를 가져옵니다.
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg도커 레포지토리 파일을 생성합니다.
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null시스템 레포지토리 목록을 업데이트합니다.
$ sudo apt update최신 버전의 도커를 설치합니다.
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin실행 중인지 확인합니다.
$ sudo systemctl status docker
? docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2023-04-13 09:37:09 UTC; 3min 47s ago
TriggeredBy: ? docker.socket
Docs: https://docs.docker.com
Main PID: 2106 (dockerd)
Tasks: 7
Memory: 26.0M
CPU: 267ms
CGroup: /system.slice/docker.service
??2106 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock기본적으로 도커는 루트 권한이 필요합니다. docker 명령을 실행할 때마다 sudo를 사용하지 않으려면 사용자 이름을 docker 그룹에 추가하십시오.
$ sudo usermod -aG docker $(whoami)이 변경 사항을 활성화하려면 서버에서 로그아웃한 후 동일한 사용자로 다시 로그인해야 합니다. 또는 다음 명령을 사용할 수 있습니다.
$ su - ${USER}사용자가 도커 그룹에 추가되었는지 확인합니다.
$ groups
navjot wheel docker3단계 - 도커 레지스트리 구성
사용자 디렉토리 생성
레지스트리 구성을 위한 디렉토리를 생성합니다.
$ mkdir ~/docker-registrydocker-registry 디렉토리로 이동합니다.
$ cd ~/docker-registryHTTP 인증 비밀번호, Nginx 구성 파일 및 SSL 인증서를 저장할 디렉토리를 생성합니다.
$ mkdir authNginx 로그를 저장할 또 다른 디렉토리를 생성합니다.
$ mkdir logsAmazon S3 버킷 생성
레지스트리 데이터와 이미지를 서버에 저장하거나 클라우드 호스팅 서비스를 사용할 수 있습니다. 튜토리얼에서는 Amazon S3 클라우드 서비스를 사용할 것입니다.
다음 단계는 몇 가지 중요한 설정으로 구성 파일을 설정하는 것입니다. 이러한 설정은 docker-compose.yml 파일에서도 정의할 수 있지만 별도의 파일을 갖는 것이 훨씬 좋습니다.
다음 설정으로 버킷을 생성합니다.
- ACL은 비활성화해야 합니다.
- 버킷에 대한 공개 액세스는 비활성화해야 합니다.
- 버킷 버전 관리는 비활성화해야 합니다.
- Amazon S3 관리 키를 사용하여 버킷 암호화를 활성화합니다. (SSE-S3)
- 객체 잠금은 비활성화해야 합니다.
다음 정책으로 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.yml 파일을 생성하고 편집을 위해 엽니다.
$ nano docker-compose.yml다음 코드를 붙여넣습니다.
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=AKIA3FIG4NVFNXKQXMSJ
- 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를 입력합니다.
컴포즈 파일에서 설정한 내용을 살펴보겠습니다.
- 첫 번째 단계는 허브에서 도커 레지스트리 버전 2의 최신 이미지를 가져오는 것입니다. 최신 태그를 사용하지 않는 이유는 주요 버전 업그레이드 시 문제가 발생할 수 있기 때문입니다. 2로 설정하면 모든 2.x 업데이트를 가져오면서 다음 주요 버전으로 자동 업그레이드되는 것을 방지할 수 있습니다. 이는 파괴적인 변경을 초래할 수 있습니다.
- 레지스트리 컨테이너는 실패 또는 예기치 않은 종료 시 항상 재시작되도록 설정되어 있습니다.
- Amazon S3 저장소를 위한 다양한 환경 변수를 설정했습니다. 빠르게 살펴보겠습니다. - REGISTRY_STORAGE는 저장소 유형을 설정합니다. Amazon S3를 사용하므로 s3를 선택했습니다.
- REGISTRY_STORAGE_S3_REGION은 S3 버킷의 지역을 설정합니다.
- REGISTRY_STORAGE_S3_BUCKET은 S3 버킷의 이름을 설정합니다.
- REGISTRY_STORAGE_S3_ENCRYPT - 버킷 암호화를 활성화한 경우 true로 설정합니다.
- REGISTRY_STORAGE_S3_CHUNKSIZE는 업로드 청크의 크기를 설정합니다. 5MB(5 1024 1024)보다 커야 합니다.
- REGISTRY_STORAGE_S3_SECURE - HTTPS를 사용할 경우 true로 설정합니다.
- REGISTRY_STORAGE_S3_ACCESSKEY 및 REGISTRY_STORAGE_S3_SECRETKEY - IAM 사용자를 생성한 후 가져온 사용자 자격 증명입니다.
- REGISTRY_STORAGE_S3_V4AUTH - AWS 인증의 v4를 사용하는 경우 true로 설정합니다. S3 로그인과 관련된 오류가 발생하는 경우 false로 설정합니다.
- REGISTRY_STORAGE_S3_ROOTDIRECTORY - 레지스트리 데이터가 저장될 버킷 내의 루트 디렉토리를 설정합니다.
- REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR - 캐시 위치를 설정합니다. 이 경우 메모리에 저장하고 있습니다. Redis를 사용하도록 설정할 수도 있습니다.
- REGISTRY_HEALTH_STORAGEDRIVER_ENABLED - 레지스트리의 저장소 상태 확인 서비스를 비활성화하려면 false로 설정합니다. 이를 false로 설정하지 않으면 레지스트리에서 문제가 발생할 수 있는 버그가 있습니다.
- 도커 레지스트리는 포트 5000을 통해 통신하며, 이는 서버에서 도커에 노출된 것입니다.
./auth:/etc/nginx/conf.d매핑은 모든 Nginx 설정이 컨테이너에서 사용 가능하도록 보장합니다../auth/nginx.conf:/etc/nginx/nginx.conf:ro는 시스템의 Nginx 설정 파일을 컨테이너의 읽기 전용 모드로 매핑합니다../logs:/var/log/nginx는 컨테이너의 Nginx 로그 디렉토리에 매핑하여 시스템에서 Nginx 로그에 접근할 수 있도록 합니다.- 도커 레지스트리의 설정은 컨테이너 내의
/etc/docker/registry/config.yml파일에 저장되며, 현재 디렉토리의config.yml파일에 매핑됩니다. 이 파일은 다음 단계에서 생성할 것입니다.
인증 설정
HTTP 인증을 설정하려면 httpd-tools 패키지를 설치해야 합니다.
$ sudo apt install apache2-utils -y~/docker-registry/auth 디렉토리에 비밀번호 파일을 생성합니다.
$ htpasswd -Bc ~/docker-registry/auth/nginx.htpasswd user1
New password:
Re-type new password:
Adding password for user user1-c 플래그는 새 파일을 생성하도록 명령에 지시하며, -B 플래그는 도커에서 지원하는 bcrypt 알고리즘을 사용하도록 설정합니다. user1을 원하는 사용자 이름으로 바꿉니다.
더 많은 사용자를 추가하려면 명령을 다시 실행하되 -c 플래그 없이 실행합니다.
$ htpasswd -B ~/docker-registry/auth/registry.password user2이제 파일이 레지스트리 컨테이너에 매핑되어 인증에 사용됩니다.
4단계 - SSL 설치
SSL 인증서를 생성하기 위해 Certbot을 설치해야 합니다. 우분투의 레포지토리를 사용하여 Certbot을 설치하거나 Snapd 도구를 사용하여 최신 버전을 가져올 수 있습니다. 우리는 Snapd 버전을 사용할 것입니다.
우분투 22.04는 기본적으로 Snapd가 설치되어 있습니다. 다음 명령을 실행하여 Snapd 버전이 최신인지 확인합니다.
$ sudo snap install core && sudo snap refresh coreCertbot을 설치합니다.
$ sudo snap install --classic certbot다음 명령을 사용하여 Certbot 명령이 /usr/bin 디렉토리에서 실행될 수 있도록 심볼릭 링크를 생성합니다.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot다음 명령을 실행하여 SSL 인증서를 생성합니다.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d registry.example.com위 명령은 서버의 /etc/letsencrypt/live/registry.example.com 디렉토리에 인증서를 다운로드합니다.
Diffie-Hellman 그룹 인증서를 생성합니다.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096Certbot 갱신 스케줄러 서비스를 확인합니다.
$ sudo systemctl list-timersnext.certbot.renew.service가 실행될 서비스 중 하나로 표시됩니다.
NEXT LEFT LAST PASSED UNIT ACTIVATES
.....
Sun 2023-04-14 00:00:00 UTC 19min left Sat 2023-02-25 18:04:05 UTC n/a snap.certbot.renew.timer snap.certbot.renew.service
Sun 2023-04-14 00:00:20 UTC 19min left Sat 2023-02-25 10:49:23 UTC 14h ago apt-daily-upgrade.timer apt-daily-upgrade.service
Sun 2023-04-14 00:44:06 UTC 3h 22min left Sat 2023-02-25 20:58:06 UTC 7h ago apt-daily.timer apt-daily.serviceSSL 갱신이 잘 작동하는지 확인하기 위해 프로세스를 드라이 런합니다.
$ sudo certbot renew --dry-run오류가 없으면 모든 준비가 완료된 것입니다. 인증서는 자동으로 갱신됩니다.
Dhparam 파일을 컨테이너로 복사
Diffie-Hellman 그룹 인증서를 ~/docker-registry/auth 디렉토리로 복사합니다. 이 디렉토리는 컨테이너에 매핑됩니다.
$ sudo cp /etc/ssl/certs/dhparam.pem ~/docker-registry/auth5단계 - Nginx 구성
다음 단계는 도커 레지스트리 서버의 프론트엔드 프록시로 Nginx 서버를 구성하는 것입니다. 도커 레지스트리는 포트 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/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를 입력하여 파일을 저장합니다.
6단계 - 도커 레지스트리 시작
도커 레지스트리 디렉토리로 이동합니다.
$ cd ~/docker-registry도커 컨테이너를 시작합니다.
$ docker compose up -d컨테이너 상태를 확인합니다.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3328b7e36bb2 nginx:alpine "/docker-entrypoint.…" About a minute ago Up 3 seconds 80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp docker-registry-nginx-1
bf7cdfc0e013 registry:2 "/entrypoint.sh /etc…" About a minute ago Up About a minute 5000/tcp docker-registry-registry-1도커 레지스트리에 로그인합니다.
$ docker login -u=user1 -p=password https://registry.example.com다음과 같은 출력이 표시됩니다.
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/username/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded브라우저에서 https://registry.example.com/v2/ URL을 열면 사용자 이름과 비밀번호를 입력하라는 메시지가 표시됩니다. {}가 있는 빈 페이지를 볼 수 있어야 합니다.
터미널에서 curl을 사용하여 URL을 확인할 수 있습니다.
$ curl -u user1 -X GET https://registry.example.com/v2/
Enter host password for user 'user1':
{}최신 우분투 도커 이미지를 다운로드합니다.
$ docker pull ubuntu:latest이 이미지를 개인 레지스트리에 태그를 붙입니다.
$ docker tag ubuntu:latest registry.example.com/ubuntu2204이미지를 레지스트리에 푸시합니다.
$ docker push registry.example.com/ubuntu2204푸시가 성공했는지 테스트합니다.
$ curl -u user1 -X GET https://registry.example.com/v2/_catalog
Enter host password for user 'user1':
{"repositories":["ubuntu2204"]}프롬프트가 나타나면 Nginx 인증 비밀번호를 입력하면 레지스트리를 통해 사용할 수 있는 리포지토리 목록이 표시됩니다.
자격 증명을 지우기 위해 터미널에서 로그아웃합니다.
$ docker logout https://registry.example.com
Removing login credentials for registry.example.com현재 사용 가능한 도커 이미지 목록을 확인합니다.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry 2 8db46f9d7550 2 weeks ago 24.2MB
nginx alpine 8e75cbc5b25c 2 weeks ago 41MB
ubuntu latest 08d22c0ceb15 5 weeks ago 77.8MB
registry.example.com/ubuntu2204 latest 08d22c0ceb15 5 weeks ago 77.8MB7단계 - 클라이언트 머신에서 도커 레지스트리에 접근하고 사용하기
클라이언트 서버에 로그인합니다. 1단계에서 클라이언트 머신에 도커를 설치했습니다.
클라이언트 머신에서 개인 도커 레지스트리에 로그인합니다.
$ docker login -u=user1 -p=password https://registry.example.com레지스트리에서 우분투 이미지를 가져옵니다.
$ docker pull registry.example.com/ubuntu2204클라이언트 머신에서 모든 이미지를 나열합니다.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.example.com/ubuntu2204 latest 08d22c0ceb15 5 weeks ago 77.8MB다운로드한 이미지를 사용하여 컨테이너를 생성하고 실행합니다.
$ docker run -it registry.example.com/ubuntu2204 /bin/bash우분투 컨테이너 내부의 셸에 로그인됩니다.
root@647899f255db:리눅스 버전을 확인하기 위해 다음 명령을 실행합니다.
root@a2da49fdbea9$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.2 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.2 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
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"
UBUNTU_CODENAME=jammy이제 클라이언트 머신에서 도커 레지스트리를 사용할 수 있습니다.
결론
이로써 Amazon S3를 저장소로 사용하는 우분투 22.04 서버에서 개인 도커 레지스트리를 설정하는 튜토리얼이 마무리되었습니다. 질문이 있으시면 아래 댓글로 남겨주세요.
새 게시물을 받은 편지함에서 받기
스팸은 없습니다. 언제든지 구독 해지 가능합니다.