Docker实验五:Docker 仓库管理
Docker 仓库管理
使用仓库(Repository)可以集中存放和管理镜像。
本实验包含三部分内容:
- 如何使用公共的 Docker 仓库。
- 如何使用 Registry 搭建 Docker 仓库。
- 如何使用 VMWare Harbor 搭建自己的Docker仓库。
1 Docker Hub
目前 Docker 官方维护了一个公共仓库 Docker Hub
大部分需求都可以通过在 Docker Hub 中直接下载镜像实现。从 Docker Hub 上下载镜像时,不需要注册账号。
以 hello-world 为关键词进行搜索:
1
docker search hello-world
可以看到Docker Hub给出的 hello-world 镜像列表,这里选择第一个镜像。
1
docker pull hello-world
但是,如果用 Docker Hub 存放(push)自己的镜像时,需要首先在Docker Hub上注册账号。
1.1 注册
在 https://hub.docker.com 免费注册一个 Docker 账号。打开官网后,点击 “Sign Up Docker Hub”注册账号,注册完毕后,点击“Sign In”登录网站。
1.2 登录
登录需要输入用户名和密码,登录成功后,我们就可以往自己账号下的推送镜像了。
使用 docker login 登录 Docker Hub。
1
docker login
输入在Docker Hub网站上注册的账号和密码后,会提示登录成功(Login Succeeded)。
1.3 退出
退出 docker hub 可以使用 docker logout 命令:
1
docker logout
1.4 推送(push)
如果当前处于登出状态,需要重新登录。
登录后,通过 docker push 命令将自己的镜像推送到 Docker Hub。
1
2
3
docker login
docker tag hello-world:latest jiongjiong/hello-world:latest
docker push jiongjiong/hello-world:latest
推送结束后,可以在官网上点击 Repositories 查看自己账号下的镜像。
2 基于 Registry 搭建仓库
在 Docker 中,当执行 docker pull image_name 时 ,实际上是从 registry.hub.docker.com 这个地址去查找,这就是 Docker 公司提供的公共仓库。
在工作中,不可能把企业项目push到公有仓库进行管理。为了更好的管理镜像,Docker不仅提供了一个中央仓库,同时也允许用户搭建本地私有仓库。本节介绍如何使用registry搭建私有仓库,下节介绍如何使用VMWare Harbor搭建仓库。
registry搭建仓库的实验分为两部分:单机版仓库和分布式仓库。
2.1 registry 本地仓库
2.1.1 搭建
Docker 官方提供了一个搭建私有仓库的镜像 registry ,只需把镜像下载下来,运行容器并暴露 5000 端口,就可以使用了。
Registry服务默认会将上传的镜像保存在容器的/var/lib/registry,我们将主机的/opt/registry目录挂载到该目录,即可实现将镜像保存到主机的/opt/registry目录了。
1
2
3
docker pull registry:2
docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --name myregistry registry:2
docker ps -l
浏览器访问http://127.0.0.1:5000/v2/_catalog,出现下面情况说明registry运行正常。
可以看到,当前还没有上传任何镜像。
2.1.2 验证
现在通过 push hello-world 镜像验证 registry 是否正常。
注意在推送前,需要将镜像做一个新的标记(tag),标记的格式为:
仓库地址/镜像名:版本号
使用 push 命令时,push的语法为:
docker push 仓库地址/镜像名:版本号
1
2
docker tag hello-world:latest localhost:5000/hello-world:latest
docker push localhost:5000/hello-world:latest
可以看出,hello-world 镜像推送成功。
通过浏览器验证 hello-world 镜像推送成功。
可以看到仓库中已显示 hello-world 镜像。
接着,使用私有仓库下载镜像,首先移除本地的 hello-world 镜像:
然后,通过pull下载镜像,pull命令的格式为:
docker pull 仓库地址/镜像名:版本号
1
2
3
4
5
docker images
docker rmi hello-world jiongjiong/hello-world localhost:5000/hello-world
docker images
docker pull localhost:5000/hello-world:latest
docker images
可以看到 hello-world 镜像已被成功下载。
对镜像做一个 hello-world:latest 的标记。
1
2
docker tag localhost:5000/hello-world:latest hello-world:latest
docker images
使用本地镜像的另一个好处是,一般局域网的速度要远快于互联网,因此,push和pull的速度都较快。
2.2 registry 远程仓库
到此为止,已经在本地系统上完成了registry仓库的搭建。然而,一般镜像仓库是需要被远程访问,即仓库服务器搭建好了之后,在其他docker客户端上可以将镜像推送到这个镜像仓库,或者从这个镜像仓库下载镜像。
由于我们的实验环境只有当前桌面环境这一台服务器,为了模拟多台服务器,这里,借助于 dind 镜像。
dind 镜像的功能是在 Docker 容器中运行 Docker 容器,可以用dind创建一个 registry_server 容器,作为镜像仓库;再创建一个 registry_client 容器,作为普通的docker服务器,然后从这个 docker服务器上向registry_server推送镜像或者从registry_server上下载镜像。这样就实现了,镜像仓库被远程访问的功能。
首先下载dind镜像,然后创建registry_server 和 registry_client,并为这两台服务器分配IP地址。
1
2
3
docker pull jpetazzo/dind
docker network create registry_net --subnet=172.20.0.0/16
docker run -itd --privileged --name registry_server --hostname server --network registry_net --ip 172.20.1.1 jpetazzo/dind
上述命令分别创建了 registry_server(172.20.1.1) 和 registry_client(172.20.1.2) ,registry_server 为仓库服务器, registry_client 为用于访问仓库服务器的远程机。
在registry_server上部署registry:2服务:
1
2
3
docker exec -it registry_server /bin/bash
docker pull registry:2
docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --name myregistry registry:2
打开Chrome浏览器,输入地址:http://172.20.1.1:5000/v2/_catalog,查看服务是否启动。
可见,服务已正常启动。
新建一个终端标签。
在新打开的终端里,进入 registry_client 。
1
docker exec -it registry_client /bin/bash
首先修改/etc/hosts
文件,添加内容到该文件尾部:
172.20.1.1 server
然后,下载 hello-world 镜像,并推送给 registry_server
1
2
3
docker pull hello-world
docker tag hello-world server:5000/hello-world:latest
docker push server:5000/hello-world:latest
可以看到推送失败了。这是因为从 Docker 1.13.2 版本开始,使用 registry 时,必须使用TLS保证其安全。
有两种方法,可以让镜像顺利推送到仓库服务器上。一种是修改仓库服务器的Docker配置文件 daemon.json ,将仓库服务器配置为非安全服务器。另一种方式是配置TLS认证。
这里,分别用这两种方式进行配置。
2.2.1 修改仓库服务器的 Docker 配置
编辑 /etc/docker/daemon.json 文件,添加如下信息:
1
2
3
{
"insecure-registries":["server:5000","172.20.1.1:5000"]
}
修改完毕后,重启Docker。在 dind 中,第一次重启 Docker 的方式为:
1
2
3
4
ps -ef | grep dockerd
kill -9 58
ps -ef | grep dockerd
service docker start
在后续的实验中,可采用如下方式在 dind 中重启 Docker
1
2
service docker stop
service docker start
通过 docker info 查看 insecure-registies 是否正确设置:
1
docker info
可以看到,insecure-registies 已被正确设置。
接下来,重新推送 hello-world 镜像:
1
docker push server:5000/hello-world
通过 Chrome 验证 hello-world 镜像推送成功。
可见,hello-world 镜像已成功推送。
2.2.2 配置TLS
接下来使用配置TLS(安全传输层协议)认证的方式配置仓库服务器和 Docker 客户端。
首先,将 Docker 客户端的 daemon.json 配置文件移除,并重启Docker。
1
2
3
4
mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
service docker stop
service docker start
docker ps
下载 nginx 镜像, 并尝试推送镜像仓库,确认 Docker 镜像仓库无法推送。
1
2
3
docker pull nginx
docker tag nginx server:5000/nginx
docker push server:5000/nginx
首先在仓库服务器上,生成带有自签名的证书:
1
2
mkdir -p /opt/docker/registry/certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout /opt/docker/registry/certs/domain.key -x509 -days 365 -out /opt/docker/registry/certs/domain.crt
根据提示信息输入自己的信息,在路径 /opt/docker/registry/certs 下生成签名证书。
删除之前创建的 myregistry 容器,重新创建带有 TLS 认证的 registry 容器。
1
2
3
docker stop myregistry
docker rm myregistry
docker run -d --name myregistry -p 5000:5000 -v /opt/docker/registry/certs:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key registry:2
然后回到 Client 端,首先需要创建/etc/docker/certs.d/目录。
然后再该目录下创建与这个registry服务器域名一致的目录:server:5000
1
2
3
mkdir /etc/docker/certs.d
cd /etc/docker/certs.d/
mkdir server:5000
然后将证书 domain.crt 复制到每一个 Client 的 /etc/docker/certs.d/server:5000/ 目录下。
这里,采用scp复制,复制前需要在 server 端安装 ssh 服务器,在 client 端安装 ssh 客户端。
首先在 server 端配置 ssh 服务器:
1
2
apt-get update
apt-get install -y openssh-server
ssh 安装完毕后,需要允许root登录,修改 /etc/ssh/sshd_config 文件,将 PermitRootLogin 这一行改为:
1
PermitRootLogin yes
修改完毕后,重启 ssh 服务器,修改过程如下所示:
1
2
3
vi /etc/ssh/sshd_config
cat /etc/ssh/sshd_config | grep PermitRoot
service ssh restart
为仓库服务器设置root密码:
1
passwd root
接着回到 Client 端安装 ssh 客户端。
1
2
apt-get update
apt-get install -y openssh-client
安装完毕后,将认证文件从仓库服务器拷贝到本地。
1
scp -p [email protected]:/opt/docker/registry/certs/domain.crt /etc/docker/certs.d/server\:5000/ca.crt
现在重新推送 nginx 镜像,输出信息如下:
1
docker push server:5000/nginx
使用 Chrome 查看镜像列表(在提示页面点击:高级->继续):
可以看到 nginx 已被成功推送于仓库服务器上。
从仓库服务器下载 ngnix 镜像进一步验证仓库服务器已正确配置。
1
2
3
4
5
docker images
docker rmi nginx:latest
docker rmi server:5000/nginx
docker pull server:5000/nginx
docker images
可见,可以顺利地从仓库服务器下载到 nginx 镜像。
2.3 基于 VMWare Harbor 搭建仓库
docker 官方提供的私有仓库 registry,用起来虽然简单 ,但在管理的功能上存在不足。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,harbor在实现上使用了官方的docker registry v2(v2命名是distribution)服务。harbor在docker distribution的基础上增加了一些安全、访问控制、管理的功能以满足企业对于镜像仓库的需求。
2.3.1 搭建本地仓库
首先,进入~/course/docker/harbor/
目录, 安装 docker-compose
, 将文件 docker-compose-Linux-x86_64
拷贝于目录 /usr/local/bin/
下,并重命名为:docker-compose
。
1
2
cd ~/course/docker/harbor/
cp docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
然后解压 harbor-offline-installer-v1.2.2.tgz 压缩包,修改 harbor.cfg 将 hostname 的值修改为 127.0.0.1。
1
2
3
4
5
6
tar -zxf harbor-offline-installer-v1.2.2.tgz
ls -l
cd harbor
ls
vim harbor.cfg
cat harbor.cfg | grep hostname
为install.sh添加执行权限,执行 install.sh。
1
2
chmod +x install.sh
./install.sh
安装完毕后,可使用 Chrome 浏览器访问 harbor 服务,在地址栏输入:127.0.0.1,可打开如下图所示页面。
输入账号/密码:admin/Harbor12345,以管理员身份登陆到 harbor 管理页面。
可以看到,当前存在一个library的目录,且该目录为空。
在推送镜像到服务器之前,需要首先用 docker login 登陆仓库服务器。
登陆账号/密码为:admin/Harbor12345
1
docker login 127.0.0.1
现在将 nginx 镜像上传至 harbor 仓库。
1
2
3
docker pull nginx
docker tag nginx 127.0.0.1/library/nginx
docker push 127.0.0.1/library/nginx
可以看到,镜像已成功推送到 harbor 仓库上。
使用 Chrome 查看所推送的镜像,刷新 harbor 管理页面后,点击library:
可以看到 nginx 镜像已被成功推送到 harbor 仓库上。
使用 docker pull 进一步验证 harbor 仓库服务。
首先删除本地的 nginx 镜像,然后从 harbor 仓库服务器上拉取。
1
2
3
docker rmi nginx 127.0.0.1/library/nginx
docker pull 127.0.0.1/library/nginx
docker images
可以看到,ngnix 已从 harbor仓库成功下载。
本地仓库在实际环境中很少使用,更常使用的仓库的远程仓库。
现在基于 dind 模拟 harbor 远程仓库。
基于 dind 创建两台服务器 harbor_server 和 harbor_client , IP 地址分别设置为 172.20.2.1,172.20.2.2。
1
2
docker run -itd --privileged --name harbor_server --hostname server --network registry_net --ip 172.20.2.1 jpetazzo/dind
docker run -itd --privileged --name harbor_client --hostname client --network registry_net --ip 172.20.2.2 jpetazzo/dind
将 docker-compose 和 harbor 安装包拷贝到 harbor_server 中,然后进入 harbor_server 安装 docker-compose 并解压 harbor 安装包。
1
2
3
4
5
6
7
8
9
10
cd ..
ls
docker cp docker-compose-Linux-x86_64 harbor_server:/home
docker cp harbor-offline-installer-v1.2.2.tgz harbor_server:/home
docker exec -it harbor_server /bin/bash
cd /home
ls
mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
tar -zxf harbor-offline-installer-v1.2.2.tgz
ls
进入harbor目录,将harbor.cfg中的IP地址改为:172.20.2.1,然后分别为/usr/local/bin/docker-compose和./install.sh 添加执行权限。
1
2
3
4
vi harbor.cfg
cat harbor.cfg | grep hostname
chmod +x /usr/local/bin/docker-compose
chmod +x install.sh
执行 install.sh 安装 harbor。
1
./install.sh
从浏览器上查看 Harbor 仓库服务,打开 Chrome 浏览器,输入地址:172.20.2.1,使用 admin/Harbor12345 登录,可以看到当前 library 仓库为空。
在终端另一个tab页上进入 harbor_client, 尝试推送 hello-world 镜像到 harbor 仓库服务器。
1
2
3
4
docker exec -it harbor_client /bin/bash
docker pull hello-world
docker tag hello-world 172.20.2.1/library/hello-world
docker login 172.20.2.1
可以看到,远程方式访问 harbor 仓库时,访问失败。
和registry:2一样,可以通过两种方式使得远程机可以推送镜像到Harbor服务器,一种是配置 daemon.json 文件,告知 Docker 客户端,所要使用的仓库时不安全的;另一种是配置TLS认证。
下面分别使用这两种方式来配置 harbor 仓库。
2.3.2 修改 daemon.json 配置文件
编辑修改 /etc/docker/daemon.json 文件,添加相关内容:
1
2
3
{
"insecure-registries":["172.20.2.1"]
}
1
2
3
ps -ef | grep dockerd
kill -9 58
service docker start
使用docker info
确认配置已生效:
可以在 Insecure Registries 中看到 172.20.2.1,因此,配置已生效。
再次使用 docker login 登录 harbor 仓库服务器,
1
docker login 172.20.2.1
提示登录已成功。
再次推送 hello-world 镜像,
1
docker push 172.20.2.1/library/hello-world
可以看到,镜像已成功推送。
通过浏览器确认镜像推送成功,切换到 Chrome 浏览器,刷新 harbor 管理页面,可以看到 hello-world 镜像已被成功推送。
2.4 基于 TLS 配置安全性更高的 harbor 仓库
首先在 Client 上移除 /etc/docker/daemon.json 文件,并重启 Dcoker, 确认关闭不安全的配置方式。
1
2
3
4
mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
service docker stop
service docker start
docker login 172.20.1.1
可以看到使用 docker login 时,无法登录,说明不安全的配置方式已关闭。
回到 harbor 仓库服务器的终端,开始为 harbor 配置 https 认证。
2.4.1 创建证书
首先创建证书的存放目录:
1
2
3
mkdir /root/ca -p
cd /root/ca
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 365 -out ca.crt
其中,
- req:申请证书签署请求
- -newkey:新密钥
- -x509:可以用来显示证书的内容,转换其格式,给CSR签名等X.509证书的管理工作,这里用来自签名。
按照提示信息输入相应内容,注意在 Common Name 提示信息处输入 harbor 服务器的仓库地址。
2.4.2 生成证书签名请求
1
openssl req -newkey rsa:4096 -nodes -sha256 -keyout 172.20.2.1.key -out 172.20.2.1.csr
按照自己的信息填写上述内容。注意在 Common Name 处需要填写 harbor 仓库服务器的 IP 地址。
2.4.3 生成证书
habor仓库服务器默认只能通过域名访问,不能通过IP地址访问,这里对其进行配置,使得可以通过IP访问仓库服务器。
1
2
echo subjectAltName = IP:172.20.2.1 > extfile.cnf
openssl x509 -req -days 365 -in 172.20.2.1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out 172.20.2.1.crt
2.4.4 配置harbor.cfg
配置 harbor.cfg 文件,
- 将协议改为 https 协议,uiurlprotocol = https
- 设置 ssl_cert 文件路径为:/root/ca/172.20.2.1.crt
- 设置 ssl_cert_key 文件路径为:/root/ca/172.20.2.1.key
使用vi,按如下方式编辑harbor.cfg文件。
2.4.5 重新启动harbor
使用 docker-compose down 命令停止当前的harbor服务,使用 prepare 脚本使得新配置的 harbor.cfg 生效,使用 docker-compose up 命令启动新配置下的 habor 服务。
1
2
3
docker-compose down -v
./prepare
docker-compose up -d
接下来需要将 harbor 仓库服务器的认证文件拷贝到 Client 远程机上。
按照 registry TLS 配置实验中的方法分别为 harbor 仓库服务器和 Client 客户端安装 SSH Server 和 SSH Client,安装完毕后,将 server 端的 root 密码重置为 coursegrading。
server端的 ssh 配置流程如下:
1
2
3
4
5
6
apt-get update
apt-get install -y openssh-server
vi /etc/ssh/sshd_config
cat /etc/ssh/sshd_config | grep PermitRootLogin
service ssh restart
passwd root
client端的 ssh 配置流程如下:
1
2
apt-get update
apt-get install -y openssh-client
然后将 server 端制作的 ca 证书拷贝到 client 端,并添加到信任。
1
2
mkdir -p /etc/docker/certs.d/172.20.2.1
scp [email protected]:/root/ca/ca.crt /etc/docker/certs.d/172.20.2.1
然后重启 client 端的 Docker 服务:
1
2
service docker stop
service docker start
2.4.6 测试
重新使用 docker login 登录 172.20.2.1 仓库服务器:
1
docker login 172.20.2.1
由于之前登陆时,账号/密码已被系统记录,所以可以直接登录。
这里,首先从 docker 官方下载 mysql 镜像,然后推送到 harbor 仓库服务器上。
1
2
3
docker pull mysql
docker tag mysql 172.20.2.1/library/mysql
docker push 172.20.2.1/library/mysql
可见,mysql镜像已成功推送。
通过Chrome浏览器查看该镜像,首先在地址栏输入:https://172.20.2.1,登录
可以看到 mysql 镜像已被成功推送。
使用docker pull 再次测试:
1
2
docker rmi 172.20.2.1/library/mysql mysql
docker pull 172.20.2.1/library/mysql
查看镜像列表:
1
docker images
可见,带有 https 认证的harbor仓库已配置成功。