Skip to content

Commit b063bd2

Browse files
committed
initial implementation
1 parent 0ba7464 commit b063bd2

44 files changed

Lines changed: 8762 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: CI Build and Deploy
2+
3+
on:
4+
push:
5+
6+
permissions:
7+
contents: read
8+
packages: write
9+
id-token: write
10+
11+
jobs:
12+
build_app:
13+
name: Build Go binaries
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v6
18+
19+
- name: Setup Go
20+
uses: actions/setup-go@v6
21+
with:
22+
go-version: '1.25'
23+
24+
- name: Create output dir
25+
run: mkdir -p dist
26+
27+
- name: Build server (linux/amd64)
28+
run: |
29+
mkdir -p dist/linux/amd64
30+
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./dist/linux/amd64/server.exe ./cmd/server
31+
32+
- name: Build server (linux/arm64)
33+
run: |
34+
mkdir -p dist/linux/arm64
35+
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o ./dist/linux/arm64/server.exe ./cmd/server
36+
37+
- name: Upload app binaries
38+
uses: actions/upload-artifact@v6
39+
with:
40+
path: dist
41+
name: dist
42+
43+
deploy_docker:
44+
name: Prepare Docker context and build/push image
45+
runs-on: ubuntu-latest
46+
needs: [build_app]
47+
steps:
48+
- name: Checkout
49+
uses: actions/checkout@v6
50+
51+
- name: Download frontend artifacts
52+
uses: actions/download-artifact@v7
53+
with:
54+
name: dist
55+
path: dist
56+
57+
- name: Login to GHCR
58+
uses: docker/login-action@v2
59+
with:
60+
registry: ghcr.io
61+
username: ${{ github.actor }}
62+
password: ${{ secrets.GITHUB_TOKEN }}
63+
64+
- name: Build and (optionally) push image
65+
uses: docker/build-push-action@v5
66+
with:
67+
context: .
68+
file: dist.Dockerfile
69+
push: ${{ startsWith(github.ref, 'refs/tags/v') }}
70+
cache-from: type=gha
71+
cache-to: type=gha
72+
tags: |
73+
ghcr.io/${{ github.repository }}:${{ github.ref_name }}
74+
platforms: linux/amd64,linux/arm64

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,15 @@ go.work.sum
3030
# Editor/IDE
3131
# .idea/
3232
# .vscode/
33+
34+
# Application binary
35+
docker-cache-server
36+
docker-cache-server-*
37+
38+
# Configuration files (keep example)
39+
config.yaml
40+
config.yml
41+
42+
# Data directory
43+
/var/lib/docker-cache-server/
44+
data/

Dockerfile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
FROM golang:1.23-alpine AS builder
2+
3+
WORKDIR /build
4+
5+
# Copy go mod files
6+
COPY go.mod go.sum ./
7+
RUN go mod download
8+
9+
# Copy source code
10+
COPY . .
11+
12+
# Build binary
13+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o docker-cache-server ./cmd/server
14+
15+
# Final stage
16+
FROM alpine:latest
17+
18+
RUN apk --no-cache add ca-certificates
19+
20+
WORKDIR /app
21+
22+
# Copy binary from builder
23+
COPY --from=builder /build/docker-cache-server .
24+
25+
# Copy example config
26+
COPY config.example.yaml .
27+
28+
# Create data directory
29+
RUN mkdir -p /var/cache/docker-cache-server
30+
31+
# Expose default port
32+
EXPOSE 5000
33+
34+
# Volume for persistent storage
35+
VOLUME ["/var/cache/docker-cache-server"]
36+
37+
ENTRYPOINT ["./docker-cache-server"]
38+
CMD ["--config", "config.example.yaml"]

