Registry用于保存docker镜像,包括镜像的层次结构和元数据。用户可以自建Registry,也可使用官方的Docker Hub。

Docker Registry 分类:

  • Sponsor Registry: 第三方的registry,供客户和Docker社区使用
  • Mirror Registry: 第三方的registryy,只让客户使用
  • Vendor Registry: 由发布Docker镜像的供应商提供的registry
  • Private Registry: 通过设有防火墙和额外的安全层的私有实体提供的registry

私有Registry

使用前先要将服务部署到服务器上。

YUM安装

可以通过yum安装:

yum install docker-registry
yum install docker-distribution

上面两个命令都会安装docker-distribution只要执行一个就好了。

软件包的信息:

[root@Docker ~]# yum info docker-distribution
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
可安装的软件包
名称    :docker-distribution
架构    :x86_64
版本    :2.6.2
发布    :2.git48294d9.el7
大小    :3.5 M
源    :extras/7/x86_64
简介    : Docker toolset to pack, ship, store, and deliver content
网址    :https://github.com/docker/distribution
协议    : ASL 2.0
描述    : Docker toolset to pack, ship, store, and deliver content

[root@Docker ~]# 

这个就不装了,因为还可以将服务安装在容器中运行。

容器安装

docker官方也提供了容器,基于容器提供Registry服务。

下载镜像:

[root@Docker ~]# docker image pull registry
Using default tag: latest
latest: Pulling from library/registry
c87736221ed0: Pull complete 
1cc8e0bb44df: Pull complete 
54d33bcb37f5: Pull complete 
e8afc091c171: Pull complete 
b4541f6d3db6: Pull complete 
Digest: sha256:8004747f1e8cd820a148fb7499d71a76d45ff66bac6a29129bfdbfdc0154d146
Status: Downloaded newer image for registry:latest
[root@Docker ~]# 

启动容器:

docker run -d -p 5000:5000 --restart always --name registry registry

配置文件
查看registry的配置文件:

[root@Docker ~]# docker container exec -it registry cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
[root@Docker ~]# 

这里是默认的配置文件。配置文件是通过CMD命令指定的,默认的dockerfile的CMD指令如下:

CMD ["/etc/docker/registry/config.yml"]

镜像存放的位置
镜像Dockerfile中有一条VOLUME指令,这个路径就是容器是存放镜像的路径:

VOLUME ["/var/lib/registry"]

启动镜像时,可以使用-v参数,指定宿主机的目录。

上传镜像

上传镜像前,先要给镜像打标:

[root@Docker ~]# docker push busybox loclhost:5000/busybox

这里要准备将本地的busybox推送到服务器loclhost:5000。这里省略了仓库的用户名,没有用户名就是一个顶层仓库。

推送:

[root@Docker ~]# docker push localhost:5000/busybox
The push refers to repository [localhost:5000/busybox]
0d315111b484: Pushed 
latest: digest: sha256:895ab622e92e18d6b461d671081757af7dbaa3b00e3e28e12505af7817f73649 size: 527
[root@Docker ~]# 

不往本机lo接口推,也就是服务器地址不使用localhost或127.0.0.1。而是向本机的网卡地址推。就像其他主机要向本机的registry推送一样了。然后会产生如下的错误:

[root@Docker ~]# docker push 192.168.24.170:5000/busybox
The push refers to repository [192.168.24.170:5000/busybox]
Get https://192.168.24.170:5000/v2/: http: server gave HTTP response to HTTPS client
[root@Docker ~]# 

这里的问题是,docker默认是使用https协议工作的,而registry服务器的响应是http协议。解决的办法有两个。
第一个方法是修改registry来适应docker,registry服务器改为https协议
第二个方法是修改docker来使用registry,将registry服务器地址加入到docker的insecure-registries中去

配置insecure-registries
修改配置文件,然后重启加载后就可以推送上去了:

[root@Docker ~]# cat /etc/docker/daemon.json
{
    "registry-mirrors": ["http://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"],
    "insecure-registries": ["192.168.24.170:5000"]
}
[root@Docker ~]# systemctl reload docker
[root@Docker ~]# docker push 192.168.24.170:5000/busybox
The push refers to repository [192.168.24.170:5000/busybox]
0d315111b484: Layer already exists 
latest: digest: sha256:895ab622e92e18d6b461d671081757af7dbaa3b00e3e28e12505af7817f73649 size: 527
[root@Docker ~]# 

下载镜像

指定Registry下载之前上传的镜像:

