南开小巷

导航

docker学习笔记

总结:

1.镜像 容器关系:镜像好比java中的类,容器好比java中的对象,一个镜像可以有多个容器;镜像是分层的

2.docker image:列出本地的镜像 -q查镜像的id

3.docker search xxx 例如docker search tomcat 在仓库(hub.docker.com)中查找 列出的offical是指的是官方版本,还可以使用 docker search -s 30 tomcat 意思是查找点赞数超过30的tomcat,给搜索出来
4.docker pull xxx:version 如果不写冒号后面的,默认是最新版本
5.docker info可以查看docker的版本,内存空间,以及注册的镜像源(可以看是否阿里云镜像是否配置成功)
6 docker rmi hello-world:version 删除某一个版本的本地镜像
如果容器在运行中,强制删除用 docker rmi -f hello-world
如果删除本地中所有容器:docker rmi -f $(docker images -qa)

docker容器:有镜像才能创建容器,这是根本前提,可以把容器看成简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间)和运行在其中的应用程序,容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的

 

docker容器相关的指令:
1.docker run -it id号(或者镜像名字)举例:docker run -it centos就进入了docker中的centos,还可以加一个参数 --name
2.docker ps 列出正在运行的容器 ,这个命令执行后会列出他的容器id,注意这个容器id和镜像命令docker images 列出的 image id不一样
docker ps -l 指的是把上次运行的容器列出来
docker ps -a列出历史和现在所有的容器
3.退出容器 exit 例如当我们以交互加伪终端的方式run centos时,进入的是docker的centos系统,这时候,我们要退出,也就是退出centos这个容器,执行exit 命令即可(在docker运行中的centos中执行exit)
另一个关闭指令(离开并不离去) ctrl +P + Q 方式就是暂时离开容器,但是容器还是在运行状态,这个可以通过 docker ps进行验证
4. docker启动容器:场景,比如刚才exit退出了一个centos容器,但是我们通过docker ps -n 2指令找到那个已经关闭容器的container id ,然后,我们在执行执行docker start container id,就可以把exit那个容器重新启动了,最终的结果也能证明,一个centos镜像,可以跑多个容器
5.容器重启 docker restart container id
6.关闭容器,docker stop container id
7.强制关闭容器: docker kill container id 与关闭容器的区别是,强制关闭容器指令关闭容器会比较快,普通的关闭容器会比较慢一些
8.删除已停止的容器 docker rm 容器 id 。解释:向上述docker stop或者docker kill指令是已经把容器停止了,在docker ps中找不到,但是docker ps -l (或者docker ps -n 数字) 中是可以看到的,也就是说,docker会缓存已经停止掉的容器,docker rm 容器id这条指令就是删除已经停止的容器
这个指令和删除镜像的区别是:删除镜像用的是docker rmi rm后面跟着i
如果想强制删除正在运行的容器,就用-f

9.容器以守护式进程启动 docker run -d id号(镜像 id号)或镜像名字,这个是和上面的交互命令(-it)相对应的另一种方式,-d是在后台运行了,但是运行完docker run -d 镜像名称(或镜像id号之后),在执行 docker ps 发现没有刚刚起的centos的容器,这是为什么呢?
10.接着上述问题,说说docker的机制:其实上述是因为容器已退出了,即容器肯定启动过,但是又退出了,Docker容器后台运行,就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令(比如top,tail)就是会自动退出的,如何解决这个问题呢?就是将你要运行的程序以前台进程的形式运行。下面这个指令就可以解决docker上述机制带来的问题
docker run -d centos /bin/sh -c "while true;do echo hello zhangshitong;sleep 2;done"
11.查看容器日志: docker logs -f -t --tail 容器ID
-t是加入时间的意思;-f跟随最新的日志打印;--tail数字,显示最后多少条
12.查看容器内运行的进程: docker top container id
13.查看容器内部细节:docker inspect 容器id docker的镜像是一层套一层的,是json串一层嵌套一层的
14.进入正在运行的容器并以命令行交互:还记得上面的ctrl+Q+P吗?docker容器还在后台运行着呢?如何再次进入呢,这个就是解决上面的问题的 docker attach 容器id,这条指令直接进入docker centos的根目录
还有另外一条指令,也能从ctrl+p+q中再次进入容器:docker exec -t ls -s
/tmp 这个-t 后面跟的是linux的指令
上面两个指令的区别:attach直接进入容器启动命令的终端,不会启动新的进程;exec是在容器中打开新的终端,并且可以启动新的进程。docker exec -t 容器id /bin/bash 就等价于 docker attach 容器id
14.从容器内拷贝文件到主机上:docker cp 容器di:容器内路径 目的主机路径

 