README.md

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# Docker Cache Server
2+
3+
LRU TTL 기반 자동 삭제를 지원하는 Docker Registry Server 구현체입니다.
4+
5+
## 주요 기능
6+
7+
- ✅ Docker Registry v2 API 완벽 지원 (distribution/distribution 기반)
8+
- ✅ Layer 및 Tag에 대한 LRU (Least Recently Used) TTL 자동 삭제
9+
- ✅ Layer read/write 시 LRU 시간 자동 갱신
10+
- ✅ 주기적 cleanup (기본 1시간마다)
11+
- ✅ Basic 인증 지원 (htpasswd)
12+
- ✅ 유연한 설정 (YAML, 환경 변수, 커맨드 라인 플래그)
13+
- ✅ 라이브러리로 사용 가능한 구조
14+
15+
## 설치
16+
17+
```bash
18+
go get github.com/jc-lab/docker-cache-server
19+
```
20+
21+
## 빠른 시작
22+
23+
### 1. 설정 파일 생성
24+
25+
[`config.yaml`](config.yaml:1) 파일을 생성합니다:
26+
27+
```yaml
28+
server:
29+
address: "0.0.0.0"
30+
port: 5000
31+
32+
storage:
33+
directory: "/var/cache/docker-cache-server"
34+
35+
auth:
36+
enabled: true
37+
users:
38+
- username: "admin"
39+
password: "admin123"
40+
- username: "user1"
41+
password: "password1"
42+
43+
cache:
44+
ttl: "30d" # 30일 후 자동 삭제
45+
cleanup_interval: "1h" # 1시간마다 cleanup 실행
46+
```
47+
48+
### 2. 서버 실행
49+
50+
```bash
51+
# 설정 파일 사용
52+
./docker-cache-server --config config.yaml
53+
54+
# 커맨드 라인 플래그 사용
55+
./docker-cache-server --server.port=5000 --cache.ttl=720h
56+
57+
# 환경 변수 사용
58+
export DCS_SERVER_PORT=5000
59+
export DCS_CACHE_TTL=720h
60+
./docker-cache-server
61+
```
62+
63+
### 3. Docker 클라이언트 설정
64+
65+
```bash
66+
# 로그인
67+
docker login localhost:5000 -u admin -p admin123
68+
69+
# 이미지 push
70+
docker tag myimage:latest localhost:5000/myimage:latest
71+
docker push localhost:5000/myimage:latest
72+
73+
# 이미지 pull
74+
docker pull localhost:5000/myimage:latest
75+
```
76+
77+
## 설정 옵션
78+
79+
### Server
80+
81+
- [`server.address`](config.example.yaml:4): 바인드 주소 (기본값: "0.0.0.0")
82+
- [`server.port`](config.example.yaml:5): 포트 번호 (기본값: 5000)
83+
84+
### Storage
85+
86+
- [`storage.directory`](config.example.yaml:8): 저장소 디렉토리 경로 (기본값: "/var/cache/docker-cache-server")
87+
88+
### Auth
89+
90+
- [`auth.enabled`](config.example.yaml:11): 인증 활성화 여부 (기본값: true)
91+
- [`auth.users`](config.example.yaml:12): 사용자 목록 (username, password)
92+
93+
### Cache
94+
95+
- [`cache.ttl`](config.example.yaml:20): 캐시 TTL (예: "30d", "720h", "43200m")
96+
- [`cache.cleanup_interval`](config.example.yaml:22): Cleanup 주기 (예: "1h", "60m")
97+
98+
## 라이브러리로 사용하기
99+
100+
다른 Go 프로젝트에서 라이브러리로 사용할 수 있습니다:
101+
102+
```go
103+
package main
104+
105+
import (
106+
"github.com/jc-lab/docker-cache-server/pkg/config"
107+
"github.com/jc-lab/docker-cache-server/pkg/server"
108+
"github.com/sirupsen/logrus"
109+
)
110+
111+
func main() {
112+
// 설정 생성
113+
cfg := config.DefaultConfig()
114+
cfg.Server.Port = 5000
115+
cfg.Cache.TTL = 30 * 24 * time.Hour // 30 days
116+
117+
// 커스텀 로거
118+
logger := logrus.New()
119+
logger.SetLevel(logrus.DebugLevel)
120+
121+
// 서버 생성 및 시작
122+
srv, err := server.New(&server.Options{
123+
Config: cfg,
124+
Logger: logger,
125+
// 커스텀 인증 함수 (선택사항)
126+
AuthValidator: func(username, password string) bool {
127+
// 여기에 커스텀 인증 로직 구현
128+
return username == "custom" && password == "pass"
129+
},
130+
// Blob 액세스 콜백 (선택사항)
131+
OnBlobAccess: func(digest string, size int64) {
132+
logger.Infof("Blob accessed: %s (size: %d)", digest, size)
133+
},
134+
})
135+
if err != nil {
136+
logger.Fatal(err)
137+
}
138+
139+
if err := srv.Start(); err != nil {
140+
logger.Fatal(err)
141+
}
142+
}
143+
```
144+
145+
## 아키텍처
146+
147+
```
148+
┌─────────────────────────────────────────┐
149+
│ Docker Client │
150+
└──────────────┬──────────────────────────┘
151+
│ Docker Registry v2 API
152+
┌──────────────▼──────────────────────────┐
153+
│ Authentication Middleware │
154+
│ (Basic Auth / htpasswd) │
155+
└──────────────┬──────────────────────────┘
156+
157+
┌──────────────▼──────────────────────────┐
158+
│ Distribution Handlers (gorilla/mux) │
159+
│ - /v2/ │
160+
│ - /v2/{name}/manifests/{reference} │
161+
│ - /v2/{name}/blobs/{digest} │
162+
│ - /v2/{name}/blobs/uploads/ │
163+
└──────────────┬──────────────────────────┘
164+
165+
┌──────────────▼──────────────────────────┐
166+
│ LRU Tracking Driver │
167+
│ (wraps storage driver) │
168+
│ - Records access times │
169+
│ - Updates on read/write │
170+
└──────────────┬──────────────────────────┘
171+
172+
┌──────────────▼──────────────────────────┐
173+
│ Filesystem Storage Driver │
174+
│ (github.com/distribution/distribution)│
175+
└──────────────┬──────────────────────────┘
176+
177+
┌──────────────▼──────────────────────────┐
178+
│ Disk Storage │
179+
│ /var/cache/docker-cache-server/ │
180+
│ ├── docker/ │
181+
│ │ └── registry/v2/ │
182+
│ │ ├── blobs/ │
183+
│ │ └── repositories/ │
184+
│ └── .metadata/ │
185+
│ └── (LRU tracking data) │
186+
└─────────────────────────────────────────┘
187+
188+
┌─────────────────────┐
189+
│ LRU Cleanup Worker │
190+
│ (runs periodically)│
191+
└─────────────────────┘
192+
```
193+
194+
## LRU TTL 작동 방식
195+
196+
1. **Access Tracking**: blob을 읽거나 쓸 때마다 last access 시간이 업데이트됩니다
197+
2. **TTL Check**: cleanup worker가 주기적으로 실행되어 TTL이 지난 blob을 확인합니다
198+
3. **Automatic Deletion**: TTL이 지난 blob은 자동으로 삭제됩니다
199+
4. **Metadata Persistence**: LRU 메타데이터는 디스크에 저장되어 서버 재시작 시에도 유지됩니다
200+
201+
## 설정 우선순위
202+
203+
1. 커맨드 라인 플래그 (최우선)
204+
2. 환경 변수 (`DCS_` prefix)
205+
3. 설정 파일 (YAML)
206+
4. 기본값
207+
208+
예시:
209+
```bash
210+
# 환경 변수로 포트 설정
211+
export DCS_SERVER_PORT=8080
212+
213+
# 플래그가 환경 변수보다 우선
214+
./docker-cache-server --server.port=9000 # 9000 사용됨
215+
```
216+
217+
## 빌드
218+
219+
```bash
220+
# 바이너리 빌드
221+
go build -o docker-cache-server ./cmd/server
222+
223+
# Docker 이미지 빌드
224+
docker build -t docker-cache-server:latest .
225+
```
226+
227+
## 개발
228+
229+
```bash
230+
# 의존성 다운로드
231+
go mod download
232+
233+
# 테스트 실행
234+
go test ./...
235+
236+
# 개발 모드로 실행
237+
go run cmd/server/main.go --config config.example.yaml
238+
```
239+
240+
## 라이선스
241+
242+
Apache License 2.0
243+
244+
## 기여
245+
246+
이 프로젝트는 [github.com/distribution/distribution](https://github.com/distribution/distribution)을 기반으로 합니다.

0 commit comments

Comments
 (0)