#!/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
启动docker容器
最新推荐文章于 2024-05-02 01:02:35 发布