docker搭建私有仓库registry及harbor

# 简介

在 Docker 中,当我们执行 docker pull xxx 的时候 ,它实际上是从 registry.hub.docker.com 这个地址去查找,这就是Docker公司为我们提供的公共仓库。在工作中,我们不可能把企业项目push到公有仓库进行管理。所以为了更好的管理镜像,Docker不仅提供了一个中央仓库,同时也允许我们搭建本地私有仓库。

  • 本地镜像:在把java程序打包成镜像,输出的镜像的位置就是本地镜像
  • 公有仓库:一个叫docker hub的网站,类似于github,所有人都可以把自己的镜像上传上去,也可以使用别人的镜像
  • 私有仓库:相当于自己建的docker hub,常用于不可公开的(例如公司),或者追求网速(镜像不像代码文件那么小)

# 基础环境安装(docker)

yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的

yum install -y yum-utils device-mapper-persistent-data lvm2
1

配置yum源

将docker的源配置成阿里的;

sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast
1
2
yum repolist  #刷新yum源
1

安装docker-ce与docker-compose

yum install docker-ce  -y  #默认安装最新版本的docker-ce,需要使用指定版本可以使用yum install docker-ce -版本号安装
yum install docker-compose	-y  #安装docker-compose
1
2

启动docker

systemctl start docker	#启动docker服务
systemctl enable docker	#设置docker服务开机启动
1
2

# 部署registry

# 安装启动

# 普通默认方式

docker run -d -p 5000:5000  /opt/registry:/var/lib/registry --restart always --name wdp-hub registry:2.7.1
1
  • -d : 让容器可以后台运行;
  • -p :指定映射端口(前者是宿主机的端口号,后者是容器的端口号);
  • -v :数据挂载(前者是宿主机的目录,后者是容器的目录);
  • --name : 为运行的容器命名;
  • Docker容器的重启策略如下:
    • no:默认策略,在容器退出时不重启容器
    • on- failure:在容器非正常退出时(退出状态非0),才会重启容器
    • on- failure:3 :在容器非正常退出时重启容器,最多重启3次
    • always:在容器退出时总是重启容器
    • unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器

默认情况下,仓库会被创建在容器的/var/lib/registry目录下,可以通过-v参数挂载本地的路径;

脚本封装

register服务的docker启动脚本; restartRegistry.sh

docker stop registry
docker rm registry
docker run -d -p 5000:5000 --name=registry --restart=always \
  --privileged=true \
  --log-driver=none \
  -v /root/registry/registrydata:/var/lib/registry \
  registry:2
1
2
3
4
5
6
7

# 其他参数方式【推荐】

docker run -d -v /data/registory:/var/lib/registry -p 5000:5000 --restart=always --privileged=true --name registry registry:latest
# docker run -itd -v /data/registry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry:latest

sudo mkdir -p /home/wdp-docker-bak/registry && sudo chown -R 1000:1000 /home/wdp-docker-bak/registry
docker run -d -p 5000:5000  /home/wdp-docker-bak/registry:/var/lib/registry --restart always --name wdp-hub registry:2.7.1
1
2
3
4
5
  • -itd:在容器中打开一个伪终端进行交互操作,并在后台运行;
  • -v:把宿主机的/data/registry目录绑定到容器/var/lib/registry目录(这个目录是registry容器中存放镜像文件的目录),来实现数据的持久化;
  • -p:映射端口;访问宿主机的5000端口就访问到registry容器的服务;
  • --restart=always: 这是重启的策略,在容器退出时总是重启容器;
  • --name registry: 创建容器命名为registry

为什么是 /var/lib/registry/ 目录?

仓库默认存放镜像等信息在容器的 /var/lib/registry/docker 目录下,可以进入该目录查看已上传镜像信息,即使私有仓库的容器被误删,再次创建此容器,之前的镜像依然存在。

docker ps 可以看到仓库容器正在运行。进入到/data下,可以看到registory文件夹;

docker exec -it f94d2c317477 /bin/bash

image-20220118192115593

image-20220118174145136

# 检查push及pull

# 以操作hello-world为例子

# 创建镜像及推送

#拉取公共的
docker pull hello-world
#重命名本地镜像名字
docker tag hello-world:latest 10.45.xxx.116:5000/hello-world:latest
#推送本地镜像到私库
docker push 10.45.xxx.116:5000/hello-world:latest
#可能会报错;
1
2
3
4
5
6
7

# http访问权限

原因是docker私有仓库服务器,默认是https协议,所以我们需要进行修改不使用https;

vi /etc/docker/daemon.json #如果没有此文件,请创建
1

添加下面这段代码; 注意这里要个json文件格式,如果报错后面会重启docker失败;