docker镜像学习:镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件 UnionFS联合文件系统:是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。 Union文件系统的特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

docker镜像加载原理:分层文件系统,这就能解释为什么一个tomcat的镜像为什么能有四五百兆之多

 

 

docker为什么采用这种分层的结构呢?:最大的一个好处就是共享资源

比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也只需要加载一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享

 docker镜像的特点:

1.docker镜像都是只读的;2.当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称为“容器层”,容器层之下都叫“镜像层”

 

docker 镜像commit操作以及docker对tomcat容器的一些操作

1.docker commit提交容器副本使之称为一个新的镜像

docker commit -m=“提交的描述信息” -a="作者" 容器ID 要创建的目标镜像名:[标签名]  举例: docker commit -a="zst" -m="tomcat without docs" 容器id atguigu/tomcat02:1.2   最后是别名加了一个版本号

2.docker 运行 tomcat镜像 : docker run  -it -p 8888:8080 tomcat   说明: -p 后面的8888指的是docker对外提供可访问的端口,冒号后面的8080是docker中的tomcat运行的端口

docker run -it -P tomcat 说明:这次的指令是大写的P,表示的是随即分配端口,如何查看这个随即分配的端口呢? 通过docker ps 找到ports选项就能查找到docker对外提供的端口了

3.如何进入已经运行的tomcat容器,(进到tomcat目录):docker exec -it 容器id号 /bin/bash

docker commit 提交实例:docker commit -a="zst" -m="tomcat without docs" b778da0b71b9 atguigu/mytomcat:1.2  这个是提交删除doc的tomcat并指定版本号

 

docker容器数据卷

1.是什么

docker的理念:将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的,容器之间希望可能共享数据

Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做成镜像的一部分保存下来,那么当容器删除后,数据自然就没有了,为了能保存数据在docker中我们使用卷

2.作用:

容器的持久化,容器间继承+共享数据

卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过UnionFile System提供一些用于持续存储或共享数据的特性:卷设计的目的就是数据的持久化完全独立于容器的生存周期,因此docker不会再容器删除时删除其挂载的数据卷

特点:

1.数据卷可在容器之间共享或重用数据;2.卷中的更改可以直接生效;3.数据卷中的更改不会包含在镜像的更新中;4.数据卷的生命周期一直持续到没有容器使用它为止

 数据卷的操作:

直接命令添加:命令:docker run -it -v /宿主机绝对路径目录:/容器内目录  镜像名  

举例: docker run -it -v /myDataVolume:/dataVolumeContainer centos  解释在宿主机中的根目录下的myDataVolume(如果不存在就创建)一个目录,在docker中centos容器内的根目录创建 dataVolumeContainer目录

执行完以上命令后,在宿主机的根目录和docker容器的根目录中都会有相应的文件夹,说明,宿主机和docker centos容器挂载成功了,也就是宿主机和docker centos容器之间建立了一个通道

 

容器停止以后,主机修改数据,然后再 重启之前的容器,数据依然是同步的

带权限的容器卷:

docker run -it -v /宿主机绝对路径目录:/容器内目录:ro  镜像名     说明:这个是只读,也就是主机单向的穿给docker centos容器,centos容器只能看文件,不能更改文件

dockerFile添加

1.什么是dockerFile:

个人理解,就是镜像模板的描述文件

说明:出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法(就是数据卷的直接命令方法)不能够直接在dockerfile中实现,出于宿主机目录是依赖于特定宿主机的,并不能保证在所有的宿主机上都存在这样的特定目录

Dockerfile的书写举例:

FROM centos  #继承容器centos
VOLUME  ["/dataVolumeContainer1","/dataVolumeContainer2"]   #在容器内建立 dataVolumeContainer1,dataVolumeContainer2两个容器卷
CMD echo "finished,------success1"
CMD /bin/bash

