容器鏡像倉庫是應用容器化部署的必選項,頂級玩家 Dockerhub 由於網絡原因,在國內使用不是很順暢,因此搭建一個企業專屬的私有化鏡像倉庫就成為了企業雲原生轉型的關鍵。現在市面上有很多類似的解決方案,比如 Harbor, GitLab Container Registry, GitHub Container Registry 等,但是這些項目都用到了開源項目 Distribution,這個項目的主要產品就是為使用 OCI Distribution 規範的容器鏡像倉庫提供一個開源的 Registry 實現,因此可以單獨使用此開源項目搭建一個私有化的容器鏡像託管平台。
由於 Distribution 支持將 S3 作為存儲後端,而 RustFS 又是一個 S3 兼容的分佈式對象存儲系統,因此可以將 RustFS 配置為 Distribution 的存儲後端。下面的整個實踐過程。
入門配置
安裝
將 Distribution 和 RustFS 進行容器化部署,整個過程使用三個容器:
- Distribution:託管容器鏡像。依賴 RustFS 和 MC 服務;配置如下:
registry:
depends_on:
- rustfs
- mc
restart: always
image: registry:3
ports:
- 5000:5000
environment:
REGISTRY_STORAGE: s3
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_STORAGE_S3_ACCESSKEY: rustfsadmin
REGISTRY_STORAGE_S3_SECRETKEY: rustfsadmin
REGISTRY_STORAGE_S3_REGION: us-east-1
REGISTRY_STORAGE_S3_REGIONENDPOINT: http://rustfs:9000
REGISTRY_STORAGE_S3_BUCKET: docker-registry
REGISTRY_STORAGE_S3_ROOTDIRECTORY: /var/lib/registry
REGISTRY_STORAGE_S3_FORCEPATHSTYLE: true
REGISTRY_STORAGE_S3_LOGLEVEL: debug
volumes:
- ./auth:/auth
networks:
- rustfs-oci
注意:REGISTRY_AUTH 指定了和容器鏡像倉庫鑑權的方式,本文使用用户名和密碼。使用如下方式生成加密的密碼:
docker run \
--entrypoint htpasswd \
httpd:2 -Bbn testuser testpassword > auth/htpasswd
將生成的 auth/htpasswd 文件掛載到 Registry 容器中即可,後續就能使用 testuser/testpassword 進行倉庫登陸了。
- RustFS:存儲鏡像倉庫數據。配置如下:
rustfs:
image: rustfs/rustfs:1.0.0-alpha.77
container_name: rustfs
hostname: rustfs
environment:
- RUSTFS_VOLUMES=/data
- RUSTFS_ADDRESS=0.0.0.0:9000
- RUSTFS_CONSOLE_ENABLE=true
- RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001
- RUSTFS_ACCESS_KEY=rustfsadmin
- RUSTFS_SECRET_KEY=rustfsadmin
- RUSTFS_OBS_LOGGER_LEVEL=debug
- RUSTFS_OBS_LOG_DIRECTORY=/logs
healthcheck:
test:
[
"CMD",
"sh", "-c",
"curl -f http://localhost:9000/health && curl -f http://localhost:9001/rustfs/console/health"
]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
ports:
- "9000:9000" # API endpoint
- "9001:9001" # Console
networks:
- rustfs-oci
- MC:創建 bucket 以存儲數據。依賴 RustFS 服務;
mc:
depends_on:
- rustfs
image: minio/mc
container_name: mc
networks:
- rustfs-oci
environment:
- AWS_ACCESS_KEY_ID=rustfsadmin
- AWS_SECRET_ACCESS_KEY=rustfsadmin
- AWS_REGION=us-east-1
entrypoint: |
/bin/sh -c "
until (/usr/bin/mc alias set rustfs http://rustfs:9000 rustfsadmin rustfsadmin) do echo '...waiting...' && sleep 1; done;
/usr/bin/mc rm -r --force rustfs/docker-registry;
/usr/bin/mc mb rustfs/docker-registry;
/usr/bin/mc policy set public rustfs/docker-registry;
tail -f /dev/null
"
將上述三個容器的配置寫到 docker-compose.yml 文件中,然後執行:
docker compose up -d
查看服務狀態:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7834dee8cbbf registry:3 "/entrypoint.sh /etc…" 38 minutes ago Up 38 minutes 0.0.0.0:80->5000/tcp, 0.0.0.0:443->5000/tcp, [::]:80->5000/tcp, [::]:443->5000/tcp docker-registry-registry-1
f922568dd11f minio/mc "/bin/sh -c '\nuntil …" About an hour ago Up About an hour mc
bf20a5b2ab4b rustfs/rustfs:1.0.0-alpha.77 "/entrypoint.sh rust…" About an hour ago Up About an hour (healthy) 0.0.0.0:9000-9001->9000-9001/tcp, [::]:9000-9001->9000-9001/tcp rustfs
測試驗證
通過使用 docker 命令登錄容器鏡像倉庫並推送容器鏡像來進行測試。
- 登錄容器鏡像倉庫
docker login localhost:5000
Username: testuser
Password:
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
- 推送鏡像
# 拉取鏡像
docker pull rustfs/rustfs:1.0.0-alpha.77
# tag 鏡像
docker tag rustfs/rustfs:1.0.0-alpha.77 localhost:5000/rustfs:1.0.0-alpha.77
# 推送鏡像
docker push localhost:5000/rustfs:1.0.0-alpha.77
The push refers to repository [localhost:5000/rustfs]
4f4fb700ef54: Pushed
8d10e1ace7fc: Pushed
fcd530aedb30: Pushed
ea6fa4aba595: Pushed
2d35ebdb57d9: Pushed
67d0472105ad: Pushed
09194c842438: Pushed
1.0.0-alpha.77: digest: sha256:88eafb9e9457dbabb08b9e93cfed476f01474e48ec85e7a9038f1f4290380526 size: 1680
i Info → Not all multiplatform-content is present and only the available single-platform image was pushed
sha256:f761246690fdf92fc951c90c12ce4050994c923fb988e3840f072c7d9ee11a63 -> sha256:88eafb9e9457dbabb08b9e93cfed476f01474e48ec85e7a9038f1f4290380526
- RustFS 驗證
在 RustFS 上查看 docker-registry 存儲桶中的內容,以確定鏡像數據被存儲到了 RustFs。
可以看到容器鏡像 localhost:5000/rustfs:1.0.0-alpha.77 的相關數據已經存儲到 RustFS 中了。
進階配置
以上的配置,Distribution Registry 都是通過 HTTP 來提供服務,而在企業生產中,這種方式是不允許的,必須配置 HTTPS。
對於 Distribution Registry 來講,可以通過多種方式進行 HTTPS 配置。比如本地提供 certificate 或者直接使用 Let's encrypt。本文選擇後者。
Distribution Registry 配置 Let's encrypt 會用到如下四個參數:
| 參數 | 是否必須 | 描述 |
|---|---|---|
cachefile |
yes | Let's Encrypt 代理用來緩存數據的文件路徑(絕對路徑)。 |
email |
yes | 註冊 Let's Encrypt 所使用的郵箱地址。 |
hosts |
no | 允許使用 Let’s Encrypt 證書的主機名(域名)列表。 |
directoryurl |
no | 使用 ACME server 的 URL(這個指私有化部署的 ACME Server)。 |
因此配置如下參數即可:
REGISTRY_HTTP_TLS_LETSENCRYPT_CACHEFILE: /auth/acme.json
REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL: email@com
REGISTRY_HTTP_TLS_LETSENCRYPT_HOSTS: '["example.rustfs.com"]'
然後再次執行:
docker compose up -d
在另外一個服務器上驗證即可:
docker login example.rustfs.com
Authenticating with existing credentials... [Username: testuser]
i Info → To login with a different account, run 'docker logout' followed by 'docker login'
Login Succeeded
再次執行前面的鏡像推送和 RustFS 控制枱驗證即可。
後面就可以使用 example.rustfs.com 這個域名對應的鏡像倉庫來託管企業內部的所有容器鏡像了,而且還可以將整個容器鏡像的構建和推送集成到 CI/CD 中。