启动docker容器

#!/bin/bash

#descrition:
#启动容器
#2016.09.29支持挂载文件
#
#precondition:mir envionment variables example
#export ENV_ETCD_SERVER_URL=http://172.16.70.73:2379,http://172.16.70.74:2379
#export containerName=tomcat8
#export imageName=hub.chinacloud.com/mir/tomcat:8
#export ETCD_CD_PHASE_LOG_DIR=mir/cicd/cd-phase-log/
#export ETCD_TTL=2592000
#DOCKER_OPTIONS_MOUNT_INFO="file_key1:/usr/vFile/setConfig1.xml;file_key2:/usr/vFile/setConfig2.xml;file_key3:/usr/vFile/setConfig3.xml"
#export ETCD_CDEVENT_JSON=eyJraW5kIjoiQ0RFdmVudCIsIm1ldGFkYXRhIjp7ImV2ZW50SWQiOiJmYjUxOWExMy1hN2M2LTQxODAtYjE2My00ZjJmZmUxZTc4NjgiLCJuYW1lIjoicHRvbWNhdC0xMTExMTFfQ0RFdmVudCJ9LCJzcGVjIjp7ImRlcGxveUluZm8iOnsiYXBwRW52IjoiMTAzIiwiZGVwbG95SWQiOiI5Y2EzNDFjM2E5OWQxMTEiLCJlbnZab25lIjoiMiIsImVudnMiOnsiTVlTUUxfUEFTU1dPUkQiOiJodWFjbG91ZCIsIk1ZU1FMX1VSTCI6Im15c3FsMTExMTExMTExIiwiTVlTUUxfVVNFUiI6InJvb3QifSwiaW1hZ2UiOiJodWIuY2hpbmFjbG91ZC5jb20vbWlyL3RvbWNhdCIsInRhZyI6IjgifSwicHJvamVjdEluZm8iOnsicHJvamVjdElkIjoiNThkYjFjMDlhMDU2Yzc2YWQwM2NkNmI4NGYzMmY4NjUzMDMwOWM5MWRiNWZkNjMxZTk0ZmRiYzUwMmIyY2YyOCIsInByb2plY3ROYW1lIjoiaGVsbG9fdG9tY2F0In19LCJ2ZXJzaW9uIjoiMSJ9
#export containerEnvs=
#export CD_DEPLOY_ID=a4da53eb-6c3b-41af-b4cc-d9b71287a7b5
#export CD_EVENT_ID=a4da53eb-6c3b-41af-b4cc-d9b71287a7b5
#steps:
#1.校验ETCD SERVER是否可用
#2.docker run
#3.发送CD-Phase-LOG finish


ETCD_SERVER_URL=$ENV_ETCD_SERVER_URL
#EVENT_ID=""
EFFECTIVE_ETCD_SERVER_URL=""
EXE_RES="0"
DOCKER_OPTIONS_P=""
DOCKER_OPTIONS_V=""
DOCKER_CONTAINER_NAME=""
#当容器挂载文件更新时,1:重启所有label=namespace=app容器 0:不重启
DOCKER_RESTART_WHEN_CONF_UPDATE="0"
LOG_SEQ_NUM=0
APPLICATION_ADDR=""
VM_IP=""

getVmIp() {
	if [ "$SCALR_EXTERNAL_IP" != "" ]
	then
		VM_IP=$SCALR_EXTERNAL_IP
	elif [ "$SCALR_INTERNAL_IP" != "" ]
	then
		VM_IP=$SCALR_INTERNAL_IP
	fi
	log "$LINENO" "DEBUG" "VM_IP is $VM_IP"
	
	#替换容器名称中的非法字符'/'
	DOCKER_CONTAINER_NAME=$(echo ${containerName##*/})
	if [ "$DOCKER_CONTAINER_NAME" == "" ]
	then
		DOCKER_CONTAINER_NAME=$(echo $containerName | sed 's/\//_/g')
	fi
}

#function 生成eventId
generateEventId(){
	EVENT_ID=`cat /proc/sys/kernel/random/uuid`
	log "$LINENO" "DEBUG" "generate eventId > $EVENT_ID"
}

#$1:$LINENO
#$2:ERROR/DEBUG/INFO
#$3:MSG
log(){
	currentTimeStamp=`date "+%Y-%m-%d %H:%M:%S"`
	#currentTimeStamp=`date -d "$Time" +%s`
	#currentTimeStamp=`date +%s`
	((LOG_SEQ_NUM=LOG_SEQ_NUM+1));
	echo "$LOG_SEQ_NUM $currentTimeStamp sh:docker-run.sh $CD_DEPLOY_ID $CD_EVENT_ID lineNo:$1 $2::$3::" >> /var/log/docker_run_debug.log
}

deploymentFailure() {
	log "$LINENO" "INFO" "step-4 send cicd-cd phase finish log."
	sendCDPhaseLog "finish" "failed"
	log "$LINENO" "INFO" "step-4 send cicd-cd phase finish log. done"
	log "$LINENO" "INFO" "finished, deployment failure."
}

#校验ETCD SERVER是否可用
checkEtcdServer(){
	arr=(${ETCD_SERVER_URL//,/ })
	for ETCD_URL in ${arr[@]}
	do
		ETCD_VERSION=`curl -L $ETCD_URL/version`
		if [ "$ETCD_VERSION" = "" ]
		then
			EXE_RES="1"
			log "$LINENO" "ERROR" "$ETCD_URL unknow etcd server" 
		else
			EFFECTIVE_ETCD_SERVER_URL=$ETCD_URL
		fi
	done
	if [ "$EFFECTIVE_ETCD_SERVER_URL" = "" ]
	then
		EXE_RES="1"
		log "$LINENO" "ERROR" "No etcd service available."
		deploymentFailure
		exit 0
	fi
	log "$LINENO" "DEBUG" "effective etcd server > $EFFECTIVE_ETCD_SERVER_URL"
}

#发送CD-Phase-LOG
#$1:finish
#$2:failed/success
sendCDPhaseLog(){
	true > /var/log/etcd_event_msg.txt
	echo "'$ETCD_CDEVENT_JSON'" | python -c "import json,base64,sys;obj=json.loads(base64.b64decode(sys.stdin.read()));obj['shellName']='docker-run.sh';obj['step']='$1';obj['stepStatus']='$2';obj['vmServerId']='$SCALR_SERVER_ID';obj['vmIp']='$VM_IP';print json.dumps(obj)" >> /var/log/etcd_event_msg.txt
	
	#generateEventId
	if [ "$ETCD_TTL" = "" ]
	then
		ETCD_TTL = 2592000
	fi
	LOG_MSG=`curl -L $EFFECTIVE_ETCD_SERVER_URL/v2/keys/$ETCD_CD_PHASE_LOG_DIR$CD_EVENT_ID/$VM_IP -XPUT -d ttl=$ETCD_TTL --data-urlencode value@/var/log/etcd_event_msg.txt`
	log "$LINENO" "DEBUG" "send cd-phase-event[step:$1,stepStatus:$2]. event msg content > $LOG_MSG"
}


#$1:REPOSITORY
#$2:TAG
i=0
checkImage() {
	((i=i+1));
	if [ "$i" = 15 ]
	then
		log "$LINENO" "ERROR" "Image download failure."
		deploymentFailure
		exit 0
	fi
	#log "$LINENO" "DEBUG" "$i $1---$2"
	
	IMAGE_ID=`docker images | grep $1 | grep $2 | awk '{print $3}'`
	if [ "$IMAGE_ID" = "" ]
	then
		sleep 10s
		checkImage "$1" "$2"
	else
		log "$LINENO" "DEBUG" "Status:Downloaded newer image for $1:$2"
	fi
}

#下载镜像
#return -p 2379:2379 -l "SERVICE_2379_NAME=/mir/appmnt/stacks/$SCALR_FARM_ID/$SCALR_FARM_ROLE_ID/$DOCKER_CONTAINER_NAME" -l "SERVICE_2379_ID=$VM_IP:2379" 
downloadImage() {
	imageName=$(echo $imageName | sed 's/\\//g')
	log "$LINENO" "DEBUG" "docker pull $imageName"
	docker pull $imageName
	arr=(${imageName//:/ })
	checkImage "${arr[0]}" "${arr[1]}"
	
	#解析dockerFile 端口号
	log "$LINENO" "DEBUG" "docker inspect $imageName"
	ports=`docker inspect $imageName | python -c "import json,sys;obj=json.loads(sys.stdin.read());keys=obj[0]['Config']['ExposedPorts'].keys();print ','.join([key.split('/')[0] for key in keys]);"`

	list=(${ports//,/ })
	for port in ${list[@]}
	do
		DOCKER_OPTIONS_P="$DOCKER_OPTIONS_P -p $port:$port -l SERVICE_${port}_NAME=\"/mir/appmnt/stacks/$SCALR_FARM_ID/$SCALR_FARM_ROLE_ID/$DOCKER_CONTAINER_NAME\" -l SERVICE_${port}_ID=$VM_IP:$port"
		
		APPLICATION_ADDR="$APPLICATION_ADDR http://$VM_IP:$port; "
	done
	log "$LINENO" "DEBUG" "parse port parameters:$DOCKER_OPTIONS_P"
}

#配置并启动confd服务
startConfd() {
	#停止confd
	PID_CONFD=`ps -ef | grep /opt/confd |grep -v grep | awk '{print $2}'`
	if [ "$PID_CONFD" != "" ]
	then
		kill -9 $PID_CONFD
		log "$LINENO" "DEBUG" "killed confd, pid=$PID_CONFD."
	fi
	
	#清除模版文件
	rm -rf /etc/confd/templates/*
	rm -rf /etc/confd/conf.d/*
	rm -rf /opt/mir-cicd/conf/managerment/*
	log "$LINENO" "DEBUG" "delete all confd template file."
	sleep 1s
	
	#{etcdFileContentKey1}:{containerFilePath1}:{fileName1};{etcdFileContentKey2}:{containerFilePath2}:{fileName2}
	#DOCKER_OPTIONS_MOUNT_INFO=51000000-0000-0000-0000-000000000000/setConfig1:/usr/vFile:setConfig1.xml;51000000-0000-0000-0000-000000000000/setConfig2:/usr/vFile:setConfig2.xml
	list=(${DOCKER_OPTIONS_MOUNT_INFO//;/ })
	for arr in ${list[@]}
	do
		mountInfo=(${arr//:/ })
		#mountInfo[0]为etcdKey,如:51000000-0000-0000-0000-000000000000/setConfig1
		#mountInfo[1]为容器内挂载路径,如:/usr/vFile
		#mountInfo[2]为配置文件名,如:setConfig1.xml
		log "$LINENO" "DEBUG" "mount file etcdKey:/mir/cicd/config/manager/${mountInfo[0]}"
		etcdKey=(${mountInfo[0]//\// })
		
		cp /etc/confd/mir_conf_management_source/mir_cicd_conf_manager.tmpl /etc/confd/templates/mir_cicd_conf_manager_${etcdKey[1]}.tmpl
		#修改读取etcd key
		sed -i "s#etcd_key#${mountInfo[0]}#g" /etc/confd/templates/mir_cicd_conf_manager_${etcdKey[1]}.tmpl
		log "$LINENO" "DEBUG" "generate file>/etc/confd/templates/mir_cicd_conf_manager_${etcdKey[1]}.tmpl"
		
		cp /etc/confd/mir_conf_management_source/mir_cicd_conf_manager.toml /etc/confd/conf.d/mir_cicd_conf_manager_${etcdKey[1]}.toml
		#修改生成目标文件名
		sed -i "s#mir_cicd_conf_manager_etcd_key.conf#${mountInfo[2]}#g" /etc/confd/conf.d/mir_cicd_conf_manager_${etcdKey[1]}.toml
		#修改模版文件名
		sed -i "s#mir_cicd_conf_manager_etcd_key.tmpl#mir_cicd_conf_manager_${etcdKey[1]}.tmpl#g" /etc/confd/conf.d/mir_cicd_conf_manager_${etcdKey[1]}.toml
		#修改监听key
		sed -i "s#\/etcd_key#\/${mountInfo[0]}#g" /etc/confd/conf.d/mir_cicd_conf_manager_${etcdKey[1]}.toml
		if [ "$DOCKER_RESTART_WHEN_CONF_UPDATE" == "0" ]
		then
			#当容器挂载文件更新时,1:重启所有label=namespace=app容器 0:不重启
			sed -i "s/reload_cmd/#reload_cmd/g" /etc/confd/conf.d/mir_cicd_conf_manager_${etcdKey[1]}.toml
		fi
		log "$LINENO" "DEBUG" "generate file>/etc/confd/conf.d/mir_cicd_conf_manager_${etcdKey[1]}.toml"
		
		DOCKER_OPTIONS_V="$DOCKER_OPTIONS_V -v /opt/mir-cicd/conf/managerment:${mountInfo[1]}"
	done
	
	log "$LINENO" "DEBUG" "DOCKER_OPTIONS_V:$DOCKER_OPTIONS_V"
	/opt/confd -backend etcd -node $EFFECTIVE_ETCD_SERVER_URL -log-level debug -watch true &
	
	#检测配置文件是否生成
	for arr in ${list[@]}
	do
		iFile=0
		mountInfo=(${arr//:/ })
		#mountInfo[0]为etcdKey,如:51000000-0000-0000-0000-000000000000/setConfig1
		#mountInfo[1]为容器内挂载路径,如:/usr/vFile
		#mountInfo[2]为配置文件名,如:setConfig1.xml
		etcdKey=(${mountInfo[0]//\// })
		
		filename="/opt/mir-cicd/conf/managerment/${mountInfo[2]}"
		log "$LINENO" "DEBUG" "Check the configuration file exists > $filename; etcd key:${etcdKey[1]}"
		checkConfFile "$filename" "${etcdKey[1]}"
	done
}

iFile=0
checkConfFile(){
	((iFile=iFile+1));
	if [ "$iFile" = 15 ]
	then
		log "$LINENO" "ERROR" "etcd configuration file does not exist > $2."
		deploymentFailure
		exit 0
	fi
	
	if [ -f "$1" ]
	then 
		#文件存在,删除第一行
		sed -i '1d' "$1"
	else
		#文件不存在
		sleep 1s
		checkConfFile "$1" "$2"
	fi
}


#docker run
dockerRun(){
	#判断是否启动confd服务
	if [ "$DOCKER_OPTIONS_MOUNT_INFO" != "" ]
	then
		startConfd
	fi
	
	log "$LINENO" "DEBUG" "docker run -d --name $DOCKER_CONTAINER_NAME --net=host -l namespace=app -e HOST_IP=$VM_IP $containerEnvs $DOCKER_OPTIONS_V -v /etc/localtime:/etc/localtime:ro $DOCKER_OPTIONS_P --restart always $imageName"
	#IFS=''
	cmd="docker run -d --name $DOCKER_CONTAINER_NAME --net=host -l namespace=app -e HOST_IP=$VM_IP $containerEnvs $DOCKER_OPTIONS_V -v /etc/localtime:/etc/localtime:ro $DOCKER_OPTIONS_P --restart always $imageName"
	mkdir -p /tmp/mir-cicd/cd
	true > /tmp/mir-cicd/cd/cd.sh
	echo "$cmd" >> /tmp/mir-cicd/cd/cd.sh
	bash /tmp/mir-cicd/cd/cd.sh
	
	sleep 2s
	CONTAINER_ID=`docker ps | grep $DOCKER_CONTAINER_NAME | awk '{print $1}'`
	if [ "$CONTAINER_ID" = "" ]
	then
		EXE_RES="1"
		log "$LINENO" "ERROR" "Failed to start the container."
		deploymentFailure
		exit 0
	else
		log "$LINENO" "DEBUG" "Start the container successfully.CONTAINER_ID > $CONTAINER_ID"
	fi
}


deleteInf() {
	#删除所有容器(标签:namespace=app)
	log "$LINENO" "DEBUG" "Delete all contain the namespace=app container"
	docker rm -f `docker ps -a -q --filter "label=namespace=app"`
	
	sleep 1
	
	#imageName=$(echo $imageName | sed 's/\\//g')
	#log "$LINENO" "DEBUG" "delete image > $imageName"
	#docker rmi $imageName
	log "$LINENO" "DEBUG" "delete all image"
	docker rmi `docker images |grep -v gliderlabs/registrator |awk -F ' ' '{print$3}'|grep -v "IMAGE"`
}



#检查logstash服务状态
i_logstash=0
checkLogstashStatus() {
	((i_logstash=i_logstash+1));
	if [ "$i_logstash" = 10 ]
	then
		log "$LINENO" "ERROR" "logstash hasn't been started."
		deploymentFailure
		exit 0
	fi
	
	LOGSTASH_PROCESS_NUM=`ps -ef | grep /opt/logstash-2.3.3 |grep -v grep | awk '{print $2}'`
	if [ "$LOGSTASH_PROCESS_NUM" = "" ]
	then
		sleep 10s
		checkLogstashStatus
	else
		log "$LINENO" "DEBUG" "logstash process number is $LOGSTASH_PROCESS_NUM."
	fi
	
	sleep 3s
}


main(){
	log "$LINENO" "INFO" "deploy start."
	
	getVmIp
	
	#1.检查logstash服务状态
	log "$LINENO" "INFO" "step-1 check logstash. start"
	checkLogstashStatus
	log "$LINENO" "INFO" "step-1 check logstash. done"
	
	#2.校验ETCD SERVER是否可用
	log "$LINENO" "INFO" "step-2 check etcd-server. start"
	checkEtcdServer
	log "$LINENO" "INFO" "step-2 check etcd-server. done"
	
	#3.删除容器&当前容器镜像
	log "$LINENO" "INFO" "step-3 clear envionmental information. start"
	deleteInf
	log "$LINENO" "INFO" "step-3 clear envionmental information. done"
	
	#4.下载容器镜像
	log "$LINENO" "INFO" "step-4 download docker image. start"
	downloadImage
	log "$LINENO" "INFO" "step-4 download docker image. done"
	
	#5.启动容器
	log "$LINENO" "INFO" "step-5 start the container. start"
	dockerRun
	log "$LINENO" "INFO" "step-5 start the container. done"
	
	#6.发送CD-Phase-LOG finish
	if [ "$EXE_RES" = "1" ]
	then
		deploymentFailure
	else
		log "$LINENO" "INFO" "step-6 send cicd-cd phase finish log. start"
		sendCDPhaseLog "finish" "success"
		log "$LINENO" "INFO" "step-6 send cicd-cd phase finish log. done"
		log "$LINENO" "INFO" "finished, deployment successful.$APPLICATION_ADDR"
	fi
	
}

main
         
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值