系统环境
- centos7
- docker 17.06.1-ce
- 安装docker-compose
- 安装docker-machine
自动部署
运行如下代码就能自动部署一套shipyard环境,运行localhost:8080就能访问shipyard
curl -sSL https://shipyard-project.com/deploy | bash -s
感兴趣可以打开https://shipyard-project.com/deploy
查看shell脚本,自动话脚本提供了多种ACTION
的操作模式,可以方便的实现快速部署,快速添加节点,删除shipyard等使用的功能
手动部署
首先启动docker服务,运行systemctl start docker
,可以通过docker --help
查看docker提供的命令
docker命令只能用
root
操作,如果想要其他用户可以操作docker命令,可以sudo groupadd docker
新建一个docker用户组,一般安装docker后就会存在一个docker用户组,随后sudo gpasswd -a ${USER} docker
将当前用户加入到docker组,其中${USER}
是当前用户,也可以直接写用户名,最后sudo systemctl restart docker
重启docker服务,并退出账号重新登录,就能用非root账号操作docker命令了
第一步,拉取镜像,shipyard环境总共启动了7个容器,对应6个镜像,分别是
- shipyard/shipyard
- swarm
- shipyard/docker-proxy
- microbox/etcd
- rethinkdb
- alpine
采用docker pull IMAGE-NAME
拉取镜像至本地,例如docker pull shipyard/shipyard
,也可以先用docker search IMAGE-NAME
查看docker仓库中的镜像,拉取得星最多的,或者官方认证的包,或者制定拉取其他包
第二步,启动容器 首先启动rethinkdb,执行下面命令即可
$ docker run \
-ti \
-d \
--restart=always \
--name shipyard-rethinkdb \
rethinkdb
然后启动discovery,这个的功能是向swarm集群提供发现服务的,运行下面的命令
$ docker run \
-ti \
-d \
-p 4001:4001 \
-p 7001:7001 \
--restart=always \
--name shipyard-discovery \
microbox/etcd -name discovery
然后运行proxy代理服务,docker默认监听socket,通过代理服务可以将tcp等进行转发
$ docker run \
-ti \
-d \
-p 2375:2375 \
--hostname=$HOSTNAME \
--restart=always \
--name shipyard-proxy \
-v /var/run/docker.sock:/var/run/docker.sock \
-e PORT=2375 \
shipyard/docker-proxy:latest
然后运行swarm manager,swarm是docker提供的集群功能,swarm manager可以管理多个swarm agent,命令中的<IP-OF-HOST>
是当前电脑的ip地址
$ docker run \
-ti \
-d \
--restart=always \
--name shipyard-swarm-manager \
swarm:latest \
manage --host tcp://0.0.0.0:3375 etcd://<IP-OF-HOST>:4001
然后运行swarm agent,这是为了将本机也加入到集群节点之中,命令如下,第一个<ip-of-host>
是当前电脑的ip,第二个是etcd发现服务电脑的ip,由于本机是manager节点,所以此处也填本机ip,若本机作为子节点,则应填入manager的ip地址
$ docker run \
-ti \
-d \
--restart=always \
--name shipyard-swarm-agent \
swarm:latest \
join --addr <ip-of-host>:2375 etcd://<ip-of-host>:4001
最后,运行shipyard-controller容器,--link
参数是用来链接其他容器,这里将shipyard-rethinkdb映射到controller里,controller访问rethinkdb时,直接写rethinkdb就行,不用再去找rethinkdb的ip地址
$ docker run \
-ti \
-d \
--restart=always \
--name shipyard-controller \
--link shipyard-rethinkdb:rethinkdb \
--link shipyard-swarm-manager:swarm \
-p 8080:8080 \
shipyard/shipyard:latest \
server \
-d tcp://swarm:3375
--link
相当于是在容器内修改了/etc/hosts
文件,例如rethinkdb的容器ip是172.12.0.3,controller通过link链接了rethinkdb容器,则可以在controller的hosts文件中找到172.12.0.3 rethinkdb <rethinkdb的容器id>
当所有容器都启动之后,运行docker ps
命令,应该可以看到如下内容
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
59a96a2356ab shipyard/shipyard:latest "/bin/controller -..." 2 days ago Up 14 seconds 0.0.0.0:8080->8080/tcp shipyard-controller
3cd68e51673e swarm:latest "/swarm j --addr 1..." 2 days ago Up 55 seconds 2375/tcp shipyard-swarm-agent
93e27c7434f9 swarm:latest "/swarm m --replic..." 2 days ago Up 53 seconds 2375/tcp shipyard-swarm-manager
8a68c07675da shipyard/docker-proxy:latest "/usr/local/bin/run" 2 days ago Up About a minute 0.0.0.0:2375->2375/tcp shipyard-proxy
5142636c549a alpine "sh" 2 days ago Up About a minute shipyard-certs
ac0f27bb97e2 microbox/etcd:latest "/bin/etcd -addr 1..." 2 days ago Up About a minute 0.0.0.0:4001->4001/tcp, 0.0.0.0:7001->7001/tcp shipyard-discovery
711497e75c5a rethinkdb "rethinkdb --bind all" 2 days ago Up About a minute 8080/tcp, 28015/tcp, 29015/tcp shipyard-rethinkdb
此时,本地通过访问localhost:8080
,或者其他地方访问本机<ip>:8080
就能看到shipyard的登录界面,初始化账号密码是admin/shipyard
增加节点
shipyard增加节点只需要在节点机上运行命令,其中10.0.1.10要改为manager节点的地址
curl -sSL https://shipyard-project.com/deploy | ACTION=node DISCOVERY=etcd://10.0.1.10:4001 bash -s
或者阅读脚本命令,自己手动部署,效果相同
通过镜像方式
docker官方提供了创建私有仓库的镜像registry
,只需要简单的拉下来跑起来就能拥有一个私有仓库,私有仓库默认端口是5000,运行如下命令启动私有仓库,其中--restart=always
定义了,这个容器在每次docker启动的时候就会自动运行,加入这个属性可以避免重启docker服务后还要手动启动一堆容器,-v /mnt/registry:/var/lib/registry
是将容器里的/var/lib/registry
路径挂在到本地的/mnt/registry
路径,这个可以避免误删容器时将存储的数据删除了
$ docker run -d \
-p 5000:5000 \
--restart=always \
--name registry \
-v /mnt/registry:/var/lib/registry \
registry:2
registry有很多的配置可以修改,可以自定义端口,自定义数据存放地址等等一系列配置,具体配置可以看官方文档,resigty部分
registry容器跑起来后,在本地就可以上传镜像了,首先需要用docker tag
命令修改镜像名字,docker镜像的命名规则是
registry<url>:port/namespace/imagename:tag
举例,通过docker tag shipyard/shipyard:latest localhost:5000/shipyard/shipyard:latest
将shipyard镜像改为了localhost:5000/shipyard/shipyard
然后通过docker push localhost:5000/shipyard/shipyard:latest
就能讲这个镜像上传到私有仓库
通过docker rmi <imageID>
删除shipyard的镜像,然后通过docker pull localhost:5000/shipyard/shipyard:latest
拉取镜像,已验证是否成功
目前的registry还只能在本地使用,要想在其他docker节点机上拉取或上传私有仓库,还需要配置一下
配置其他机器使用registry
由于docker仅允许https
访问registry,所以,在其他节点上,直接访问registry节点的ip访问不过去,提示认证失败等错误,有两种方法可用
方法一:
修改或创建/etc/docker/daemon.json
加入如下内容
{
"insecure-registries" : ["myregistrydomain.com:5000"]
}
然后systemctl restart docker
重启docker服务,这样就能通过http
连上私有仓库了
daemon.json还有很多其他可以配置的属性,可以看daemon CLI reference
方法二: 获取CA认证,此处采用个人签名证书,有钱可以上权威认证证书 首先运行如下命令创建公钥和私钥
$ mkdir -p certs
$ openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt
运行这段命令后会让你输入一些信息,可以自由发挥,但域名那一栏一定不能乱填,不能搞事情,下面是参考
Generating a 4096 bit RSA private key
.........................................................................................................................................................................................................++
...++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Chongqing
Locality Name (eg, city) []:Chongqing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SpringAirline
Organizational Unit Name (eg, section) []:QC
Common Name (e.g. server FQDN or YOUR name) []:czy.registry.com
Email Address []:docker@inner.czy.com
证书生成之后可以按照官方文档的样子启动容器,TLS模式重启registry
$ docker run -d \
--restart=always \
--name registry \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:80 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-p 80:80 \
registry:latest
在远程节点机上,还需要将私钥domain.crt
复制到/etc/docker/certs.d/myregistrydomain.com:5000/ca.crt
下,myregistrydomain.com
要与证书内配置的地址一致,然后重启docker服务即可通过https远程访问私有仓库
若还是不能访问,提示认证问题,则可能是某些系统拦截了证书请求,考虑将证书加入到系统信任中,针对不同linux系统,方法不同
UBUNTU
执行如下命令
$ cp certs/domain.crt /usr/local/share/ca-certificates/myregistrydomain.com.crt
update-ca-certificates
Red Hat Enterprise Linux
$ cp certs/domain.crt /etc/pki/ca-trust/source/anchors/myregistrydomain.com.crt
update-ca-trust
Oracle Linux
$ update-ca-trust enable
然后重启docker服务,再尝试访问私有仓库
网上流行用nginx反向代理做https认证,虽然我也没搞明白为什么要这么做,但依葫芦画瓢我也写下来
通过nginx反向代理设置https服务
首先安装最新的nginx,不会的可以参考官方文档进行安装
大致是先按照官方文档添加yum
源,然后通过yum makecache
创建缓存,如果出问题,可以尝试先yum clean all
清理缓存,再重新创建,最后通过yum install nginx
安装nginx
验证nginx是否安装好,可以通过nginx --help
命令,如果已经有nginx命令了,应该是安装好了,或者通过systemctl start nginx
启动nginx,访问localhost<主机ip>
nginx默认监听80端口,是http默认端口,所以url后面可以不用接端口号,如果显示nginx欢迎页面,则表示nginx安装成功
配置nginx
在/etc/nginx/
目录下创建docker-registry.conf(文件名也可自定义,和后面的文件有关联),填入一下内容,这些内容可以在docker官网nginx代理配置找到相关说明
proxy_pass http://docker-registry;
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
然后再/etc/nginx/conf.d
目录下创建registry.conf(文件名也可自定义),填入以下内容,这部分内容是nginx的代理配置,引导nginx将请求指向哪里
# For versions of nginx > 1.3.9 that include chunked transfer encoding support
# Replace with appropriate values where necessary
upstream docker-registry {
server localhost:5000; # 这里是docker-registry的地址
}
# uncomment if you want a 301 redirect for users attempting to connect
# on port 80
# NOTE: docker client will still fail. This is just for convenience
# server {
# listen *:80;
# server_name my.docker.registry.com;
# return 301 https://$server_name$request_uri;
# }
server {
listen 443;
server_name czy.registry.com;
ssl on; # 打开ssl
ssl_certificate /mnt/registry/certs/registry.crt; # 公钥证书
ssl_certificate_key /mnt/registry/certs/registry.key; # 私钥
client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
location /v2/ {
auth_basic "Registry realm";
auth_basic_user_file /mnt/registry/auth/nginx.htpasswd;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
include docker-registry.conf;
}
}
这段配置中/mnt/registry/auth/nginx.htpasswd
文件是存帐号密码的文件,访问私库需要提供账号密码,如果不想输入账号秘密,就不要这么配置,具体怎么配,上网查一下,帐号密码文件是用以下代码生成,htpasswd
是apache2-utils
提供的功能,如果找不到htpasswd
,可以用yum install apache2-utils
安装
htpasswd -cb /mnt/registry/auth/nginx.htpasswd admin admin
公钥私钥就是之前生成的公钥私钥的路径
现在剩下最后一部,就是修改hosts,也可以修改公司网络的DNS,一劳永逸,如果不方便需改DNS,就可以修改本机hosts,修改之后上传和下载镜像就可以写成czy.registry.com/<namespace>/<imagename>:tag
,因为443是https的默认端口,所以域名后面可以不用接端口了
至此,docker平台基本可以使用了,但是还有很多问题没有解决,还在持续优化中 问题:
在shipyard中增加仓库只能显示镜像名称,不能拉取(已解决,删除registry认证后就可以下载了,shipyard没有提供传输账号密码的地方)- shipyard的images页面没有显示node节点信息
- shipyard增加节点后,启动容器无法启动老节点的容器,只能启动新加入节点的容器
遇到的坑
因为docker容器与容器之间通信是通过docker0的虚拟网卡,有自己的ip,所以如果shipyard和registry搭建在同一台电脑的话,给shipyard增加仓库的时候,填写外部域名怎么也添加不上,只能写docker容器内部的ip就能加上了,我采用的方式是通过link方式,链接两个容器,这样可以方便在重启后ip变化导致有需要重新添加的情况.