wzg0wzg 2015-09-14
【编者的话】Docker技术炙手可热,但是对于初创企业如何利用Docker这门新技术来解决内网开发或者测试环境的快速部署,解放运维并提高工作效率,尤其在创业之初人力资源不足的情况下,更为重要。为此我和公司一位开发同学一起研究的关于Docker快速部署应用的解决方案架构,下面是整个方案部署的步骤,由于资源有限过程中有问题还望大家指正交流,谢谢!


1)安装docker软件,部署说明中需要docker环境的都需要先安装软件,命令如下:
systemctl stop firewalld;systemctl disable firewalld setenforce 0 sed -i s/^SELINUX=enforcing/SELINUX=permissive/ /etc/selinux/config #设置Selinux为允许或者直接关闭。 yum install docker -y vi /etc/sysconfig/docker OPTIONS='--selinux-enabled --insecure-registry docker.smart.com' #添加docker仓库信任 systemctl start docker #启动docker服务
2)配置DNS解析smart.com区域文件
DNS服务器配置过程略。
192.168.10.200 docker.smart.com #解析仓库域名服务器 echo nameserver 192.168.10.86 >>/etc/resolv.conf #修改所有服务器域名服务器地址
3)配置Docker仓库
/data/docker/registry #创建docker运行映射目录 docker pull index.alauda.cn/juqkai/registry #灵雀云拉一个仓库镜像 docker tag index.alauda.cn/juqkai/registry docker.smart.com/base/registry #修改标签 docker run -d --restart=always -p 80:5000 -v /data/docker/registry:/tmp/registry-dev docker.smart.com/juqkai/registry #运行registry服务 docker push docker.smart.com/base/registry #将本地镜像推送到仓库 curl http://docker.smart.com/v1/search #查看仓库中的相关镜像(可以使用Python json模块转换| python -m json.tool) (可以按照此方法将Jenkins、nginx、zookeeper等镜像拉下来并推送到docker.smart.com仓库)
4)配置zookeeper
mkdir /data/docker/zookeeper/conf -p #创建配置文件映射目录(统一将docker运行的软件配置文件放到这个目录)
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/tmp/zookeeper clientPort=2181 server.1=0.0.0.0:2888:3888 server.2=zk2.paas.smart.com:2888:3888 server.3=zk3.paas.smart.com:2888:3888
echo "1" > /data/docker/zookeeper/data/myid
5)配置mesos-master和mesos-slave
rpm -i http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm yum -y install mesos mesos-master --ip=192.168.10.203 --hostname=master1.paas.smart.com --work_dir=/var/lib/mesos --quorum=1 --log_dir=/var/log/mesos --port=5050 --zk_session_timeout=120secs --zk=zk://zk1.paas.smart.com:2181,zk2.paas.smart.com:2181,zk3.paas.smart.com:2181/mesos #启动master
mesos-slave --ip=192.168.10.136 --hostname=192.168.10.136 --log_dir=/var/log/mesos --containerizers=docker,mesos --master=zk://zk1.paas.smart.com:2181,zk2.paas.smart.com:2181,zk3.paas.smart.com:2181/mesos --executor_registration_timeout=5mins #启动slave 首次启动均在前台,没有问题可以使用nohup放到后台。
6)配置marathon平台
rpm -i http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm yum -y install mesos marathon java
echo "export LIBPROCESS_IP=192.168.10.124" >> /etc/profile source /etc/profile #IP为本机的IP地址 bin/start --master zk://zk1.paas.smart.com:2181,zk2.paas.smart.com:2181,zk3.paas.smart.com:2181/mesos --zk zk://zk1.paas.smart.com:2181,zk2.paas.smart.com:2181,zk3.paas.smart.com:2181/marathon --hostname 192.168.10.124 --framework_name smart #启动服务,hostname为主机IP或本机主机名
7)配置consul集群
#将consul可执行文件放到/usr/bin目录下
mkdir /usr/local/consul/conf
#创建consul配置文件目录
cat /usr/local/consul/conf/config.conf
{
"datacenter": "diliPAAS"
,"data_dir": "/usr/local/consul/data"
,"log_level": "INFO"
,"node_name": "master1"
,"server": true
,"retry_join":["192.168.10.210","192.168.10.184","192.168.10.152","192.168.10.136"]
,"rejoin_after_leave":true
,"client_addr":"192.168.10.203"
}
#retry_join IP为各个consul节点的IP,client_addr为本机IP地址,server为工作模式。
consul agent -node=master1 -server -bootstrap -data-dir=/usr/local/consul/data -dc=diliPAAS
#前台首次启动命令,需要指定consul相关数据存放目录,当启动其他consul之后可以使用如下命令启动
nohup consul agent -config-file=config.conf >consul.out&
consul members -rpc-addr=192.168.10.210:8400
#查看consul集群情况,其中rpc-addr为任意节点consul IP. 8)nginx配置
mkdir /data/docker/nginx/conf/ #创建nginx配置映射目录,ssl等文件也放在这个目录 docker run -d --name nginx -p 80:80 -v /data/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf index.alauda.cn/library/nginx #从灵雀云拉的镜像运行,如果之前拉过并push到仓库,可以从我们之前放到docker.smart.com仓库中拉去。
9.配置consul-template来动态发现注册服务。
cat /data/docker/nginx/conf/nginx.conf.tmpl
#nginx配置模板文件
{{$model:="test"}}
worker_processes 1;
events {
worker_connections 65535;
}
http {
#lua_code_cache off;
client_max_body_size 1G;
server_names_hash_bucket_size 64;
upstream marathon {
server 192.168.10.186:8080;
server 192.168.10.124:8080;
}
server {
server_name marathon1.paas.smart.com;
listen 80;
location / {
proxy_pass http://marathon;
}
}
upstream registry {
server 192.168.10.200:80;
}
server {
server_name docker.smart.com;
listen 80;
location / {
proxy_pass http://registry;
}
}{{range services}}
{{$nameArr := .Name | split "-"}}
{{if gt (len $nameArr) 1}}
{{if eq $model (index $nameArr 1)}}
{{$name := (index $nameArr 0)}}
{{if service .Name }}
upstream {{.Name}} { {{range service .Name}}
server {{.Address}}:{{.Port}};#{{range .Tags}}{{.}},{{end}}{{end}}
}
server {
server_name {{$name}}.smart.com;
listen 80;
location / {
proxy_pass http://{{.Name}};
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
{{if eq $name "passport"}}
upstream {{.Name}}ssl { {{range service .Name}}
server {{.Address}}:{{.Port}};{{end}}
}
server {
server_name {{$name}}.smart.com;
listen 443;
ssl on;
ssl_certificate smart_server.pem;
ssl_certificate_key smart_server.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://{{.Name}}ssl;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
{{end}}
{{end}}
{{end}}
{{end}}
{{end}}
}
#nginx配置文件模板文件内容
mkdir -p /usr/local/consul-template/
#创建consul-template 配置文件目录
cat nginx.tmpl.conf
consul="192.168.10.203:8500"
template {
source="/data/docker/nginx/conf/nginx.conf.tmpl"
destination="/data/docker/nginx/conf/nginx.conf"
command="docker exec nginx nginx -s reload >> /dev/null"
}
#其中consul中的IP为mesos-master
nohup consul-template -config=./nginx.tmpl.conf &
#启动consul-template更新nginx服务 cat /var/named/smart.com.zone.tmp
#DNS区域文件模板
{{$model:="test"}}
$TTL 1D
@ IN SOA @ rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS @
A 127.0.0.1
AAAA ::1
@ IN NS ns.smart.com.
{{$ips:=file "/var/named/smart.json" |parseJSON}}
{{range services}}
{{$nameArr := .Name | split "-"}}
{{if gt (len $nameArr) 1}}
{{if eq $model (index $nameArr 1)}}
{{$name := (index $nameArr 0)}}
{{$name}} IN A 192.168.10.177
{{end}}
{{end}}
{{end}}
{{range $k,$v := $ips}}{{$kn := $k|regexReplaceAll "$" "-"|regexReplaceAll "$" $model}}{{$sk := service $kn}}{{$l:=len $sk}}{{if $l}}{{else}}
{{$k}} IN A {{$v}}{{end}}{{end}}
#由于系统需要调用外部资源所以增加外部固定资源DNS A记录 smart.json
cat /var/named/smart.json
{
"ns":"192.168.10.86"
,"zk1.paas":"192.168.10.160"
,"zk2.paas":"192.168.10.150"
,"zk3.paas":"192.168.10.209"
,"master1.paas":"192.168.10.203"
,"master2.paas":"192.168.10.210"
,"docker":"192.168.10.200"
,"cms":"192.168.6.54"
,"supplier":"192.168.6.54"
,"user":"192.168.6.54"
,"www":"192.168.6.54"
,"manweb":"192.168.6.54"
,"passport":"192.168.6.54"
,"authcode":"192.168.6.54"
,"shop":"192.168.6.54"
,"manage":"192.168.6.54"
,"upload":"192.168.6.53"
,"chat":"192.168.6.53"
,"csc":"192.168.6.53"
,"titan":"192.168.6.53"
,"orders":"192.168.6.53"
,"static":"192.168.6.53"
"smart.json" 51L, 1157C
,"mapi.pay":"192.168.6.53"
,"pay2":"192.168.6.53"
,"sso":"192.168.6.54"
,"group-admin":"192.168.6.54"
,"group":"192.168.6.54"
,"group-orders":"192.168.6.54"
,"img0":"192.168.6.153"
,"img1":"192.168.6.153"
,"img2":"192.168.6.153"
,"img3":"192.168.6.153"
,"img4":"192.168.6.153"
,"img5":"192.168.6.153"
,"img6":"192.168.6.153"
,"img7":"192.168.6.153"
,"img8":"192.168.6.153"
,"img9":"192.168.6.153"
,"cashier.pay":"192.168.6.53"
,"schedule":"192.168.4.14"
,"dp":"192.168.4.211"
,"apd":"192.168.6.54"
,"marathon":"192.168.10.177"
,"jenkins":"192.168.10.161"
,"leader.paas":"192.168.10.177"
}
#添加consul-template更新DNS的配置文件
cat /usr/local/consul-template/bind.conf
consul="192.168.10.184:8500"
template {
source="/var/named/smart.com.zone.tmp"
destination="/var/named/smart.com.zone"
command="chown root.named /var/named/smart*;/etc/init.d/named restart"
}
nohup consul-template -config=./bind.conf >dns.out &
#运行DNS的consul-template服务
10)配置Jenkins
docker run -it --rm -p 80:8080 -v /data/docker/jenkins:/var/jenkins_home -v /data/docker/jenkins/maven:/home/anonymous/.m2 docker.smart.com/base/jenkins
cat /data/docker/jenkins/upload_file
#jenkins 编译完成之后推送脚本
#!/bin/bash
dcpu=${cpu:="0.4"}
dmem=${mem:="512"}
dins=${ins:="1"}
model="test"
#sysName="www"
#BUILD_NUMBER="1"
#sysDir="/data/docker/jenkins/workspace/www/diligrp-website-web/target/diligrp-website-web"
sysName=${JOB_NAME}
[email protected]
sysTmp=$(find ${WORKSPACE} -name ${filename:=*.war})
sysDir=${sysTmp/'.war'/}
echo "war path: ${sysDir}"
upload_file()
{
ssh -nq $HOST "[ -d /tmp/${sysName} ] && rm -rf /tmp/${sysName} >>/dev/null ; mkdir -p /tmp/${sysName}"
ssh -nq $HOST "mkdir -p /tmp/${sysName} "
scp -r ${sysDir}/* $HOST:/tmp/${sysName}
ssh -nq $HOST "sh /usr/bin/Docker_Build ${sysName} ${BUILD_NUMBER} ${dcpu} ${dmem} ${dins} ${model}"
}
upload_file
11)配置Docker Build服务
cat /usr/bin/Docker_Build
#!/bin/bash
cpu=$3
mem=$4
ins=$5
sysName=$1
BUILD_NUMBER=$2
model=$6
#sysTmp=$(find / -name ${filename:=*.war})
#sysDir=${sysTmp/'.war'/}
sysDir=/tmp/$1
echo "war path: ${sysDir}"
if [ ! -f "${sysDir}/Dockerfile" ]; then
#дDockerfile
echo "FROM docker.smart.com/base/tomcat
RUN rm -rf /usr/local/tomcat/webapps/ROOT/*
ADD ./ /usr/local/tomcat/webapps/ROOT
" > ${sysDir}/Dockerfile
fi
dockerPath=docker.smart.com/front/$sysName:${BUILD_NUMBER}
cd ${sysDir}
docker build -t ${dockerPath} .
docker push ${dockerPath}
curl -X DELETE -H "Content-Type: application/json" http://marathon1.paas.smart.com/v2/apps/${model}/${sysName}
sleep 20
if [ ! -f "${sysDir}/app_marathon.json" ]; then
cat << EOF >${sysDir}/app_marathon.json
{"id": "/${model}/${sysName}","container": {"docker":{"image":"${dockerPath}","network": "BRIDGE","parameters":[{"key":"dns", "value": "192.168.10.86"}],"portMappings": [{"containerPort": 8080}]}},"cpus": ${cpu},"mem": ${mem},"instances": ${ins}}
EOF
fi
curl -X POST -H "Content-Type: application/json" http://marathon1.paas.smart.com/v2/apps -d@${sysDir}/app_marathon.json
sleep 5
cd /
rm -rf ${sysDir} 更多Docker相关教程见以下内容:
平台部署遇到的一些坑: