Docker Registry를 기반으로 한 사설 이미지 저장소에 프록시 서버(Spring Boot)를 구성하고, RESTful API 및 Docker CLI를 통해 다음 기능을 제공합니다:
- 이미지 등록(push) / 다운로드(pull)
- 이미지 및 태그 목록 조회
- 특정 태그 또는 이미지 전체 삭제
- 사용자 인증 (Basic Auth 기반)
- 감사 로그 기록 및 사용자/이미지별 조회
- 프론트엔드 없이 REST API 기반
- 사용자 요청 → Spring Proxy Server → Docker Registry
- 이미지 메타/레이어 프록시 요청 + DB 감사 로그 기록
- OS: Ubuntu 22.04
- Java: 21
- Spring Boot: 3.2+
- Docker: 28.0.4
- Docker Compose: v2.x
sudo apt update
sudo apt install -y docker.io docker-compose openjdk-21-jdk
sudo vim /etc/docker/daemon.json{
"insecure-registries": ["localhost:5000", "localhost:8080"]
}sudo systemctl restart docker
sudo usermod -aG docker $USER
newgrp docker
git clone https://github.com/MAYFIFTH99/docker-registry.git
cd docker-registry
chmod +x ./gradlew
./gradlew build
docker-compose up -d
docker login localhost:8080
# 아이디: test / 비밀번호: 1234POST /api/users: 사용자 생성GET /api/users: 전체 사용자 조회DELETE /api/users/{username}: 사용자 삭제- 인증은
htpasswd기반 Basic Auth
GET /api/images: 전체 이미지 목록 조회 (filter쿼리 지원)GET /api/images/{name}/tags: 특정 이미지의 태그 조회DELETE /api/images/{name}: 이미지 전체 삭제 (모든 태그 삭제)DELETE /api/images/{name}/tags/{tag}: 특정 태그 삭제
HEAD /v2/{name}/manifests/{tag}→ digest 조회DELETE /v2/{name}/manifests/{digest}→ manifest 삭제 → tag 제거 효과
GET /api/audit/user?username=test: 특정 사용자 활동 조회GET /api/audit/image?image=busybox: 특정 이미지 활동 조회
로깅 항목 (총 6개):
VIEW_ALL_IMAGESVIEW_TAGSDELETE_IMAGE_TAGDELETE_IMAGE_ALL_TAGSPUSH_IMAGEPULL_IMAGE
스프링 AOP 기반으로 서비스 계층 메서드 실행 후 자동 기록 사용자명은 Basic Auth에서 추출하거나 없을 경우 anonymous
curl -X GET 'http://localhost:8080/api/users'
curl -X POST 'http://localhost:8080/api/users?username=minseok&password=minseok' \
-H 'Authorization: Basic dGVzdDoxMjM0'
curl -X DELETE 'http://localhost:8080/api/users/minseok' \
-H 'Authorization: Basic dGVzdDoxMjM0'curl -X GET 'http://localhost:8080/api/images' \
-H 'Authorization: Basic dGVzdDoxMjM0'
curl -X GET 'http://localhost:8080/api/images?filter=alpine' \
-H 'Authorization: Basic dGVzdDoxMjM0'
curl -X GET 'http://localhost:8080/api/images/busybox/tags' \
-H 'Authorization: Basic dGVzdDoxMjM0'
curl -X DELETE 'http://localhost:8080/api/images/busybox' \
-H 'Authorization: Basic dGVzdDoxMjM0'
curl -X DELETE 'http://localhost:8080/api/images/busybox/tags/latest' \
-H 'Authorization: Basic dGVzdDoxMjM0'curl -X GET 'http://localhost:8080/api/audit/user?username=test' \
-H 'Authorization: Basic dGVzdDoxMjM0'
curl -X GET 'http://localhost:8080/api/audit/image?image=busybox' \
-H 'Authorization: Basic dGVzdDoxMjM0'docker login localhost:8080
docker push localhost:8080/alpine:latest
docker pull localhost:8080/alpine:latestdocker-registry/
├── docker-compose.yml
├── Dockerfile
├── src/
│ └── main/
│ └── java/
│ └── opensource/
│ └── dockerregistry/
│ └── backend/
│ ├── aop/
│ │ └── AuditLogAspect.java
│ ├── config/
│ │ ├── RestTemplateConfig.java
│ │ ├── SecurityConfig.java
│ │ └── SwaggerConfig.java
│ ├── controller/
│ │ ├── AuditLogController.java
│ │ ├── ImageController.java
│ │ ├── RegistryProxyController.java
│ │ └── UserController.java
│ ├── dto/
│ │ ├── AuditLogRequestDto.java
│ │ ├── DeleteTagsResponse.java
│ │ ├── ImageActivityResponse.java
│ │ ├── TagListResponse.java
│ │ └── UserActivityResponse.java
│ ├── entity/
│ │ └── AuditLogEntity.java
│ ├── repository/
│ │ └── AuditLogRepository.java
│ ├── service/
│ │ ├── AuditLogService.java
│ │ ├── HtpasswdUserDetailsService.java
│ │ ├── ImageService.java
│ │ └── UserService.java
│ ├── util/
│ │ └── UserUtils.java
│ └── DockerRegistryApplication.java