"insecure-registries":["10.45.xxx.116:5000"]
1
{
   "registry-mirrors": ["http://hub-mirror.c.163.com"],
   "insecure-registries": ["10.45.xx.xx:5000","https://host116:4433"]
}     
1
2
3
4

重启docker服务

systemctl daemon-reload
systemctl restart docker
1
2

再次将镜像推送到私有仓库,即可推送成功

docker push 10.45.xxx.116:5000/hello-world:latest
1

# get验证pull部分

  • 查看私有仓库执行此命令:curl -XGET http://ip:端口/v2/_catalog;
  • 获取某个镜像的标签列表:curl -XGEThttp://127.0.0.1:5000/v2/私有仓库镜像名称/tags/list;
  • 也可通浏览器直接访问;
    • http://10.45.xxx.116:5000/v2/_catalog
    • http://10.45.xxx.116:5000/v2/xxx/tags/list
curl -XGET http://10.45.xxx.116:5000/v2/_catalog
# 若成功会返回以下值
#{"repositories":["hello-world","nginxtest"]}
curl http://10.45.xx.116:5000/v2/hello-world/tags/list
#{"name":"hello-world","tags":["latest"]}

# 删除本地重命名的镜像
# docker rmi -f 8652b9f0cb4c 
docker rmi 10.45.xxx.116:5000/hello-world:latest
# 检查镜像
sudo docker images
# 拉取私有库中的镜像
docker pull 10.45.xxx.116:5000/hello-world:latest
# 检查镜像
sudo docker images
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

image-20220121133017081

# 部署harbor【推荐】

包含registry库;

docker 官方提供的私有仓库 registry,用起来虽然简单 ,但在管理的功能上存在不足。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,harbor使用的是官方的docker registry(v2命名是distribution)服务去完成。harbor在docker distribution的基础上增加了一些安全、访问控制、管理的功能以满足企业对于镜像仓库的需求。

Harbor (opens new window) 是一个开源镜像仓库,可通过基于角色的访问控制来保护镜像,新版本的Harbor还增加了扫描镜像中的漏洞并将镜像签名为受信任。

Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境的Registry也是非常必要的。 所以Harbor孕育而生,Harbor是由VMware公司开源的企业级的Docker Registry管理项目,它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。

Harbor组件均以Docker容器方式启动,因此,你可以将其部署在任何支持Docker的Linux发行版上。

img

# 特性

  • **☆ 易于部署:**可通过Docker compose或Helm Chart 部署 Harbor。
  • ***☆* 云原生注册表:**Harbor 支持容器镜像和Helm图表,可作为容器原生运行时和编排平台等云原生环境的注册表。
  • ***☆* 基于角色控制:**用户通过项目访问不同的存储库,并且用户可以对项目下的镜像或Helm图表具有不同的权限。
  • ***☆* 基于策略的复制:**可以使用过滤器基于策略在多个注册表实例之间复制(同步)镜像和图表。
  • ***☆* 镜像删除和垃圾收集:**系统管理员可以运行垃圾收集作业,以便可以删除镜像,并可以定期释放其空间。
  • ***☆* 漏洞扫描:**Harbor会定期扫描映像中的漏洞,并进行策略检查以防止部署易受攻击的映像。
  • ***☆* 公证人:**支持对容器镜像进行签名,以确保真实性和出处。
  • ***☆* 审核:**通过日志跟踪对存储库的所有操作。
  • ***☆* 图形门户:**用户可以轻松浏览,搜索存储库和管理项目。
  • ***☆* 外部集成:**提供RESTful API有助于管理操作,并且易于与外部系统集成。

# 安装compose

部署harbor要依赖; yum install docker-compose

compose 基本命令

# 启动Harbor容器
docker-compose start
# 停止Harbor容器
docker-compose stop
# 重启Harbor容器
docker-compose restart
# 停止并删除Harbor容器,加上-v参数可以同时移除挂载在容器上的目录
docker-compose down
# 创建并启动Harbo容器,参数“-d”表示后台运行命令
docker-compose up -d
1
2
3
4
5
6
7
8
9
10

# 下载harbor安装包并进行解压

# 使用在线安装程序
#wget -P /usr/local wget https://github.com/goharbor/harbor/releases/download/v2.3.2/harbor-online-installer-v2.3.2.tgz
wget https://github.com/goharbor/harbor/releases/download/v2.4.1/harbor-offline-installer-v2.4.1.tgz
tar zxf harbor-offline-installer-v2.4.1.tgz  -C /usr/local/
cd /usr/local
mv harbor/ wdp-harbor/
1
2
3
4
5
6
harbor安装位置 /usr/local/wdp-harbor 暂无
harbor数据目录 /home/wdp-docker-bak/harbor 暂无

