在以前使用docker镜像的构建上传过程中一直都是使用的export DECKSER_HOST的方式,但由于暴露了2375端口之后,任何人无需认证即可上传镜像和运行容器,并且挂载宿主机的文件到容器内部,十分危险,docker官方也不推荐这么做,所以我以前的做法是暴露到非2375端口如10086之类的,虽然减少了黑产扫描到的概率,但依然存在很大的风险,但是docker hub能免费使用的私人仓库限制数量为1个

所以使用docker官方registry镜像搭建了一个私有仓库,并且实现了权限认证,在此记录一下整个过程
docker registry 搭建
根据官方文档,直接使用docker compose拉取最新registry镜像,docker-copose.yml配置如下
version: '3.1'
services:
registry:
image: registry
restart: always
container_name: registry
ports:
- 127.0.0.1:9010:5000
volumes:
- /home/docker/registry/registry:/var/lib/registry
将仓库中的镜像文件挂载到宿主机
由于我使用nginx代理,所以SSL配置不需要在registry中配置,通过nginx 反代到127.0.0.1:9010即可
但是需要修改一下nginx的配置
location / {
proxy_pass http://127.0.0.1:9010/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 100m;
}
主要是设置请求大小限制,默认1m修改到100m,不然镜像push的时候会超粗大小限制失败
此时访问 https://xxx.xxx.xxx/v2/_catalog 可以看到镜像列表

但是此时的仓库是没有用户认证的,所有人知道仓库的host之后都可以push和pull
auth认证
官方提供三种方式用户认证

htpasswd -Bbn user password > ~/auth/htpasswd
通过htpasswd生成认证文件
修改docker-compose.yml配置
version: '3.1'
services:
registry:
image: registry
restart: always
container_name: registry
ports:
- 127.0.0.1:9010:5000
volumes:
- /home/docker/registry/registry:/var/lib/registry
- /home/docker/registry/config.yml:/etc/docker/registry/config.yml
- /home/docker/registry/auth:/auth
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
添加认证方式的环境变量,并且将认证文件挂载进容器内
将仓库的配置文件config.yml文件挂载出来,修改为
version: 0.1
log:
fields:
service: registry
storage:
delete:
enabled: true
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
Access-Control-Allow-Origin: ['https://xxx.xxx.xxx']
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Headers: ['Authorization', 'Accept']
Access-Control-Max-Age: [1728000]
Access-Control-Allow-Credentials: [true]
Access-Control-Expose-Headers: ['Docker-Content-Digest']
主要是设置一下delete字段打开,允许调用镜像删除的api,如果有cors的问题也可以设置Access-Control-Allow-Origin来实现跨域访问
此时再访问https://xxx.xxx.xxx/v2/_catalog,可以看到已经提示输入密码

同时,现在执行docker push之前也要先docker login,认证成功后才可以执行push pull等操作
web ui管理页面搭建
这个时候的仓库没有可视化界面,管理起来不方便于是搜索到常用的方案
- https://github.com/Joxit/docker-registry-ui (推荐)
- https://github.com/kwk/docker-registry-frontend (截止2021.8.22的v2版本无法实现删除功能)
- https://github.com/mkuchin/docker-registry-web (最后一次release在2016年)
在docker-compose.yml中添加ui服务如下
version: '3.1'
services:
registry:
image: registry
restart: always
container_name: registry
ports:
- 127.0.0.1:9010:5000
volumes:
- /home/docker/registry/registry:/var/lib/registry
- /home/docker/registry/config.yml:/etc/docker/registry/config.yml
- /home/docker/registry/auth:/auth
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
networks:
- registry-ui-net
# 现阶段无删除功能,不使用该方案
# frontend-registry:
# image: konradkleine/docker-registry-frontend:v2
# restart: always
# container_name: frontend-registry
# ports:
# - 127.0.0.1:8010:80
# environment:
# - ENV_DOCKER_REGISTRY_HOST=107.172.218.23
# - ENV_DOCKER_REGISTRY_PORT=9010
# - ENV_MODE_BROWSE_ONLY=false
ui:
image: joxit/docker-registry-ui:latest
restart: always
container_name: ui-registry
ports:
- 127.0.0.1:8010:80
environment:
- REGISTRY_TITLE=1zilc Private Docker Registry
# - REGISTRY_URL=registry
- NGINX_PROXY_PASS_URL=http://registry:5000
- SINGLE_REGISTRY=false
- DELETE_IMAGES=true
depends_on:
- registry
networks:
- registry-ui-net
networks:
registry-ui-net:
如果之前没有在仓库的config文件或者nginx配置文件中配置跨域访问的头部,则这里要使用NGINX_PROXY_PASS_URL来REGISTRY_URL
并且通过docker的内部网络来访问仓库,即容器名+端口http://registry:5000
此处通过域名访问会报403,原因暂时不太明白
此时再配置一下nginx反代到127.0.0.1:8010,再访问页面

如果是在github actions中push镜像需要在push前登录到docker hub,添加如下配置

至此私人Docker Registry搭建完成