[root@Docker ~]# docker pull 192.168.24.170:5000/busybox
Using default tag: latest
latest: Pulling from busybox
ee153a04d683: Pull complete 
Digest: sha256:895ab622e92e18d6b461d671081757af7dbaa3b00e3e28e12505af7817f73649
Status: Downloaded newer image for 192.168.24.170:5000/busybox:latest
[root@Docker ~]# 

Harbor

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器。

Harbor特性

基于角色的访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。
镜像复制:镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。
图形化用户界面:用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。
AD/LDAP 支持:Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理。
审计管理:所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。
国际化:已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。
RESTful API:RESTful API 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易。
部署简单:提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备。

安装准备

github项目地址:
https://github.com/vmware/harbor
这是一个vmware的开源项目,实际会跳转到下面这个地址:
https://github.com/goharbor/harbor

下载 harbor
查看项目的README,Features的内容上面提过了,这里主要看Install & Run部分的内容。

首先是下载
Harbor release:
https://github.com/goharbor/harbor/releases

$ wget https://storage.googleapis.com/harbor-releases/release-1.8.0/harbor-offline-installer-v1.8.2-rc1.tgz

安装配置向导
Installation & Configuration Guide:
https://github.com/goharbor/harbor/blob/master/docs/installation_guide.md

硬件要求:

Resource Capacity Description
CPU minimal 2 CPU 4 CPU is preferred
Mem minimal 4GB 8GB is preferred
Disk minimal 40GB 160GB is preferred

软件要求:

Software Version Description
Docker engine version 17.06.0-ce+ or higher For installation instructions, please refer to: docker engine doc
Docker Compose version 1.18.0 or higher For installation instructions, please refer to: docker compose doc
Openssl latest is preferred Generate certificate and keys for Harbor

安装步骤:

  1. Download the installer;
  2. Configure harbor.yml;
  3. Run install.sh to install and start Harbor;

下载完之后,先解压:

[root@Harbor ~]# tar xvf harbor-offline-installer-v1.8.1.tar -C /opt
harbor/harbor.v1.8.1.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/harbor.yml
[root@Harbor ~]# 

下载的文件在解压后就不需要了。解压后的文件在安装完成后也都是不需要的。所以下载到哪里,解压到哪里其实都不重要。建议可以解压到 /opt 或 /usr/local 这两个目录里。

安装包中的镜像
解压后的文件中,有一个文件harbor.v1.8.1.tar.gz。这个是被导出的docker镜像。还记得docker save命令吧,可以打包导出多个镜像并完成压缩:

$ docker save myimg/httpd:v1 myimg/httpd:v2 | gzip > myimage_latest.tar.gz

这个文件应该就是这么来的。之后的安装过程中,则是会把这个文件里的所有镜像做一次批量导入:

$ docker load -i myimage_latest.tar.gz

在安装时执行的install.sh脚本里有解压并导入镜像的语句:

if [ -f harbor*.tar.gz ]
then
        h2 "[Step $item]: loading Harbor images ..."; let item+=1
        docker load -i ./harbor*.tar.gz
fi

安装的依赖和过程
Harbor的安装,就是给当前的主机安装很多容器,并且把这些容器都启动起来。启动Harbor就是用docker-compose把这些容器的启动起来,而关闭harbor也是通过docker-compose来把容器一次关闭。之所以需要借助docker-compose,因为harbor是由很多容器协同过程的,容器之间又依赖关系,这些都需要docker-compose这个单机编排工具来协调。

所以安装harbor前,需要安装好docker-compose,才能实现本地的容器的编排。需要安装好docker,才能把本地的镜像启动起来。镜像就在下载解压的文件中。并且还需要启动docker,这样才能运行容器。
准备工作完成后,就是执行harbor准备的install.sh脚本,在本地加载好镜像,通过docker-compose把这些镜像依次启动起来,并且运行在本地的docker上。

修改harbor.yml配置文件,主机名一定看改掉,最好使用本机的域名,如果没有域名那么就用本机的IP地址。没改的话,会有如下的错误提示:

[root@Harbor harbor]# ./install.sh 
➜ Please set hostname and other necessary attributes in harbor.yml first. DO NOT use localhost or 127.0.0.1 for hostname, because Harbor needs to be accessed by external clients.
Please set --with-notary if needs enable Notary in Harbor, and set ui_url_protocol/ssl_cert/ssl_cert_key in harbor.yml bacause notary must run under https. 
Please set --with-clair if needs enable Clair in Harbor
Please set --with-chartmuseum if needs enable Chartmuseum in Harbor
[root@Harbor harbor]# 

检查发现没有安装docker:

[root@Harbor harbor]# ./install.sh 