# 编写harbor配置文件

配置参数位于安装目录的 harbor.yml 文件中。

# 重命名
cd /usr/local 
# 修改配置文件,根据自己的需求进行修改
cd wdp-harbor
cp harbor.yml.tmpl harbor.yml
# harbor.yml中按需修改或添加如下内容
## 修改hostname
hostname: harbor.test.com #如果是ip的话,直接设置ip;
## 修改admin密码
harbor_admin_password: xxxxxxx
## 暂时关闭https
#https:
  # https port for harbor, default is 443
  #  port: 443
  # The path of cert and key files for nginx
  #  certificate: /your/certificate/path
  # private_key: /your/private/key/path
## 添加禁止用户自注册
self_registration: off
## 设置只有管理员可以创建项目(可选)
# project_creation_restriction: adminonly
## 指定数据目录,若无则手动创建该目录
data_volume: /home/wdp-docker-bak/harbor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# harbor.yml

修改以下内容:

hostname = 192.168.xxx.204 #修改harbor的启动ip,这里需要依据系统ip设置
port: 5000 #harbor的端口,有两个端口,http协议(80)和https协议(443)
harbor_admin_password = xxxx   #修改harbor的admin用户的密码
data_volume: /home/wdp-docker-bak/harbor #修改harbor存储位置
1
2
3
4

一般情况下,我们最少需要配置的内容如下:

  • hostname 需要配置为 127.0.0.1 之外的内容,以提供外部访问,本例中我配置为: docker.soulteary.com
  • https 的配置需要同时配置证书,生产环境中,如果使用 SLB 或者使用其他应用统一提供 SSL 接入,则可以删除。
  • harbor_admin_password 默认密码即可,但是初次使用登陆后台后需要修改密码。
  • data_volume 根据自己实际情况修改宿主机的文件储存地址。

# 必须参数

  • hostname: 目标主机的主机名。它应该是目标计算机的 IP 地址或完全限定的域名(FQDN),例如:172.16.1.30 或 reg.yourdomain.com。不要使用 localhost 或 127.0.0.1 作为主机名。
  • data_volume: Harbor 数据的存储位置
  • harbor_admin_password: 管理员的初始密码。此密码仅在 Harbor 首次启动时生效。请注意,默认用户 名/密码为 admin / Harbor12345
  • database: 与本地数据库相关的配置。
  • password: 默认数据库密码为 root123,应该改为一个安全的生产环境密码。

# 可选参数

  • http: port: 你的 http 的端口号。
  • https: 启用 https 协议。如果启用了秘钥,则必须设置为 https。
    • port: https 的端口号。
    • certificate: SSL 证书的路径,仅在协议设置为 https 时应用。
    • private_key: SSL 密钥的路径,仅在协议设置为 https 时应用。

# 网络端口

img

# 修改docker配置文件

修改docker配置文件,使docker支持harbor

编辑客户机/etc/docker/daemon.json文件

{"insecure-registries":["192.168.100.204:80"]}
1

重启客户机docker服务

systemctl restart docker  #或者(service docker restart) 
1

# 设置Harbor开机启动【要点】

使用vim编辑器编辑配置文件vim /lib/systemd/system/harbor.service并向文件中写入

