Docker私有仓库搭建,存储建站镜像
把建站镜像放到自己的服务器上,比每次从公共仓库拉取更稳定,也更适合内网或带宽有限的场景。
本文用 Docker 官方 Registry 镜像搭一个私有仓库,带你完成从启动、配置到推送建站镜像、验证拉取的全过程。
跟着做,你最终会得到一个可用 docker push 和 docker pull 访问的镜像仓库地址。
先分清你的使用场景
私有仓库不是必须品。
如果你只有一台服务器、镜像不多,直接 docker save 打包传输也能用。
但当你需要多台机器共享建站镜像、想让 CI 自动推送、或者不想依赖公网仓库时,私有仓库就更合适。
判断条件可以简单记:需要跨机器复用镜像、需要版本管理、需要控制镜像访问权限,满足任意一条就建议搭建。
本文默认你在 Linux 服务器上操作,已安装 Docker,并且有 root 或 sudo 权限。
启动一个基础版 Registry
Docker Registry 官方镜像名是 registry,默认监听 5000 端口。
先用最简方式跑起来,确认基本可用。
mkdir -p /data/registry
docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v /data/registry:/var/lib/registry \
registry:2
参数说明:-v /data/registry:/var/lib/registry 把镜像数据存到宿主机,容器重建不丢数据;--restart=always 保证开机自启。
启动后检查容器状态:
docker ps | grep registry
curl http://127.0.0.1:5000/v2/
如果返回 {},说明仓库已经正常响应。
这个结果表示基础功能可用,但还没有加密和鉴权,只适合本机或内网测试。
给仓库加上 HTTPS 和登录验证
生产环境不建议用 HTTP 明文传输,也不建议匿名可推。
下面用 Nginx 做反向代理并配置自签或已有证书,同时给 Registry 加 basic auth。
第一步,生成账号密码文件:
mkdir -p /data/registry/auth
docker run --rm --entrypoint htpasswd httpd:2 -Bbn youruser yourpassword > /data/registry/auth/htpasswd
把 youruser 和 yourpassword 换成你自己的。
第二步,准备 Nginx 配置,假设你的域名是 registry.example.com,证书路径按实际填写:
server {
listen 443 ssl;
server_name registry.example.com;
ssl_certificate /etc/nginx/ssl/registry.crt;
ssl_certificate_key /etc/nginx/ssl/registry.key;
client_max_body_size 0;
location / {
auth_basic "Registry";
auth_basic_user_file /data/registry/auth/htpasswd;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
}
}
client_max_body_size 0 很重要,否则推送大镜像时会被 Nginx 拦截。
第三步,重启 Registry 时挂载鉴权文件:
docker rm -f registry
docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v /data/registry:/var/lib/registry \
-v /data/registry/auth:/auth \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM=Registry \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry:2
配置完成后,客户端需要先 docker login registry.example.com 才能推送。
推送和拉取建站镜像
以常见的 Nginx 建站镜像为例。
先给本地镜像打上私有仓库标签,再推送。
docker pull nginx:alpine
docker tag nginx:alpine registry.example.com/nginx:alpine
docker login registry.example.com
docker push registry.example.com/nginx:alpine
推送成功后,在另一台机器上登录同一仓库并拉取:
docker pull registry.example.com/nginx:alpine
docker images | grep registry.example.com
能看到对应镜像就说明仓库读写正常。
如果你想确认仓库里到底存了哪些镜像,可以直接查目录:
ls /data/registry/docker/registry/v2/repositories/
这里列出的就是已经推送上来的镜像名称。
容易踩的几个坑
HTTP 仓库推送失败:Docker 默认要求 HTTPS。
如果坚持用 HTTP,需要在客户端 /etc/docker/daemon.json 中加入 "insecure-registries": ["你的仓库地址:5000"],然后重启 Docker。
推送时提示 blob upload unknown:多数是 Nginx 的 client_max_body_size 没放开,或者代理超时太短。
按上面的配置加上 client_max_body_size 0 再试。
登录报 401:检查 htpasswd 文件路径和容器内挂载路径是否一致,以及 REGISTRY_AUTH_HTPASSWD_PATH 是否写对。
磁盘写满:镜像数据默认存在 /data/registry,长期使用要留意分区容量。
建议单独挂一块数据盘,并定期用 docker exec registry registry garbage-collect /etc/docker/registry/config.yml 清理无用层。
删除镜像不释放空间:Registry 默认只删标签,不删底层数据,必须配合垃圾回收才会真正释放磁盘。
验证与后续维护
功能验证可以分三步:curl -u 用户名:密码 https://registry.example.com/v2/ 返回 {},说明鉴权通过;docker push 无报错,说明写入正常;
换机器 docker pull 成功,说明读取正常。
三条都通过,私有仓库就算搭建完成。
后续维护建议关注三件事:定期备份 /data/registry 目录,关注磁盘使用率,以及固定 Registry 镜像版本避免自动升级带来兼容问题。
如果之后镜像数量增多,可以考虑迁移到 Harbor 等带图形界面的方案,但初期用 Registry 已经足够稳定。