[Step 0]: checking installation environment ...
✖ Need to install docker(17.06.0+) first and run this script again.
[root@Harbor harbor]# 

检查发现没有安装docker-compose:

[root@Harbor harbor]# ./install.sh 

[Step 0]: checking installation environment ...

Note: docker version: 19.03.1
✖ Need to install docker-compose(1.18.0+) by yourself first and run this script again.
[root@Harbor harbor]# 

检查发现docker没有启动:

[root@Harbor harbor]# ./install.sh 

[Step 0]: checking installation environment ...

Note: docker version: 19.03.1

Note: docker-compose version: 1.18.0

[Step 1]: loading Harbor images ...
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
[root@Harbor harbor]# 

Docker Compose

Docker的单机编排工具。官方文档:
https://docs.docker.com/compose/

为了简化harbor的安装和部署,所以harbor做成了在容器中运行的应用。但是harbor的运行还依赖很多其他的应用,所以需要编排几个容器来协同工作。所以harbor的部署和使用时需要借助Docker的单机编排工具Docker Compose。

安装docker-compose,位于epel源中:

yum install docker-compose

Compose模板文件
模板文件是使用Compose的核心,设计的指令关键字也有很多,默认的模板文件名称为docker-compose.yml,格式为YAML格式。
这个不是重点,能安装使用harbor就好了,不过还是简单了解一下。
要使用docker-compose就要写一个编排脚本,和dockerfile类似,也是有很多指令。定义要启动的每一个容器,指明依赖关系,这样被依赖的容器需要先启动。关闭容器的时候也要对称,先把没有被依赖的容器关闭掉。
顺便就来看下harbor的docker-compose.yml文件:

[root@Harbor harbor]# cat docker-compose.yml 
version: '2.3'  # docker-compose的版本
services:  # 定义一个服务
  log:  # 服务的名称,服务是通过容器来提供的,具体就是下面的设置
    image: goharbor/harbor-log:v1.8.1  # 指定容器的镜像,也可以用build指令通过dockerfile创建
    container_name: harbor-log  # 生成的容器的名称
    restart: always  # 容器自动重启
    dns_search: .
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETGID
      - SETUID
    volumes:  # 定义卷
      - /var/log/harbor/:/var/log/docker/:z
      - ./common/config/log/:/etc/logrotate.d/:z
    ports:
      - 127.0.0.1:1514:10514
    networks:  # 加入的网络
      - harbor
  registry:
    image: goharbor/registry-photon:v2.7.1-patch-2819-v1.8.1
    container_name: registry
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    volumes:
      - /data/registry:/storage:z
      - ./common/config/registry/:/etc/registry/:z
      - type: bind
        source: /data/secret/registry/root.crt
        target: /etc/registry/root.crt
    networks:
      - harbor
    dns_search: .
    depends_on:  # 依赖的容器名称
      - log
    logging:
      driver: "syslog"
      options:  
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "registry"
  registryctl:
    image: goharbor/harbor-registryctl:v1.8.1
    container_name: registryctl
    env_file:
      - ./common/config/registryctl/env
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    volumes:
      - /data/registry:/storage:z
      - ./common/config/registry/:/etc/registry/:z
      - type: bind
        source: ./common/config/registryctl/config.yml
        target: /etc/registryctl/config.yml
    networks:
      - harbor
    dns_search: .
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:  
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "registryctl"
  postgresql:
    image: goharbor/harbor-db:v1.8.1
    container_name: harbor-db
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETGID
      - SETUID
    volumes:
      - /data/database:/var/lib/postgresql/data:z
    networks:
      harbor:
    dns_search: .
    env_file:
      - ./common/config/db/env
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:  
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "postgresql"
  core:
    image: goharbor/harbor-core:v1.8.1
    container_name: harbor-core
    env_file:
      - ./common/config/core/env
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - SETGID
      - SETUID
    volumes:
      - /data/ca_download/:/etc/core/ca/:z
      - /data/psc/:/etc/core/token/:z
      - /data/:/data/:z
      - ./common/config/core/certificates/:/etc/core/certificates/:z
      - type: bind
        source: ./common/config/core/app.conf
        target: /etc/core/app.conf
      - type: bind
        source: /data/secret/core/private_key.pem
        target: /etc/core/private_key.pem
      - type: bind
        source: /data/secret/keys/secretkey
        target: /etc/core/key
    networks:
      harbor:
    dns_search: .
    depends_on:
      - log
      - registry
    logging:
      driver: "syslog"
      options:  
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "core"
  portal:
    image: goharbor/harbor-portal:v1.8.1
    container_name: harbor-portal
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
      - NET_BIND_SERVICE
    networks:
      - harbor
    dns_search: .
    depends_on:
      - log
      - core
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "portal"

  jobservice:
    image: goharbor/harbor-jobservice:v1.8.1
    container_name: harbor-jobservice
    env_file:
      - ./common/config/jobservice/env
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    volumes:
      - /data/job_logs:/var/log/jobs:z
      - type: bind
        source: ./common/config/jobservice/config.yml
        target: /etc/jobservice/config.yml
    networks:
      - harbor
    dns_search: .
    depends_on:
      - redis
      - core
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "jobservice"
  redis:
    image: goharbor/redis-photon:v1.8.1
    container_name: redis
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    volumes:
      - /data/redis:/var/lib/redis
    networks:
      harbor:
    dns_search: .
    depends_on:
      - log
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "redis"
  proxy:
    image: goharbor/nginx-photon:v1.8.1
    container_name: nginx
    restart: always
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
      - NET_BIND_SERVICE
    volumes:
      - ./common/config/nginx:/etc/nginx:z
    networks:
      - harbor
    dns_search: .
    ports:
      - 80:80
    depends_on:
      - postgresql
      - registry
      - core
      - portal
      - log
    logging:
      driver: "syslog"
      options:  
        syslog-address: "tcp://127.0.0.1:1514"
        tag: "proxy"
