在Docker容器中部署安卓应用apk的自动化流程

安卓应用apk部署到Docker中,并自动检测容器状态,根据容器的状态(unhealthy、Created、Exited、不在docker ps -a列表等)自动重启容器,并自动完成配置文件的设定,自动安装(安装这一步,在commit时,会自动集成到镜像,创建容器时,自动完成)、自动运行等。

一、基础信息

Docker服务器IP地址:10.11.*.*
登录账号:account
登录密码:*******
apk安装包和相关的数据配置打包成:release.zip

二、自定义镜像

1、拷贝文件到Docker服务器

  scp ***/release.zip account@ip:/home/account/

2、登录命令

  ssh account@ip
  sudo su -

3、拉取镜像创建容器ad1

  docker run --privileged -d -p 6001:6080  -e DEVICE="Nexus 7" --name ad1 budtmo/docker-android-x86-7.0

4、拷贝文件到容器

  cp /home/account/release.zip ad1:/root/

5、解压release.zip

  unzip release.zip

6、安装apk

  adb install -r release/networknode1.apk
  adb install -r release/networknode2.apk
  adb install -r release/networknode3.apk
  adb install -r release/networknode4.apk
  adb install -r release/networknode5.apk

7、拷贝配置文件到指定目录(如有必要)

  cp release/config.ini /sdcard/myconfig/config.ini

8、访问设备,确认权限

  在浏览器中访问:ip:6001
  找到刚才安装的5个apk,分别为这些apk设置访问权限(打开app,按照弹出框提示,确认授权即可)

9、提交镜像

  docker commit ad1 'xhs/7.0'

10、容器量产

docker run --privileged -d -p 6001:6080  -e DEVICE="Nexus 7" --name ad1 xhs/7.0
docker run --privileged -d -p 6002:6080  -e DEVICE="Nexus 7" --name ad2 xhs/7.0
docker run --privileged -d -p 6003:6080  -e DEVICE="Nexus 7" --name ad3 xhs/7.0
docker run --privileged -d -p 6004:6080  -e DEVICE="Nexus 7" --name ad4 xhs/7.0
docker run --privileged -d -p 6005:6080  -e DEVICE="Nexus 7" --name ad5 xhs/7.0

三、自动化监测

1、目标

1、监测坏死、不健康的容器,如果有必要则kill掉非正常状态的容器,并重新自动创建新的容器,并为其自动设置好app需要的数据文件;
2、利用代码自动运行app,并对模拟器中的配置文件进行纠错。

2、创建自动化脚本

将下面代码保存到文件,并将其放到指定目录(按自己需求,如:/home/account/docker/autosh/dockermonitor)

#!/bin/sh
now=`date +%Y%m%d.txt`
logPath="/home/account/docker/logs/log"$now
echo $logPath >> $logPath
containerStartIndx=1    #容器起始编号:ad1
containerEndIndex=5    #容器结束编号: ad5

log() {
    echo $1 >> $logPath
}

removeContainer() {
    for((i=$1;i<=$2;i++)); do
        adn=ad${i}
        docker kill $adn
        docker rm $adn
    done
}