构建Dockerfile文件

指令 : docker build -f  /mydocker/Dockerfile -t zzyy/centos .     解释,-f指的是文件,后面跟的是dockefile文件的宿主机地址, -t指的是命名空间(就是docker pull 后面的名字) 后面还有一个点,这个点的意思是在当前文件夹下构建

构建成功后,用docker images 就能列出来刚刚构建的镜像zzyy/centos ,如果用docker run  -it 镜像名字(或者镜像id) ,成功后,创建的容器默认是加载dockerfile中创建的dataVolumeContainer1,dataVolumeContainer2两个容器卷的,也就是说,docker容器中的zzyy/centos 里面的根目录是有dataVolumeContainer1,和dataVolumeContainer2两个文件夹的

那还有一个问题,数据卷的建立是宿主机和容器主机的“通道”,那既然你dockerfile创建中有容器卷(创建了容器卷的位置),那容器卷跟宿主机的那个文件对应呢?

答案: docker  inspect 镜像id

 

容器间传递共享: volumes-from  

先执行docker run -it --name dc01 zzyy/centos ,这个zzyy/centos用dockerfile构建的数据卷,容器开启的时候,是在容器的根目录下创建dataVolumeContainer1 ,dataVolumeContainer2的容器卷

指令:  docker run -it  --name dc02   --volumes-from dc01 zzyy/centos   指令说明,这个是创建容器dc02,是“继承”容器dc01的

 执行完成之后,dc01和dc02中的dataVolumeContainer1 ,dataVolumeContainer2就是作为dc01和dc02互传的数据卷

docker run -it  --name dc02   --volumes-from dc01 zzyy/centos  又创建了一个dc03 同样是“继承”dc01

结论: 1.回到dc01可以看到dc02/dc03各自添加的文件都能共享了

2.删除dc01后(也就是删除父容器),剩下的两个子容器dc02和dc03数据依然是可以共享的 docker rm -f dc01 删除dc01

3.新建dc04继承dc03  docker run -it --name dc04 --volumes-from dc03 zzyy/centos,然后删除dc03,那dc04继承自dc03的那些数据,依然是存在的

最终的结论:容器之间配置信息的传递,数据卷的声明周期一直持续到没有容器使用它为止

 

 

dockerfile的学习:dockerfile的构建步骤

1.手动编写一个dockerfile文件,必须符合dockerfile的规范

2.有文件后,直接docker build命令执行,获得一个自定义的镜像

3.docker  run

dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本

 Dockerfile的内容基础知识:

1.每条保留字指令都必须为大写字母且后面要跟随至少一个参数

2.指令按照从上到下,顺序执行

3.#表示注释

4.每条指令都会创建一个新的镜像层,并对镜像进行提交

Dockerfile执行的大致流程:

1.docker从基础镜像运行一个容器

2.执行一条指令并对容器做出修改

3.执行类似docker commit的操作提交一个新的镜像层

4.docker再基于刚提交的镜像运行一个新的容器

5.执行dockerfile中的下一条指令直到所有指令都执行完成

 

从应用软件的角度来看Dockfile、Docker镜像与Docker容器分别代表软件的三个不同阶段

Dockfile是软件的原材料;Docker镜像是软件的交付品;Docker容器则可以认为是软件的运行态

Dockfile面向开发,Docker镜像称为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力为Docker体系的基石

 

 

DockerFile保留字指令:

1.FROM 基础镜像,当前镜像是基于哪个镜像的

2.MAINTAINER 作者和作者的邮箱

3.RUN  容器构建时需要运行的命令

4.EXPOSE  当前容器爆露出的端口

5.WORKDIR 指定在创建容器后,终端默认登录进来工作目录的一个落脚点

6.ENV  用来在构建镜像的过程中设置环境变量

7.ADD  将宿主机目录下的文件拷贝进镜像且ADD指令会自动处理URL和解压tar压缩包

8.COPY 类似ADD 拷贝文件和目录到镜像中,将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置

9.VOLUME 容器数据卷,用于数据保存和持久化工作

