/SomeDocker

docker相关的内容

shipyard搭建

系统环境

  • 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文件是存帐号密码的文件,访问私库需要提供账号密码,如果不想输入账号秘密,就不要这么配置,具体怎么配,上网查一下,帐号密码文件是用以下代码生成,htpasswdapache2-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变化导致有需要重新添加的情况.