RegistryAdmin 是 Docker 注册表 UI 工具,允许用户管理私有 Docker 注册表的访问和条目。它提供了一个基于 Web 的用户界面,用于管理存储库、图像和用户访问,并允许用户使用任一password
进行身份验证。该项目的主要目标是提供一个高级 API 来管理用户对私有注册表的访问,并根据官方私有 Docker 注册表映像限制用户对特定存储库的操作(例如推送和拉取)。这对于希望对其注册表有更多控制权并希望能够更轻松地管理对其注册表的访问的注册表所有者来说非常有用。
使用 React-Admin 框架和 MUI 组件创建的 Web 用户界面。
pull
/ push
)限制对存储库的访问,用于token
验证方案)RegistryAdmin 是一个与私有 Docker 注册表结合使用的工具,并使用注册表的 V2 API 与其进行通信。它具有 HTTP 端点,用于使用令牌对用户进行身份验证并检查他们的访问权限。为了将RegistryAdmin 与注册表一起使用,必须将注册表配置为支持基于令牌的身份验证。这允许用户根据其身份验证令牌被授予或限制对某些操作(例如pull
或push
)的访问权限。
# in registry config file
...
auth :
token :
realm : https://{registry-admin-host}/api/v1/registry/auth
service : container_registry_service_name
issuer : registry_token_issuer_name
rootcertbundle : /certs/cert.crt # path to certificate bundle
您可以使用htpasswd
身份验证方案,但使用此方法只能管理用户,而不能限制特定用户对存储库的访问。此功能仅在使用基于令牌的身份验证时可用。
为了通过排序、搜索和自动完成等功能增强用户体验,RegistryAdmin 有一个嵌入式存储系统,可以与注册表中的数据同步。这是必要的,以避免注册表 API 公开的搜索 API(目录)的限制,因为搜索功能仅允许使用光标分页,不支持通过存储库条目进行搜索。该应用程序还包括一个内部垃圾收集器,用于检查嵌入式存储中的数据一致性。
要捕捉注册表中的更改,您应该配置要发送到RegistryAdmin应用程序的注册表通知。
# in registry config file
...
notifications :
events :
includereferences : true
endpoints :
- name : ra-listener
disabled : false
url : http://{registry-admin-host}/api/v1/registry/events
headers :
Authorization : [ Basic Y2xpZW50MDg6Y0t1cnNrQWdybzA4 ]
timeout : 1s
threshold : 5
backoff : 3s
ignoredmediatypes :
- application/octet-stream
ignore :
mediatypes :
- application/octet-stream
根据用户角色访问RegistryAdmin UI:
Admin
- 用户读写、存储库访问和条目的完全权限。Manager
- 浏览访问列表和存储库条目的有限权限。User
- 只能浏览指定的存储库条目。RegistryAdmin 作为一个小型独立二进制文件以及 Docker 镜像进行分发。二进制支持多种架构和多种操作系统,包括linux_x86_64、linux_arm64、linux_arm、macos_x86_64、macos_arm64和windows_x86_64。 Docker 镜像支持 linux_x86_64、linux_arm64 和 linux_arm 架构。
最新稳定版本具有 :vX.YZ docker 标签(带有 :latest 别名),当前 master 具有 :master 标签。
首先,您需要在docker-compose文件中或使用命令行标志设置所需的参数。您可以在 _examples 文件夹中找到各种配置示例。
当您将RegistryAdmin作为docker容器启动时,您应该为具有UID 1001
的应用程序文件夹( certs
、 config
、 data
)用户设置权限。要覆盖容器内的 UID,您应该在容器中使用环境变量来启动参数APP_UID
。
chown -R 1001:1001 {root-registry-admin-folder}
hostname
- 定义要包含在用于检查CORS
请求的AllowedOrigins
标头中的主机名或 IP 地址
port
- 定义应用程序用于侦听 HTTP 请求的端口(默认为 80)。注意:如果您将应用程序作为 Docker 容器启动,则只有端口80
和443
会在容器内公开。
store.type
- 定义存储主要数据的存储类型(用户、访问、存储库)。默认( embed
)
Now implement embed storage type only
store.admin_password
- 首次创建存储时覆盖默认管理员密码(默认密码: admin
)store.embed.path
- 定义嵌入存储文件的路径名(默认值: ./data.db
) registry.host
- 使用协议方案前缀定义私有注册表实例的主主机或 IP 地址。
example: host: https://{registry-host}
registry.port
- 私有 docker 注册表实例的端口(默认值: 5000
)registry.auth_type
- 定义身份验证类型token
或basic
(默认值: token
)。issuer
- 检查注册表内部的发行者名称,发行者名称在私有 docker 注册表和RegistryAdmin 中必须相同。service
- 在注册表设置中定义的服务名称,私有 docker 注册表和RegistryAdmin 中的服务名称必须相同。 ❗ 请记住,必须定义token
身份验证类型所需的certs
选项。
registry.certs.path
- 将在其中生成和存储用于令牌签名的证书的根目录registry.certs.key
- 用于令牌签名的私钥路径registry.certs.public_key
- 用于验证令牌签名的公钥的路径registry.certs.ca
- 证书颁发机构捆绑包的路径registry.certs.fqdns
- 需要添加注册表证书的 FQDN 并根据客户端的请求进行检查registry.certs.ip
- IP 地址将添加到证书扩展字段 (SAN)。如果省略证书,可能会发生错误。如果registry.certs.path
有效且目录为空,则会自动生成证书。如果未定义certs
选项,将在用户主目录的子文件夹.registry-certs
中创建证书:
~/.registry-certs/
registry_auth.key
registry_auth.pub
registry_auth_ca.crt
注意:当使用自签名证书时,您应该在客户端主机上配置 Docker 引擎才能使用自签名证书。
# https://docs.docker.com/config/daemon/
# /etc/docker/daemon.json (Linux)
# C:ProgramDatadockerconfigdaemon.json (Windows)
{
...
"insecure-registries": ["{registry-host}:{port}"],
...
}
为注册表令牌生成的证书也可用于 HTTP TLS/SSL。该证书自动添加到受信任的 CA。但如果您使用其他证书进行 HTTPS 访问,则应将其添加到受信任的 CA 池中。对于它使用选项--registry.https-certs
用于定义用于 TLS/SSL 访问的已用证书的路径。 Let's Encrypt 颁发的证书也需要它。另外,您可以定义--registry.https-insecure
选项来跳过对受信任证书的检查,但不推荐。
# in a registry-admin config
registry :
...
certs :
...
https_cert : /{path-to-ssl}/cert.pem
...
请记住,如果您使用auto
ssl 模式,则必须为存储 ACME 缓存定义--ssl.acme-location
选项。然后缓存日期应该在registry
配置中的 LetsEncrypt 选项中定义:
letsencrypt :
cachefile : /path/to/cache-file
email : [email protected]
hosts : [you-registry.domain.org]
仅支持注册表 V2。要将 docker 注册表与令牌身份验证一起使用,您需要将其配置为独立的访问控制管理器,用于其他希望使用单独的访问控制管理器进行身份验证和管理授权的服务托管的资源。要获取有关它的更多信息,请参阅官方文档。
首先,您需要为token
身份验证定义auth
选项,并设置使用RegistryAdmin应用程序生成的特定certificate
和key
。令牌选项必须与RegistryAdmin Registry
定义的选项相同( issuer
、 service
、 cert_ca
)。 RegistryAdmin 应用程序具有公共端点,用于验证用户对注册表的请求,必须在realm
注册表选项中使用该端点。
https://{registry-admin-host}:{port}/api/v1/auth
❗ realm
是IP 地址或主机名RegistryAdmin 实例的选项,docker 客户端必须可以访问该实例,使用它来对私有注册表进行身份验证。
auth :
token :
realm : http://{registry-admin-hostname}/api/v1/registry/auth
service : container_registry
issuer : registry_token_issuer
rootcertbundle : /certs/cert.crt
为了处理注册表事件和触发存储库任务(例如添加新的、更新或删除存储库条目),您应该设置注册表通知选项:
url
- 带有事件端点路径的RegistryAdmin 主机的http(s) url。
在RegistryAdmin 应用程序中对任何启用和注册的用户及其密码Authorization
,以Base64 编码。
notifications :
events :
includereferences : true
endpoints :
- name : ra-listener
disabled : false
url : http://registry-admin/api/v1/registry/events
headers :
Authorization : [Basic YWRtaW46c3VwZXItc2VjcmV0] # encoded in Base64 as 'admin:super-secret'
timeout : 1s
threshold : 5
backoff : 3s
ignoredmediatypes :
- application/octet-stream
ignore :
mediatypes :
- application/octet-stream
使用.htpasswd
文件的basic
选项,不支持限制对特定存储库的访问。要使用basic
身份验证,您需要以下选项:
login
- 用于访问 docker 注册表的用户名password
- 访问 docker 注册表的密码Docker注册表每次验证调用时都会读取.htpasswd
文件,并且在RegistryAdmin中更新或删除用户后不需要重新启动注册表服务
默认情况下,不生成请求日志。可以通过设置--logger.enabled
来打开此功能。日志(自动旋转)具有 Apache 组合日志格式
用户还可以使用--logger.stdout
打开标准输出登录。它不会影响上面的文件日志记录,但会输出一些有关已处理请求的最小信息,如下所示:
127.0.0.1 - - [06/Dec/2022:18:36:34 +0300] "GET /auth/user HTTP/2.0" 200 159
127.0.0.1 - - [06/Dec/2022:18:36:34 +0300] "GET /api/v1/registry/auth HTTP/2.0" 200 198
当RegistryAdmin可以从互联网访问时,您应该最少设置安全规则以防止密码暴力破解。最简单的方法是在 docker 主机上使用fail2ban
服务和访问日志文件。
access.log
# in registry-admin config file
logger :
enabled : true
filename : /var/log/registry-admin/access.log # mount the directory to a docker host folder for get access for fail2ban
max_size : 5M
max_backups : 3
401
和403
auth/z 错误的registry-admin
服务规则创建filter
# /etc/fail2ban/filter.d/registry-admin.conf
[Definition]
failregex = ^<HOST> .+" 40[1,3] d+ .*$
ignoreregex =
fail2ban
操作,因为正常的系统流量传统上是在INPUT
链上遇到的,而 Docker 容器流量是通过FORWARD
链发送的。 # in the /etc/fail2ban/action.d/ directory
sudo cp iptables-common.conf iptables-common-forward.conf
sudo sed -i ' s/INPUT/FORWARD/g ' iptables-common-forward.conf
sudo cp iptables-multiport.conf iptables-multiport-forward.conf
sudo sed -i ' s/iptables-common.conf/iptables-common-forward.conf/g ' iptables-multiport-forward.conf
registry-admin
规则创建jail
# in /etc/fail2ban/jail.local
[registry-admin]
enabled = true
port = http,https # or set your custom port
filter = registry-admin
banaction = iptables-multiport-forward
logpath = /{path-to-logs-mounted-dir}/logs/access.log
maxretry = 5
findtime = 1h
bantime = 1d
每个选项都可以以三种形式提供:命令行、环境键:值对或配置文件( json
或yaml
格式)。命令行选项只有长格式,例如 --hostname=localhost。为每个选项列出的环境键(名称)作为后缀,即 [$HOSTNAME]。
允许使用json
和yml
格式的配置文件
--listen: listen on host:port (127.0.0.1:80/443 without) (default: *) [$RA_LISTEN]
--hostname: Main hostname of service (default: localhost) [$RA_HOST_NAME]
--port: Main web-service port. Default:80 (default: 80) [$RA_PORT]
--config-file: Path to config file [$RA_CONFIG_FILE]
--debug enable the debug mode [$RA_DEBUG]
registry:
--registry.host: Main host or address to docker registry service [$RA_REGISTRY_HOST]
--registry.port: Port which registry accept requests. Default:5000 (default: 5000) [$RA_REGISTRY_PORT]
--registry.auth-type:[basic|token] Type for auth to docker registry service. Available 'basic' and 'token'. Default 'token' (default: token) [$RA_REGISTRY_AUTH_TYPE]
--registry.login: Username is a credential for access to registry service using basic auth type [$RA_REGISTRY_LOGIN]
--registry.password: Password is a credential for access to registry service using basic auth type [$RA_REGISTRY_PASSWORD]
--registry.htpasswd: Path to htpasswd file when basic auth type selected [$RA_REGISTRY_HTPASSWD]
--registry.https-insecure Set https connection to registry insecure [$RA_REGISTRY_HTTPS_INSECURE]
--registry.service: A service name which defined in registry settings [$RA_REGISTRY_SERVICE]
--registry.issuer: A token issuer name which defined in registry settings [$RA_REGISTRY_ISSUER]
--registry.token-ttl: Define registry auth token TTL (in seconds). Default value 60 seconds. [$RA_REGISTRY_TOKEN_TTL]
--registry.gc-interval: Use for define custom time interval for garbage collector execute (minutes), default 1 hours [$RA_REGISTRY_GC_INTERVAL]
certs:
--registry.certs.path: A path to directory where will be stored new self-signed cert,keys and CA files, when 'token' auth type is used [$RA_REGISTRY_CERTS_CERT_PATH]
--registry.certs.key: A path where will be stored new self-signed private key file, when 'token' auth type is used [$RA_REGISTRY_CERTS_KEY_PATH]
--registry.certs.public-key: A path where will be stored new self-signed public key file, when 'token' auth type is used [$RA_REGISTRY_CERTS_PUBLIC_KEY_PATH]
--registry.certs.ca-root: A path where will be stored new CA bundles file, when 'token' auth type is used [$RA_REGISTRY_CERTS_CA_ROOT_PATH]
--registry.certs.fqdn: FQDN(s) for registry certificates [$RA_REGISTRY_CERTS_FQDN]
--registry.certs.ip: Address which appends to certificate SAN (Subject Alternative Name) [$RA_REGISTRY_CERTS_IP]
--registry.https-certs: A path to a HTTPS certificate used for TLS access to registry instance [$RA_REGISTRY_HTTPS_CERT]
auth:
--auth.token-secret: Main secret for auth token sign [$RA_AUTH_TOKEN_SECRET]
--auth.jwt-issuer: Token issuer signature (default: zebox) [$RA_AUTH_ISSUER_NAME]
--auth.jwt-ttl: Define JWT expired timeout (default: 1h) [$RA_AUTH_JWT_TTL]
--auth.cookie-ttl: Define cookies expired timeout (default: 24h) [$RA_AUTH_COOKIE_TTL]
logger:
--logger.stdout enable stdout logging [$RA_LOGGER_STDOUT]
--logger.enabled enable access and error rotated logs [$RA_LOGGER_ENABLED]
--logger.file: location of access log (default: access.log) [$RA_LOGGER_FILE]
--logger.max-size: maximum size before it gets rotated (default: 10M) [$RA_LOGGER_SIZE]
--logger.max-backups: maximum number of old log files to retain (default: 10) [$RA_LOGGER_BACKUPS]
ssl:
--ssl.type:[none|static|auto] ssl (auto) support. Default is 'none' (default: none) [$RA_SSL_TYPE]
--ssl.cert: path to cert.pem file [$RA_SSL_CERT]
--ssl.key: path to key.pem file [$RA_SSL_KEY]
--ssl.acme-location: dir where certificates will be stored by autocert manager (default: ./acme) [$RA_SSL_ACME_LOCATION]
--ssl.acme-email: admin email for certificate notifications [$RA_SSL_ACME_EMAIL]
--ssl.port: Main web-service secure SSL port. Default:443 (default: 443) [$RA_SSL_PORT]
--ssl.http-port: http port for redirect to https and acme challenge test (default: 80) [$RA_SSL_ACME_HTTP_PORT]
--ssl.fqdn: FQDN(s) for ACME certificates [$RA_SSL_ACME_FQDN]
store:
--store.type:[embed] type of storage (default: embed) [$RA_STORE_DB_TYPE]
--store.admin-password: Define password for default admin user when storage create first (default: admin) [$RA_STORE_ADMIN_PASSWORD]
embed:
--store.embed.path: Parent directory for the sqlite files (default: ./data.db) [$RA_STORE_EMBED_DB_PATH]
Help Options:
-? Show this help message
-h, --help Show this help message
frontend
开发,您应该使用定义的环境变量RA_DEV_HOST=http://127.0.0.1:3000
运行RegistryAdmin,以防止浏览器中出现CORS
错误。此外.env.development
必须包含RegistryAdmin 的有效开发主机名。engine
接口的存储实现,可用于扩展支持的存储类型Embed
使用SQLite
数据库并启用所需的CGO
该项目正在积极开发中,在 v1 发布之前可能会发生重大变化。然而,除非有充分的理由,否则我们会尽力不破坏东西。
这个项目的灵感来自于 Umputun 的项目和想法