10.CMD  指定一个容器启动时要运行的命令, Dockfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

11.ENTRYPOINT 指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数

12.ONBUILD 当构建一个被继承的Dockfile时运行命令,父镜像在被子镜像继承后父镜像的onbuild被触发

 

Dockfile 的案例部分:

案例一:自定义mycentos,目的是使我们自己的镜像具备如下:

1.指定登录后的默认路径;2.使vim能用;3.能够支持ifconfig这个指令

FROM centos

MAINTAINER zst<zhangshitongsky@163.com>

 

ENV MYPATH  /tmp

WORKDIR  $MYPATH

 

RUN yum  -y install vim

RUN yum  -y install net-tools

 

EXPOSE 80

CMD echo $MYPATH

CMD echo "success ----------------ok"

CMD  /bin/bash

 

列出镜像历史的变更历史  docker history 镜像名(或者镜像id)

 

 

用实例介绍 CMD   与 ENTRYPOINT之间的区别

docker  run  -it  -p  7777:8080 tomcat  ls  -l   执行完这一条指令之后,直接进入了tomcat的目录,tomcat并没有起来,就是因为Dockfile中CMD这个含义是替换,CMD ls -l  最终会替换掉  CMD ["catalina.sh", "run"]   所以最终执行的是 ls -l 指令,CMD ["catalina.sh", "run"] 这条指令并没有执行被覆盖了,也就是介绍CMD说的,CMD 会被 docker run 之后的参数覆盖掉

 

实例2:查询ip

Dockfile1:

FROM  centos

RUN  yum  install -y curl

CMD  ["curl","-s","http://ip.cn"]

 

Dockfile2:

FROM  centos

RUN  yum  install -y curl

ENTRYPOINT ["curl","-s","http://ip.cn"]

 以上就是Dockfile中CMD和ENTRYPOINT的区别:当运行上面的Dockfile产生的镜像,形成的容器是 docker  run -it  容器名字  -i   的时候  (注意后面的-i)第一个Dockerfile产生的容器会报错,第二个就不会

原因是 -i  在Dockfile1中追加CMD["-I"]会覆盖CMD  ["curl","-s","http://ip.cn"],所以会报错,而第二个Dockfile2是ENTRYPOINT,这个是追加 类似  执行  curl -s -i   http://ip.cn所以会把消息头也给返回回来(-i的作用)

 

ONBUILD命令的Dockfile案例:

Dockerfile3文件:加入build后的镜像名字叫做myip_father

FROM  centos

RUN yum install -y curl

ENTRYPOINT ["curl","-s","http://ip.cn"]

ONBUILD RUN echo "father images onbuild ------886"

 

Dockerfile4 : 假如它构建的镜像名字为 myip_son

FROM  myip_father    # 这个继承的是Dockerfile3构建的镜像

RUN yum install -y curl

ENTRYPOINT ["curl","-s","http://ip.cn"]

当我们执行 docker  build  -f  /Dockerfile4  -t myip_son .   这条语句的时候,就会触发myip_father  Dockerfile中 ONBUILD  RUN后面的那句话

 

自制tomcat9实例:

Dockfile5:

FROM  centos

MAINTAINER  zst<zhangshitongsky@163.com>

#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下,并重命名为cincontainer.txt

COPY c.txt  /usr/local/cincontainer.txt

#把java与tomcat添加到容器中

ADD  jdk-8u171-linux-x64.tar.gz /usr/local/

ADD apache-tomcat-9.0.8.tar.gz  /usr/local/

#安装vim编辑器

RUN  yum -y  install  vim

#设置工作访问时候的WORKDIR路径,登录落脚点

ENV  MYPATH  /usr/local

WORKDIR  $MYPATH

#配置java与tomcat环境变量

ENV  JAVA_HOME  /usr/local/jdk1.8.0_171

ENV  CLASSPATH  $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

ENV  CATALINA_HOME /usr/local/apache-tomcat-9.0.8

ENV  CATALINA_BASE /usr/local/apache-tomcat-9.0.8

ENV  PATH  $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

#容器运行时监听的端口

EXPOSE  8080

#启动时运行tomcat

#ENTRYPOINT  ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh"]

#CMD  ["usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]