networks:
  harbor:
    external: false
[root@Harbor harbor]# 

安装 Harbor

安装前,需要去修改一下harbor.yml这个文件的配置,至少要把主机名改掉,之前已经说过了。其他配置按需要修改,不改也能够安装了。

一切准备就行,就可以安装了:

[root@Harbor harbor]# ./install.sh 

[Step 0]: checking installation environment ...

Note: docker version: 19.03.1

Note: docker-compose version: 1.18.0

[Step 1]: loading Harbor images ...
ba58b7bb3f17: Loading layer  33.32MB/33.32MB
......略过......
Loaded image: goharbor/clair-photon:v2.0.8-v1.8.1

[Step 2]: preparing environment ...
prepare base dir is set to /opt/harbor
Generated configuration file: /config/log/logrotate.conf
......略过......
Generated certificate, key file: /secret/core/private_key.pem, cert file: /secreCreating harbor-log ... done
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir

Creating registry ... done
Creating harbor-core ... done
[Step 3]: starting Harbor ...
Creating harbor-portal ... done
Creating nginx ... done
Creating harbor-db ... 
Creating redis ... 
Creating registryctl ... 
Creating registry ... 
Creating harbor-core ... 
Creating harbor-portal ... 
Creating harbor-jobservice ... 
Creating nginx ... 

✔ ----Harbor has been installed and started successfully.----

Now you should be able to visit the admin portal at http://HarborStudy. 
For more details, please visit https://github.com/goharbor/harbor .

[root@Harbor harbor]# 

安装成功,可以看看监听的端口,安装了哪些镜像,启动了哪些容器:

$ ss -tnl
$ docker images
$ docker ps

登录 Harbor

默认的密码在harbor.yml有设置的:

harbor_admin_password: Harbor12345

用户名是admin,密码没改的话就是默认的,可以登录进去。

使用浏览器访问Web页面,可以看到一些管理界面。
另外要上传或下载镜像,需要在命令行使用docker命令,在那之前也需要登录Harbor,使用docker login命令来完成登录:

[root@Harbor harbor]# docker login localhost
Username: admin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
[root@Harbor harbor]# 

登录成功之后,才能推送镜像。

停止 Harbor

要想停止或启动harbor,需要通过docker-compose命令。
在操作之前,最好先切换目录到要操作的docker-compose.yml所在的目录,这样docker-compose能够自动找到模板文件并进行操作。
停止harbor:

[root@Harbor harbor]# cd /opt/harbor/
[root@Harbor harbor]# docker-compose stop
Stopping nginx             ... done
Stopping harbor-portal     ... done
Stopping harbor-jobservice ... done
Stopping harbor-core       ... done
Stopping registryctl       ... done
Stopping harbor-db         ... done
Stopping registry          ... done
Stopping redis             ... done
Stopping harbor-log        ... done
[root@Harbor harbor]# 

然后再次启动:

[root@Harbor harbor]# docker-compose start
Starting log         ... done
Starting registry    ... done
Starting registryctl ... done
Starting postgresql  ... done
Starting core        ... done
Starting portal      ... done
Starting redis       ... done
Starting jobservice  ... done
Starting proxy       ... done
[root@Harbor harbor]#