setEnv() {
    info=`docker exec -it $adx adb shell "ls /sdcard/myconfig/ | tr '\n' ' '"`
    if [[ $info =~ "config$1.ini" ]]; then
        log "$adx /sdcard/myconfig/路径下包含config$1.ini"
        for((idx=1;idx<=5;idx++)); do
            log "docker exec -it $adx adb shell am start -n com.im.datacollect.networknode$idx/com.im.datacollect.networknode$idx.MainActivity"
            docker exec -it $adx adb shell am start -n com.im.datacollect.networknode$idx/com.im.datacollect.networknode$idx.MainActivity
        done
    elif [[ $info =~ ".ini" ]]; then
        log "$adx /sdcard/myconfig/路径下包含.ini"
        strconf=$(docker exec -it $adx adb shell "ls /sdcard/myconfig/ | tr '\n' ' '")
        log $strconf
        array=(`echo $strconf` ) 
        for((m=0;m<${#array[@]};m++)) do
            config=${array[$m]};
            configval="config$1.ini"
            if [ $config != $configval ]; then
                log "docker exec -it $adx adb shell mv /sdcard/myconfig/$config /sdcard/myconfig/config$1.ini"
                docker exec -it $adx adb shell mv /sdcard/myconfig/$config /sdcard/myconfig/config$1.ini
            fi
        done
        for((idx=1;idx<=5;idx++)); do
            log "docker exec -it $adx adb shell am start -n com.im.datacollect.networknode$idx/com.im.datacollect.networknode$idx.MainActivity"
            docker exec -it $adx adb shell am start -n com.im.datacollect.networknode$idx/com.im.datacollect.networknode$idx.MainActivity
        done
    else
        log "异常"
    fi
}

str=$(docker ps -a | sed 's/[ ]\{1,10\}/||/g')
list=(${str/\n/ })  

log "list长度:"${#list[@]}

for((j=$containerStartIndx;j<=$containerEndIndex;j++)); do
    exist="0"  
    adx=ad$j
    log "adx:"$adx
    for(( i=1;i<${#list[@]};i++)) do
        item=${list[$i]};
        ad=$(echo $item | awk -F\| '{print $NF}')
        log "ad:"$ad
        if [[ $ad = $adx ]]; then
            exist="1"
            log "item:"$item;
            log "$adx已存在:$ad"
            if [[ $item =~ "unhealthy" ]]||[[ $item =~ "Created" ]]; then
                log "$adx需要重启,重启中……: docker restart $adx"
                rs=`docker restart $adx`
                sleep 2m
            elif [[ $item =~ "Exited" ]]; then
                # 无法重启的报错:Error response from daemon: Cannot restart container
                # if [[ $rs =~ "Error response from daemon: Cannot restart container" ]]; then
                log "重启失败,即将删除容器,并重建:docker rm $adx"
                docker rm $adx
                exist="0"
            else
                log "正常运行中, 或starting 或 healthy"
            fi
            log "exist1:"$exist
            break
        fi
    done
    log "exist2:"$exist
    if [ $exist = "0" ]; then
        log "$adx没有启动,启动中……"
        if (($j<10));then
            log "docker run --privileged -d -p 600$j:6080  -e DEVICE='Nexus 5' --name $adx xhs/7.0"
            docker run --privileged -d -p 600$j:6080  -e DEVICE='Nexus 5' --name $adx xhs/7.0
        else
            log "docker run --privileged -d -p 60$j:6080  -e DEVICE='Nexus 5' --name $adx xhs/7.0"
            docker run --privileged -d -p 60$j:6080  -e DEVICE='Nexus 5' --name $adx xhs/7.0
        fi
        sleep 2m

        log "重命名完成!"
    fi
    setEnv $j
    
done

3、将刚才的自动化脚本放到定时任务队列中,开启循环执行

  • 进入循环任何队列(初次进入会出现编辑器选择,按照个人习惯,本人选择的是vi)
  crontab -e
  • 在顶部加入刚才的自动化脚本,如下
GNU nano 5.2                                                                 /tmp/crontab.fGOhnz/crontab                                                                           
# 每两小时执行一次,文件路径替换成自己的真实路径
0 */2 * * * /bin/sh /home/account/docker/autosh/dockermonitor

# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
  • 重启cron,让修改的队列立即生效
  sudo service cron restart
  • 相关命令:
sudo service cron start
sudo service cron stop
sudo service cron reload

我的Docker服务器是ubantu,对应的是cron,有的系统则是crond,本人没有细究,如果上述命令不行,可以试试:

  sudo service crond start         # 开启服务
  sudo service crond stop         # 关闭服务
  sudo service crond restart       # 重启服务
  sudo service crond reload       # 重新载入配置

crond报错:
Failed to restart crond.service: Unit crond.service not found.
则换成:sudo service cron restart

你可能感兴趣的:(在Docker容器中部署安卓应用apk的自动化流程)