[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor

[Service]
Type=simple
Restart=on-failure
RestartSec=5

#需要注意harbor的安装位置
ExecStart=/usr/bin/docker-compose -f /usr/local/wdp-harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f /usr/local/wdp-harbor/docker-compose.yml down

[Install]
WantedBy=multi-user.target

#或者修改.yml 中每个的:restart: always;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
systemctl enable harbor #设置harbor开机自启
systemctl start harbor #启动harbor

#临时脚本
cd /usr/local/wdp-harbor
docker-compose up -d
docker-compose down

#查看
docker-compose ps -a
1
2
3
4
5
6
7
8
9
10

# 启动Harbor

# 执行安装脚本
bash ./install.sh
1
2

最终目录结构:

root@harbor:/usr/local/harbor# ll
total 60
drwxr-xr-x  3 root root  4096 Aug 31 06:41 ./
drwxr-xr-x 11 root root  4096 Aug 31 03:27 ../
drwxr-xr-x  3 root root  4096 Aug 31 03:27 common/
-rw-r--r--  1 root root  3361 Aug 18 08:53 common.sh
-rw-r--r--  1 root root  6066 Aug 31 03:34 docker-compose.yml
-rw-r--r--  1 root root  7919 Aug 31 03:34 harbor.yml
-rw-r--r--  1 root root  7840 Aug 18 08:53 harbor.yml.tmpl
-rwxr-xr-x  1 root root  2500 Aug 18 08:53 install.sh*
-rw-r--r--  1 root root 11347 Aug 18 08:53 LICENSE
-rwxr-xr-x  1 root root  1881 Aug 18 08:53 prepare*
1
2
3
4
5
6
7
8
9
10
11
12

# 查看容器的运行状态

root@harbor:/usr/local/harbor# docker-compose ps
      Name                     Command                  State                      Ports                
--------------------------------------------------------------------------------------------------------
harbor-core         /harbor/entrypoint.sh            Up (healthy)                                       
harbor-db           /docker-entrypoint.sh 96 13      Up (healthy)                                       
harbor-jobservice   /harbor/entrypoint.sh            Up (healthy)                                       
harbor-log          /bin/sh -c /usr/local/bin/ ...   Up (healthy)   127.0.0.1:1514->10514/tcp           
harbor-portal       nginx -g daemon off;             Up (healthy)                                       
nginx               nginx -g daemon off;             Up (healthy)   0.0.0.0:80->8080/tcp,:::80->8080/tcp
redis               redis-server /etc/redis.conf     Up (healthy)                                       
registry            /home/harbor/entrypoint.sh       Up (healthy)                                       
registryctl         /home/harbor/start.sh            Up (healthy) 
1
2
3
4
5
6
7
8
9
10
11
12

# 启动注意事项

如果修改harbor.yml,一定要通过install.sh脚本启动;

当修改 harbor.yml 后,我们需要执行 bash prepare,让配置能够得到更新。当然,历史存在的容器 container 也需要清理,除了使用 docker rm 进行清理外,还可以使用 docker system prune 进行清理。

# 注册和创建仓库

访问登录界面了。(用户admin,密码:x x x(在harbor配置文件中可以查看到),新建个项目设置为wdp-test;设置项目仓库为公开模式;

image-20220127192535318

修改tag,及推送;注意要多一次文档目录;

#docker login 10.45.46.xxx:5000 #记得要登录后推送设置;
docker tag SOURCE_IMAGE[:TAG] 10.45.46.xxx:5000/wdp/REPOSITORY[:TAG]
docker push 10.45.xxx.116:5000/wdp/REPOSITORY[:TAG]
docker pull 10.45.xxx.116:5000/wdp/REPOSITORY[:TAG]
1
2
3
4

image-20220127193951504

# 配置https TODO

# 把这三个证书文件复制到docker相应的目录下,注意最后的路径名,要跟上面的保持一致
mkdir -p /etc/docker/certs.d/www.harbor.mobi/
cp www.harbor.mobi.cert /etc/docker/certs.d/www.harbor.mobi/
cp www.harbor.mobi.key /etc/docker/certs.d/ywww.harbor.mobi/
cp ca.crt /etc/docker/certs.d/www.harbor.mobi/

最终docker目录结构:
/etc/docker/certs.d/
    └── www.harbor.mobi
       ├── www.harbor.mobi.cert  <-- Server certificate signed by CA
       ├── www.harbor.mobi.key   <-- Server key signed by CA
       └── ca.crt               <-- Certificate authority that signed the registry certificate

# 先停止harbor
cd /usr/local/harbor
docker-compose down -v

# 重启docker
systemctl restart docker.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 配置定时垃圾清理

一定要记得设置这个定时清理功能,要不然随着不断推送tag会原来越大,导致磁盘空间不够,最终导致Harbor启动运行不正常;

image-20220322092918900

检查各磁盘空间的命令:

#全局查看
df -h 
#依次查看各个目录的磁盘大小
du -ah --max-depth=1
1
2
3
4

image-20220322094442342

image-20220322094525265

管理后台查看打下:

image-20220322094011738

# 迁移Docker仓库

# 采用registry部署的迁移方法

大概流程就是导出registry镜像,在新的机器导入,然后把镜像文件放到相同的目录下,启动就可以了。

采用Harbor部署的迁移方法

编写脚本把镜像重新上传到Harbor;

参考文档 (opens new window)

# 切换镜像仓库【推荐】

不管以上如何实现,但切换镜像仓库的方法大致相同。在测试没问题的前提下,执行以下流程:

  • 如果选择registry,则只需要把原来registry仓库的镜像文件,直接复制到新的registry仓库的目录下。如过选用Harbor,则需要编写脚本把原来镜像仓库的镜像同步过去。

  • 编写shell脚本通过ansible更新所有要与Registry交互的Docker主机。如果选择Insecure Registry需要更改所有 Docker主机的Docker Daemon。如果选择Secure Registry则是颁发证书。

  • 通知新镜像仓库的地址,避免push、pull失败。

sudo docker run -d -p 5000:5000 --restart=always --name registry -v /app_data/registry/:/var/lib/registry registry:2
1

# 参考相关

上次更新: 2022/04/15, 05:41:30
×