docker 虚拟化工具
docker 的一些基本命令
例子
docker 镜像 ,容器是从镜像启动的起点环境
docker 容器,虚拟化的运行单位
dockerfile 打镜像工具 格式规范
格式,例子
docker-compose 管理容器工具 格式规范
格式,例子
练习:
1)通过docker 启动一个可包好的现成容器,
指定 端口,目录, 运行脚本 等 等
2) 通过makefile 打包好几个基本开发环境
jdk tomcat环境,jdk main方法环境
指定环境变量,挂载目录等操作
通过在 linux镜像基础上用makefile 格式构建环境
3)通过 docker-compose 进行,demo代码的自动打包,构建,运行。
自动从git拉取代码,通过maven构建。
通过jkens 配置自动定时构建测试环境。
通过jkens 指定的shell 启动docker 管理 docker容器。
最简单,最基本的docker打包流程
1) 生成一个Dockerfile文件
touch Dockerfile
2) 写入内容如下
FROM bba097ee5ee1 #【bba097ee5ee1为镜像ID】
CMD top #容器启动后执行一个命令
3)根据当前目录下的Dockerfile内容编译生成一个新的镜像 例:id= 73c7d25ff74c
docker build .
4)运行docker 镜像
docker run -i 73c7d25ff74c
5)进入容器
docker ps -a 查看容器id
sudo docker exec -it 775c7c9ee1e1 /bin/bash
docker 常用命令
$ docker ps // 查看所有正在运行容器 $ docker stop containerId // containerId 是容器的ID $ docker ps -a // 查看所有容器 $ docker ps -a -q // 查看所有容器ID $ docker stop $(docker ps -a -q) // stop停止所有容器 $ docker rm $(docker ps -a -q) // remove删除所有容器
docker images |sed -n '2,$p'|awk '{print $3}'|xargs -i echo {} //删除所有镜像
docker images |sed -n '/8-jdk-alpine/!p'|sed -n '2,$p'|awk '{print $3}'|xargs -i docker rmi {} //删除除 8-jdk-alpine 以外的所有镜你
docker build .
docker run -p 192.168.99.100:8080:8080 94051f6e8f3c
mvn 常用命令
mvn compile
mvn install
mvn test-compile
mvn test
mvn package
docker kill 0f115428397c 杀死容器进程
docker rm -f 0f115428397c 强制移除容器
针对spring Cloud实战代码的一个打包脚本:
顺便练一下 shell,贴一下,以后要查方便一点
主要是sed 中正则转义问题,文件生成行号再处理问题,sed awk基本使用格式问题。
docker 基本命令
demo目录是模板目录 路径是 /e/docker/demo
demo/
Dockerfile
run.sh*
simple-service-0.0.1-SNAPSHOT.jar
-----------------镜像生成开始----------------
bulid.sh #编译 maven并复制到工作目录 ,再打包成docker 镜像
m.sh #编译子脚本
copy.sh #复制子脚本
package.sh #找到每个Jar forech bulidimage.sh
bulidimage.sh #针对单个jar 进行打包动作
-----------------镜像生成完成------------------
-----------------在docker 运行容器开始-------------
runDocker.sh #针对工作目录找到 chapter(章节)
chapter-run.sh #找到每个Jar forech single-run.sh
single-run.sh #针对每个jar参数 完成端口映射等启动docker的动作
-----------------在docker 运行完成-------------
bulid.sh
ll /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ./m.sh {} ll /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ./copy.sh {} ll /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning |awk '{print $9}' > .dockerignore docker images |sed -n '/8-jdk-alpine/!p'|sed -n '2,$p'|awk '{print $3}'|xargs -i docker rmi -f {} ll /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ./package.sh {}
bulidimage.sh
echo $1 fallPath=`echo $1| sed 's///\\//g' ` echo fallPath: ${fallPath} path=`echo $1|sed "s//[^/]{0,100}$//g"` echo path: ${path} path2=`echo ${path}| sed 's///\\//g'` echo path2: ${path2} chapterName=`echo $1|sed "s/.{0,100}spmia-//g" |sed "s/-master.{0,100}//g "` echo chapterName: ${chapterName} jarName=`echo $1|sed "s/.{0,100}master///g"` echo jarName: ${jarName} serverName=`echo ${jarName}|sed "s/-0.0.1-SNAPSHOT.jar//g"` echo ${serverName} jarShortName=`echo ${jarName}|sed "s/.jar//g"` echo ${jarShortName} #echo cat ./demo/start.sh| sed 's/simple-service/'${serverName}'/g'| sed 's/simple-service-0.0.1-SNAPSHOT.jar/'${jarName}'/g' > ${path}/start.sh cat ./demo/run.sh| sed 's/simple-service/'${serverName}'/g'| sed 's/simple-service-0.0.1-SNAPSHOT.jar/'${jarName}'/g' > ${path}/start.sh cat ./demo/Dockerfile | sed 's/simple-service-0.0.1-SNAPSHOT.jar/'${fallPath}'/g' | sed 's/simple-service/'${serverName}'/g' | sed 's/start.sh/'${path2}'/start.sh/g' > ${path}/${serverName}-Dockerfile cat .dockerignore |sed 's/demo//g'|sed 's/'${chapterName}'//g' >.dockerignore echo docker build -f ${path}/${serverName}-Dockerfile -t ${serverName}-${chapterName}/latest: . docker build -f ${path}/${serverName}-Dockerfile -t ${chapterName}-${serverName}:latest .
chapter-run.sh
echo $1 find ./$1 | sed -n '/jar$/p'|awk '{print $0}' |sed -n '=;p'|sed -n '{N;s/ / /;p;d}'|xargs -i ./single-run.sh {}
copy.sh
rm -rf /e/docker/$1 mkdir /e/docker/$1 cd /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning/$1 find /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning/$1/* | sed -n '/jar$|docker/Dockerfile$/p'| xargs -i cp -r {} /e/docker/$1
m.sh
cd /e/zhl/code.ing/code.root.git/learning/SpringCloud_learning/$1 mvn compile mvn install
package.sh
echo $1 find ./$1 | sed -n '/jar$/p' |xargs -i ./bulidimage.sh {}
runDocker.sh
echo " begin" > history-docker-run docker stop $(docker ps -a -q) sleep 1 docker rm $(docker ps -a -q) sleep 1 ll |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ./chapter-run.sh {}
single-run.sh
#echo $1 #echo val: ${fallPath} val=`echo $1|awk '{print $2}' ` #echo val: ${val} chapterName=`echo ${val}|sed "s/.{0,100}spmia-//g" |sed "s/-master.{0,100}//g "` #echo chapterName: ${chapterName} chapterNumber=`echo ${chapterName}|sed "s/chapter//g"` echo chapterNumber: ${chapterNumber} nr=`echo $1|awk '{print $1}' ` echo nr: ${nr} jarName=`echo ${val}|sed "s/.{0,100}master///g"` echo jarName: ${jarName} serverName=`echo ${jarName}|sed "s/-0.0.1-SNAPSHOT.jar//g"` echo ${serverName} path=`echo ${val}|sed "s//[^/]{0,100}$//g"` echo path: ${path} echo docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 ${chapterName}-${serverName}:latest echo docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 ${chapterName}-${serverName}:latest >> history-docker-run echo begin >${path}/${chapterName}-${serverName}.txt docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 -p 192.168.99.100:8761:8761 -p 192.168.99.100:8888:8888 -p 192.168.99.100:8085:8085 -p 192.168.99.100:5432:5432 -p 192.168.99.100:5555:5555 -p 192.168.99.100:2181:2181 -p 192.168.99.100:9411:9411 ${chapterName}-${serverName}:latest & > ${path}/${chapterName}-${serverName}.log
demo/
Dockerfile
FROM bba097ee5ee1 RUN apk update && apk upgrade && apk add netcat-openbsd RUN mkdir -p /usr/local/simple-service ADD simple-service-0.0.1-SNAPSHOT.jar /usr/local/simple-service/ ADD start.sh run.sh RUN chmod +x run.sh CMD ./run.sh
run.sh
#!/bin/sh echo "********************************************************" echo "Starting simple-service " echo "********************************************************" java -jar /usr/local/simple-service/simple-service-0.0.1-SNAPSHOT.jar
simple-service-0.0.1-SNAPSHOT.jar
上面的脚本很乱:整一个合并版:
source_code_path=/e/zhl/code.ing/code.root.git/learning/SpringCloud_learning work_path=`pwd` #编译maven m() { source_code_path=$2 cd ${source_code_path}/$1 mvn compile pwd mvn install } #复制jar到当前工作目录 copy() { source_code_path=$2 work_path=$3 echo $1 $2 $3 echo exec copy fun cd ${work_path} rm -rf ${work_path}/$1 mkdir ${work_path}/$1 find ${source_code_path}/$1/* | sed -n '/jar$/p'| xargs -i cp -r {} ${work_path}/$1 #find ${source_code_path}/$1/* | sed -n '/jar$|docker/Dockerfile$/p'| xargs -i cp -r {} ${work_path}/$1 } #根据单个jar生成镜像 bulidimage() { source_code_path=$2 work_path=$3 echo exec bulidimage fun echo $1 #转义一次用于sed正则里面去匹配 jar包全路径 fallPath=`echo $1| sed 's///\\//g' ` echo fallPath: ${fallPath} #jar路径 不含包名 path=`echo $1|sed "s//[^/]{0,100}$//g"` echo path: ${path} #转义一次用于sed正则去匹配jar路径 path2=`echo ${path}| sed 's///\\//g'` echo path2: ${path2} #章节名 chapterName=`echo $1|sed "s/.{0,100}spmia-//g" |sed "s/-master.{0,100}//g "` echo chapterName: ${chapterName} #文件名 jarName=`echo $1|sed "s/.{0,100}master///g"` echo jarName: ${jarName} #章节路径 chapter_path=`echo $1 | sed 's//'${jarName}'//g'` echo chapter_path: ${chapter_path} #从jar包中取服务名 serverName=`echo ${jarName}|sed "s/-0.0.1-SNAPSHOT.jar//g"` echo ${serverName} #文件名去掉jar后缀 jarShortName=`echo ${jarName}|sed "s/.jar//g"` echo ${jarShortName} #忽略工作目录中除了demo目录和jar所在目录以外的所有文件、目录 echo dockerignore1 cd ${work_path} ll |awk '{print $9}' |sed -n '/'${chapterName}'/!p'|sed -n '/'demo'/!p' > .dockerignore echo dockerignore2 #忽略jar所在目录里除当前Dockerfile、jar和start.sh以外的所有文件、目录 cd ${work_path} find ${chapter_path} |sed -n '2,$p'|sed -n '/'Dockerfile'/!p'|sed -n '/'${serverName}'/!p'|sed -n '/start.sh/!p'|sed -n '/start.sh/!p' >> .dockerignore #修改 start.sh 模板 cat ${work_path}/demo/run.sh| sed 's/simple-service/'${serverName}'/g'| sed 's/simple-service-0.0.1-SNAPSHOT.jar/'${jarName}'/g' > ${path}/start.sh #修改 Dockerfile 模板 cat ${work_path}/demo/Dockerfile | sed 's/simple-service-0.0.1-SNAPSHOT.jar/'${fallPath}'/g' | sed 's/simple-service/'${serverName}'/g' | sed 's/start.sh/'${path2}'/start.sh/g' > ${path}/${serverName}-Dockerfile #打包镜像 echo docker build -f ${path}/${serverName}-Dockerfile -t ${chapterName}-${serverName}:latest . docker build -f ${path}/${serverName}-Dockerfile -t ${chapterName}-${serverName}:latest . } #针对每个jar包打镜像 package() { echo exec package fun echo $1 source_code_path=$2 work_path=$3 #find ${work_path}/$1 | sed -n '/jar$/p' |xargs -i ${work_path}/bulidimage.sh {} #将函数做为一个系统函数,就是说调用时系统会把这段函数代码当成一个shell脚本 cd ${work_path} find ./$1 | sed -n '/jar$/p'| awk -v prm=${source_code_path} -v prm2=${work_path} '{ cmd =" bulidimage "$1" "prm" "prm2 system(cmd); }' } #编译maven并生成镜像 build () { echo exec bulid fun source_code_path=$1 work_path=$2 echo ${source_code_path} #编译maven #ll ${source_code_path} |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ${work_path}/m.sh {} export -f m ll -l ${source_code_path} |grep spmia-chapter |awk '{print $9}'|sed 's////g'| awk -v prm=${source_code_path} '{ cmd =" m "$1" "prm system(cmd); }' #复制jar到当前目录 #ll ${source_code_path} |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ${work_path}/copy.sh {} export -f copy ll -l ${source_code_path} |grep spmia-chapter |awk '{print $9}'|sed 's////g'| awk -v prm=${source_code_path} -v prm2=${work_path} '{ cmd =" copy "$1" "prm" "prm2 system(cmd); }' #停止所有容器 docker stop $(docker ps -a -q) sleep 1 #删除所有容器 docker rm $(docker ps -a -q) #强制删除多余的镜像 只留 8-jdk-alpine #docker images |sed -n '/8-jdk-alpine/!p'|sed -n '2,$p'|awk '{print $3}'|xargs -i docker rmi -f {} #删除所有 chapter 镜像 |column -t 对齐 #docker images|sed -n '/chapter/p'|awk '{print $1,$3}'|column -t |awk '{print $3}'|xargs -i docker rmi {} docker images|sed -n '/chapter/p'|awk '{print $3}' |xargs -i docker rmi {} #生成镜像 export -f bulidimage export -f package ll ${work_path} |grep spmia-chapter |awk '{print $9}'|sed 's////g'| awk -v prm=${source_code_path} -v prm2=${work_path} '{ cmd="package "$1" "prm" "prm2 system(cmd); }' } #运行单个镜像 single_run() { source_code_path=$3 work_path=$4 echo exec single_run fun echo "1:"$1 "2:"$2 "3:"$3 "4:"$4 nr=`echo $1` echo nr: ${nr} val=`echo $2` echo val: ${val} chapterName=`echo ${val}|sed "s/.{0,100}spmia-//g" |sed "s/-master.{0,100}//g "` #echo chapterName: ${chapterName} chapterNumber=`echo ${chapterName}|sed "s/chapter//g"` echo chapterNumber: ${chapterNumber} jarName=`echo ${val}|sed "s/.{0,100}master///g"` echo jarName: ${jarName} serverName=`echo ${jarName}|sed "s/-0.0.1-SNAPSHOT.jar//g"` echo ${serverName} path=`echo ${val}|sed "s//[^/]{0,100}$//g"` echo path: ${path} echo docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 ${chapterName}-${serverName}:latest echo docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 ${chapterName}-${serverName}:latest >> history-docker-run echo begin >${path}/${chapterName}-${serverName}.log #echo docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 -p 192.168.99.100:8761:8761 -p 192.168.99.100:8888:8888 -p 192.168.99.100:8085:8085 -p 192.168.99.100:5432:5432 -p 192.168.99.100:5555:5555 -p 192.168.99.100:2181:2181 -p 192.168.99.100:9411:9411 ${chapterName}-${serverName}:latest & > ${path}/${chapterName}-${serverName}.log docker run -p 192.168.99.100:8${chapterNumber}${nr}:8080 -p 192.168.99.100:8761:8761 -p 192.168.99.100:8888:8888 -p 192.168.99.100:8085:8085 -p 192.168.99.100:5432:5432 -p 192.168.99.100:5555:5555 -p 192.168.99.100:2181:2181 -p 192.168.99.100:9411:9411 ${chapterName}-${serverName}:latest & > ${path}/${chapterName}-${serverName}.log } #启动一个章节对应的所有镜像 chapter_run() { source_code_path=$2 work_path=$3 echo exec chapter_run fun echo $1 cd ${work_path} find ./$1 | sed -n '/jar$/p'|awk '{print $0}' |sed -n '=;p'|sed -n '{N;s/ / /;p;d}'| awk -v prm=${source_code_path} -v prm2=${work_path} '{ cmd="single_run "$1" "$2" "prm" "prm2 system(cmd); }' } #运行docker runDocker() { source_code_path=$1 work_path=$2 echo exec runDocker fun echo " begin" > history-docker-run docker stop $(docker ps -a -q) sleep 1 docker rm $(docker ps -a -q) sleep 1 #ll |grep spmia-chapter |awk '{print $9}'|sed 's////g'|xargs -i ${work_path}/chapter-run.sh {} export -f single_run export -f chapter_run ll |grep spmia-chapter |awk '{print $9}'|sed 's////g'| awk -v prm=${source_code_path} -v prm2=${work_path} '{ cmd="chapter_run "$1" "prm" "prm2 system(cmd); }' } if [ $# -eq 0 ]; then exit fi if [ $1 = "run" ];then echo run runDocker ${source_code_path} ${work_path} elif [ $1 = "build" ];then echo build build ${source_code_path} ${work_path} else echo none fi
一个好玩的shll 先记一下以后看
Mytest() { echo $1 } if [ "$1" == "Mytest" ]; then then shift Mytest $* exit 0 fi # ll || xargs -n 1 -i $0 Mytest {}
行转列(awk):
awk -F "+" '{for(i=1;i<=NF;i++) a[i,NR]=$i}END{for(i=1;i<=NF;i++) {for(j=1;j<=NR;j++) printf a[i,j] " ";print ""}}' file.txt
列转行(tr):
cat file.txt |tr " " ","|sed -e 's/,$/ /'
shell脚本常见变量
变量 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2 $# 传递给脚本或函数的参数个数 $* 传递给脚本或函数的所有参数 $@ 传递给脚本或函数的所有参数。被双引号(” “)包含时,与 $* 稍有不同 $? 上个命令的退出状态,或函数的返回值。成功返回0,失败返回1 $$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID $* 和 $@ 都是将参数一个一个返回 "$*"将所有参数当做一个整体字符串返回 , "$@"将参数一个一个返回 命令 含义 -eq 等于 -ne 不等于 -gt 大于 -lt 小于 ge 大于等于 le 小于等于 操作符 作用 -d 测试文件是否为目录类型 -e 测试文件是否存在 -f 判断是否为一般文件 -r 测试当前用户是否有权限读取 -w 测试当前用户是否有权限写入 -x 测试当前用户是否有权限执行 2:实例 下面使用文件测试语句来判断/etc/fstab是否为一个目录类型的文件,然后通过Shell解释器的内设$?变量显示上一条命令执行后的返回值。如果返回值为0,则目录存在; 如果返回值为非零的值,则意味着目录不存在: [root@linuxprobe ~]# [ -d /etc/fstab ] [root@linuxprobe ~]# echo $? 1 再使用文件测试语句来判断/etc/fstab是否为一般文件,如果返回值为0,则代表文件存在,且为一般文件: [root@linuxprobe ~]# [ -f /etc/fstab ] [root@linuxprobe ~]# echo $? 0 逻辑语句用于对测试结果进行逻辑分析,根据测试结果可实现不同的效果。例如在Shell终端中逻辑“与”的运算符号是&&,它表示当前面的命令执行成功后才会执行它后面的命令, 因此可以用来判断/dev/cdrom文件是否存在,若存在则输出Exist字样。 [root@linuxprobe ~]# [ -e /dev/cdrom ] && echo "Exist" Exist 除了逻辑“与”外,还有逻辑“或”,它在Linux系统中的运算符号为||,表示当前面的命令执行失败后才会执行它后面的命令,因此可以用来结合系统环境变量USER来判断当前登录 的用户是否为非管理员身份: [root@shizhan2 sh]# echo $USER root [root@shizhan2 sh]# [ $USER = root ] || echo "user" [root@shizhan2 sh]# su - hadoop [hadoop@shizhan2 ~]$ [ $USER = root ] || echo "user" user 第三种逻辑语句是“非”,在Linux系统中的运算符号是一个叹号(!),它表示把条件测试中的判断结果取相反值。也就是说,如果原本测试的结果是正确的,则将其变成错误的; 原本测试错误的结果则将其变成正确的。 [linuxprobe@linuxprobe ~]$ exit logout [root@linuxprobe root]# [ $USER != root ] || echo "administrator" administrator 先判断当前登录用户的USER变量名称是否等于root,然后用逻辑运算符“非”进行取反操作,效果就变成了判断当前登录的用户是否为非管理员用户了。最后若条件成立则会根据逻 辑“与”运算符输出user字样;或条件不满足则会通过逻辑“或”运算符输出root字样,而如果前面的&&不成立才会执行后面的||符号。 [root@linuxprobe ~]# [ $USER != root ] && echo "user" || echo "root" root 使用规范的整数比较运算符来进行操作数字,不能将数字与字符串、文件等内容一起操作 操作符 作用 -eq 是否等于 -ne 是否不等于 -gt 是否大于 -lt 是否小于 -le 是否等于或小于 -ge 是否大于或等于 我们先测试一下10是否大于10以及10是否等于10(通过输出的返回值内容来判断): [root@linuxprobe ~]# [ 10 -gt 10 ] [root@linuxprobe ~]# echo $? 1 [root@linuxprobe ~]# [ 10 -eq 10 ] [root@linuxprobe ~]# echo $? 0 free命令,它可以用来获取当前系统正在使用及可用的内存量信息。接下来先使用free -m命令查看内存使用量情况(单位为MB),然后通过grep Mem:命令过滤出剩余内存量的行, 再用awk '{print $4}'命令只保留第四列,最后用FreeMem=`语句`的方式把语句内执行的结果赋值给变量 复制代码 [root@linuxprobe ~]# free -m total used free shared buffers cached Mem: 1826 1244 582 9 1 413 -/+ buffers/cache: 830 996 Swap: 2047 0 2047 [root@linuxprobe ~]# free -m | grep Mem: Mem: 1826 1244 582 9 [root@linuxprobe ~]# free -m | grep Mem: | awk '{print $4}' 582 [root@linuxprobe ~]# FreeMem=`free -m | grep Mem: | awk '{print $4}'` [root@linuxprobe ~]# echo $FreeMem 582 复制代码 我们使用整数运算符来判断内存可用量的值是否小于1024,若小于则会提示“Insufficient Memory”(内存不足)的字样: [root@linuxprobe ~]# [ $FreeMem -lt 1024 ] && echo "Insufficient Memory" Insufficient Memory 字符串比较语句用于判断测试字符串是否为空值,或两个字符串是否相同。它经常用来判断某个变量是否未被定义(即内容为空值),理解起来也比较简单。 字符串比较中常见的运算符如表4-5所示: 操作符 作用 = 比较字符串内容是否相同 != 比较字符串内容是否不同 -z 判断字符串内容是否为空 接下来通过判断String变量是否为空值,进而判断是否定义了这个变量: [root@linuxprobe ~]# [ -z $String ] [root@linuxprobe ~]# echo $? 0 再尝试引入逻辑运算符来试一下。当用于保存当前语系的环境变量值LANG不是英语(en.US)时,则会满足逻辑测试条件并输出“Not en.US”(非英语)的字样: [root@linuxprobe ~]# echo $LANG en_US.UTF-8 [root@linuxprobe ~]# [ $LANG != "en.US" ] && echo "Not en.US" Not en.US