CMD  /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out

 

然后执行 docker  build  -f /Dockerfile5  -t  zzyytomcat9 .

然后构建容器,此时注意,这时候构建容器和平常的不太一样了

docker  run  -d  -p 9080:8080  --name  myt9 

-v  /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test 

 -v  /zzyyuse/mydockerfile/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs 

--privileged=true  zzyytomcat9(镜像名字)

 

对于后台运行tomcat容器,想看一下目录情况,可以用指令  docker exec   容器id   ls  -l      说明:容器id后面可以跟一些linux指令    

docker exec   容器id  java  -version 

 

 

Docker常用安装:

总体步骤:1.搜索镜像;2拉取镜像;3.查看镜像;4.启动镜像;5.停止容器,6移除容器

 

docker安装mysql

1. docker  pull  mysql:5.6

2.docker run -p 12345:3306 --name mysql

-v /zzyyuse/mysql/conf:/etc/mysql/conf.d

-v /zzyyuse/mysql/logs:/logs

-v /zzyyuse/mysql/data:/var/lib/mysql

-e MYSQL_ROOT_PASSWORD=123456 # 初始化root用户的密码

-d mysql:5.6

 

3.在宿主机上操作docker容器中的mysql 使其的数据备份到宿主机 :docker exec 42ef49cb3741(容器id号) sh -c 'exec mysqldump --all-databases -uroot -p"123456" ' > /zzyyuse/all-databases.sql

 

docker安装redis

1.docker  pull  redis:3.2

2.docker run -p 6379:6379 -v /zzyyuse/myredis/data:/data -v /zzyyuse/myredis/conf/redis.conf:/usr/local/etc/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes

3.在宿主机中创建redis配置文件 注意第一个redis.conf是个目录,第二个redis.conf才是文件,然后通过数据卷映射到docker容器中的usr/local/etc/redis.conf 

vi /zzyyuse/myredis/conf/redis.conf/redis.conf

 

docker编排:

“编排”在云计算行业里不算是新词汇,它主要是指用户如何通过某些工具或者配置来完成一组虚拟机以及关联资源的定义、配置、创建 删除等工作,然后由云计算平台,然后由云计算平台按照这些指标的逻辑来完成的过程

 什么是进程:

一旦程序被执行起来,它就从磁盘上的二进制文件(程序需要输入的数据)变成了计算机内存中的数据、寄存器里的值、堆栈中的指令、被打开的文件,以及各种设备的状态信息的一个集合。像这样一个程序运起来后的计算机执行环境的总和,就是进程。

所以对于进程来讲,它的静态表现就是程序,平常都安安静静的待在磁盘上;而一旦运行起来,它就变成了计算机里的数据和状态的总和,这就是它的动态表现

容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”

对于Docker等大数据Linux容器来说,Cgroups技术是用来制造约束的主要手段,而Namespace技术则是用来修改进程视图的主要方法

Docker容器这个听起来玄而又玄的概念,实际上是在创建容器进程时,指定了这个进程所需要启用的一组Namespace参数,这样,容器就只能看到当前Namespace所限定的资源、文件、设备、状态,或者配置,而对于宿主机以及其他不相关的程序,它就完全看不到了,所以说,容器,其实就是一种特殊的进程而已。

跟真实存在的虚拟机不同,在使用Docker的时候,并没有一个真正的“Docker容器”运行在宿主机里面,Docker项目帮助用户启动的,还是原来的应用进程,只不过在创建这些进程的时候,Docker为它们加上了各种各样的Namespace参数

 

 

基于Linux Namespace的隔离机制,相比于虚拟化技术有很多不足之处,其中最主要的问题是:隔离不彻底

1.既然容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核

2.在linux内核中,有很多资源和对象是不能被Namespace化的,最典型的例子就是:时间

 

Linux Cgroups就是linux内核中用来为进程设置资源限制的一个重要功能,它就是一个子系统目录加上一组资源限制文件的组合,而对于Docker等linux容器项目来说,它们只需在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的PID填写到对应控制组的tasks文件中就可以了

 

容器是一个单进程模型

posted on 2019-06-22 20:31  南开小巷  阅读(231)  评论(0编辑  收藏  举报