为什么学习Docker |
---|
Docker可以提供项目的服务,比如MySql,Redis |
Java工程师必备技能 |
当你编写完程序,打成war包,给运维让他部署到服务器,这时可能突然发现,这项目根本跑不起来,因为换了系统,环境不一样 |
那么Docker就是虚拟这个环境,避免上述问题发生 |
Docker可以实现一次构建处处运行 |
Docker定义 |
---|
操作系统级别的虚拟化方案 |
一个开源引擎,可以轻松为任何应用创建一个轻量级、可移植、自给自足的容器 |
Docker思想来自于集装箱,将运行环境,部署等等,统一按Docker的标准来封装 |
Docker容器与虚拟机区别 |
---|
Docker启动一个环境系统只需几秒(因为仅仅虚拟一个简单操作系统环境和容器) |
虚拟机启动一个虚拟系统需要几分钟(因为虚拟的是一个完整的几个G的操作系统) |
Docker概念 |
---|
Docker镜像:一个只读模板,用来创建Docker容器,镜像就是你运行环境的镜像,有了镜像,运维在服务器只需要安装Docker,而不需要安装运行环境 |
容器:Docker利用容器来运行应用,容器是从镜像创建的运行实例 |
仓库:集中存放镜像文件的场所 |
运行概述 |
---|
我们把应用程序和配置依赖打包成一个用于交付的运行环境(镜像),通过镜像生成一个或多个容器(实例),所有的镜像都存储在仓库中 |
一、环境搭建
Docker支持CentOS 6.5以上的Linux版本,6.5以下不支持 |
---|
uname -r:查看Linux系统版本 |
1、安装Linux环境(自己的主机)
2、使用阿里云ESC(推荐,我们可以将自己的网站部署上去)
3、安装Docker
1、CentOS6.X版本
1、yum install -y epel-release
2、yun install -y docker-io
3、配置文件:/etc/sysconfig/docker
4、启动Docker后台服务:service docker start
5、验证是否安装成功:docker version
2、CentOS7.X版本
7.x版本配置文件:/etc/docker/daemon.json
4、配置阿里云镜像
使用docker run hello-world命令测试 |
---|
它会先本地找镜像,没有就去阿里云镜像拉,下载运行 |
二、常用命令
linux快捷键 |
---|
ctrl+insert 复制 |
shift+insert 粘贴 |
1、镜像命令
一、帮助命令
docker --help
获取docker命令已经提示信息
二、镜像命令
docker images
列出本地主机上的所有镜像(就是你通过docker下载的镜像)
执行结果(因为仅仅上面测试时下载了hello-world镜像,所以就这一个):
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 6 months ago 13.3kB
参数说明
REPOSITORY :镜像仓库源
TAG : 镜像的标签
IMAGE ID:镜像id
CREATED:镜像创建时间
SIZE:镜像大小
docker images [option]
通过option指定不同规则的显示方式,记住此命令是从主机查
option
-a:列出本地所有镜像
-q:只显示镜像ID
--digests:显示镜像的摘要信息
--no-trunc:显示完整的镜像信息
docker search 镜像名
在docker Hub(docker的镜像仓库)上搜索指定镜像名的详细信息,注意是从docker仓库查,不是自己的主机
docker search [option] 镜像名
指定查询规则
option
--no-trunc:显示完整的镜像描述
-s:列出收藏数不小于指定值的镜像
--automated:只列出automated build(自动构建)类型的镜像
举例
docker search -s 30 tomcat
搜索docker Hub上收藏数量大于30的tomcat镜像
docker pull 镜像名[:TAG]
从仓库(Docker Hub ,这里我们配置了阿里云,就从阿里云)下载镜像
:TAG
默认为latest,表示最新版
2.181x:版本号,可以先到docker hub上查询版本号,然后指定版本下
举例
docker pull tomcat:latest
下载最新版tomcat镜像
docker pull tomcat:3.85xxx
下载指定版本的tomcat镜像
docker rmi 镜像名字或镜像id:[TAG]
删除镜像
:TAG还是一样指定版本,默认为latest
举例
docker rmi -f hello-world
强制删除hello-world镜像
docker rmi -f hello-world nginx
强制删除hello-world和nginx镜像,删除多个就用空格分隔
docker rmi -f $(docker images -q)
如果你学过sql中的子查询,就可以很好理解,$()括号中执行后会得到所有镜像id,这时
执行强制删除,就是将所有查询结果删除了
2、容器命令
首先你得拉取一个CentOS镜像,这个镜像不是完整的操作系统,而是一个内核进行,用来给docker虚拟容器环境的 |
---|
因为docker就是用来虚拟运行环境的,所以肯定不能用完整的系统来虚拟,那样直接用虚拟机就好了 |
==================================================
首先拉取CentOS镜像
docker pull centos
==================================================
一、创建并启动容器(这个就是初期第一次创建时候用,可不要将它当成启动容器的命令)
docker run [option] 镜像名或镜像id [COMMAND][ARG]
option
--name=“容器名字”:为容器指定一个名称
-d:后台运行容器,并返回容器id,就是启动守护式容器
-i:以交互模式运行容器,通常和-t一起使用
-t:为容器重新分配一个伪输入终端,通常与-i一起使用
-P(大写的p):随机端口映射
-p(小写p):指定端口映射,有以下4种格式
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort
containerPort
举例
docker run -it centos
以伪交互的模式创建运行centos容器(你会发现你输入命令行是前面的内容变成[root@xxxxx容器地址])
此时你输入ls等命令,就会发现,目前命令行操作的是虚拟容器的centos,而不是你的linux本体centos
另外你不写-it,也会是同样的效果,因为默认就是运行容器并进入交互式
二、查看容器运行情况
docker ps [option]
查看docker中正在运行的容器(如果你还在刚才的为交互中,不在你的本机,你是查不到的,因为容器中,本来就没有docker,你需要重开一个交互窗口或者退出伪交互,才能看到)
option
-a:列出当前所有正在运行的容器+历史上运行过的
-l:显示最近创建的容器
-n:显示最近n个创建的容器
-q:静默模式,只显示容器编号
--no-trunc:不截断输出
举例
docker ps -n 3
把最近3次创建的容器显示出来
三、退出容器
exit
容器停止并退出
ctrl+P+Q
快捷键,容器退出但不停止运行,转为后台运行,此时想要重新进入,请看下面重要知识中内容
四、启动已创建过的容器
docker start 容器id
启动指定id容器
五、重启容器
docker restart 容器id
重启指定id容器
五、普通的慢慢的温柔的停止容器
docker stop 容器id或容器名
停止容器运行
六、强制停止容器
docker kill 容器id或容器名
强制结束容器生命,直接拔掉容器接口,使其停止
七、删除已停止容器
docker rm 容器id
删除指定id容器
docker rm -f $(docker ps -a -q)
$(查询出所有容器的id) 强制删除所有容器
=============================================
重要知识
=============================================
一、创建守护式容器(会自杀(自动终止))
docker run -d centos
参照上面的创建容器,[option] 为-d就表示创建守护式容器
docker ps
查询现在正在运行的容器,这时你会发现刚刚创建的守护式容器根本不在
这是因为,docker容器有一种机制,只要你这个容器没有前台交互,就自动终止这个容器
二、查看容器日志
docker logs -f -t --tall 容器id
查看指定容器的日志
-t:加入时间戳
-f:跟随最新的日志打印
--tall:数字显示最后多少条
三、创建不会自杀的守护式容器
前面我们说过,因为没有前台交互,守护式容器会自杀,那么我们可以让其通过不断打印,实现有前台交互
docker run -d centos /bin/sh -c "while true; do echo hello zzyy; sleep 2; done"
使用shell编程,让这个容器不断后台打印hello zzyy
socker ps
查看当前运行的容器,这时你会发现这个容器没有自杀
docker logs -t -f 容器id
查看容器日志,不想看了就按快捷键ctrl+c
三、查看容器内运行的进程
docker top 容器id
查看容器中正在运行的进程
四、查看容器内部细节
docker inspect 容器id
查看指定容器内部细节,因为容器时一层套一层的
五、进入正在运行的容器,并交互式
docker exec -it 容器id bashShell
不进入容器,直接在外面操作进程终端
举例
docker exec -it 容器id ls -l
此时不会进入容器,而是在外部执行ls -l命令到容器内部
docker attach 容器id
直接进入容器启动命令的终端,不会启动新的进程
举例
docker attach 容器id
进入容器
ls -l
执行查询列表命令
这个是进入容器内容运行命令,exec是在外部运行,而不进入容器内部
六、从容器内拷贝文件到主机
docker cp 容器id:容器内路径 目的主机路径
将容器中文件拷贝到主机的指定路径中
举例
docker cp 容器id:/a.txt /
将容器中根目录下a.txt文件拷贝到本机的根目录下
三、Docker镜像
1、镜像概述
镜像 |
---|
一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,包含运行某个软件所需的所有内容,比如代码,运行时,库,环境变量和配置文件等 |
镜像是一个联合文件系统UnionFS |
---|
分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一场提交来一层层叠加 ,同时可以将不同目录挂载到同一个虚拟文件系统下,是Docker镜像的基础,镜像可以通过分层来基础,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像 |
一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录 |
镜像加载原理 |
---|
镜像实际上由一层层的文件系统组成 |
在Docker镜像的最底层是bootfs |
bootfs主要包含BootLoader和kernel,BootLoader主要引导加载kernel,Linux刚启动时会加载bootfs文件系统 |
bootfs这一层与典型的Linux系统一样,包含boot加载器和内个,当boot加载完成之后整个内核就都在内存中了,此时内存使用权由bootfs转交给内核,此时系统卸载bootfs |
rootfs在bootfs之上,包含的就是典型Linux职工/dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Centos等等 |
为什么docker中的CentOS才200M而典型CentOS都好几个G |
---|
一个精简OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以,因为底层直接用Host和kernel,自己只需要提供rootfs就可以 |
不同linux的发行版bootfs基本一致,但rootfs会有差别,因此不同发行版可以公用bootfs(内核) |
上面的你可以不太懂,了解如下内容即可 |
---|
我们上面说过联合文件系统,什么意思呢,如果你开启tomcat容器,你会发现,这个容器有400多M |
这是因为联合文件系统就像俄罗斯套娃一样,一层套一层 |
最外层tomcat,依赖于jdk8,所有tomcat里面有一层jdk,jdk依赖于操作系统(比如centos),那么jdk里面就再套一层centos |
这么算下来,tomcat自然就大了 |
镜像好处 |
---|
资源共享,比如多个镜像都是从相同的base镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像 |
同时内存中也只需要加载一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以被共享 |
2、镜像特点
特点 |
---|
镜像都是只读的 |
容器启动时,一个新的可写层被加载到镜像的顶部 |
这一层通常被称作"容器层",“容器层"之下的都叫"镜像层” |
3、commit提交操作
docker commit
提交容器副本使之成为一新的镜像
docker commit -m="提交描述信息" -a="作者" 容器id 要创建的目标镜像名:[TAG]
提交指定容器副本,并指定描述,作者,名字和版本
举例
1、docker run -it -p 8888:8080 tomcat
运行tomcat并使用-p绑定端口,用docker的端口8888绑定容器内部tomcat的默认端口8080
此时你在浏览器访问8888端口就会打开tomcat了
如果你-p(小写)换成-P(大写),那么这个端口会随机分配,此时如果给你分配的3306,那么你浏览器访问3306会打开tomcat,因为tomcat默认是8080
2、docker commit -a="zzyy" -m="nothing" 容器id newTomcat:0.1
提交一个修改过(你自己看看怎么改,能看出来就行)容器
3、关闭所有正在运行的容器,通过docker ps查看是否关干净
4、然后docker images查看是否提交成功
5、docker run -it newTomcat:0.1
启动我们提交的容器
另外
如果你想让tomcat守护式运行在后台,不用写shell,因为tomcat自带前台交互,不会自杀
四、Docker 容器数据卷
1、概述
为什么使用容器数据卷 |
---|
Docker是将运行环境打包成容器,但是对数据我们是希望持久化的,容器之间我们希望可以共享数据 |
Docker容器产生的数据,如果不通过docker commit生成新的镜像,让数据作为新镜像一部分保留下来,那么容器关闭,数据自然消失 |
为了能保存数据而不生成新镜像,我们使用数据卷完成 |
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过联合文件系统提供的一些用于持续存储或共享数据的特性:
卷的设计目的就是数据的持久化,完全独立与容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
特点:
1、数据卷可在容器之间共享或重用数据
2、卷中的更改可以直接生效
3、数据卷中的更改不会包含在镜像的更新中
4、数据卷的生命周期一直持续到没有容器使用它为止
2、容器内的添加
一、直接命令添加
docker run -it -v /宿主机绝对路径:/容器内目录 [-v /宿主机路径2:/容器目录2...] 镜像名
以数据卷挂载形式启动容器
-v:数据卷的缩写,自带创建文件夹功能
举例======
docker run -it -v /testSZJ:/testContainer centos
以数据卷挂载形式启动容器,容器中根目录下的testContainer目录挂载到宿主机根目录下testSZJ目录
此时你可以通过docker images 容器id 查看json字符串中是否挂载成功,或者直接看容器中和宿主机中是否有相应文件夹
此时你操作容器中的数据卷文件夹,会发现数据自动同步到宿主机文件夹
此时如果你关闭当前容器,这时主机中数据卷文件夹修改后,下次容器重启时,数据依然同步,正真的实现数据共享
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
在上面的基础上,加上一个权限,就是容器内目录只读,不可写,也就是主机可以修改数据卷,而容器只能读这些文件,不能修改,也不能新建文件
二、DockerFile方式(具体是什么请看下节,就是描述文件,类似java中.java文件和.class文件的关系,写完java文件后,编译成.class文件运行。而DockerFile是docker镜像的描述文件)
3、数据卷容器
容器挂载数据卷,其它容器通过挂载这个父容器实现数据共享,挂载数据卷的容器,称之为数据卷容器 |
---|
docker run -it --name doc1 -v /宿主机路径:/容器内目录 镜像名
创建名字为doc1的父数据卷容器
docker run -it --name doc2 --volumes-from doc1 镜像名
退出doc1容器(不要关,让他后台运行),创建名字为doc2的容器,并继承doc1容器,此时doc1位doc2父容器
此时修改doc2中数据卷目录,doc1中也会同步
如果你这是创建一个doc3,让它也继承doc1,你会发现doc3也共享了
这时你关掉doc1,doc2修改后,doc3还是会共享
结论
容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止
五、DockerFile
1、概述
dockerfile |
---|
用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本 |
构建三步骤 |
---|
编写Dockerfile文件 |
docker build构建文件获取自定义镜像 |
docker run执行镜像获得容器 |
这是centos的DockerFile文件
FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20200611"
CMD ["/bin/bash"]
解析:
FROM 被继承镜像
继承一个镜像
scratch:源镜像(最顶级的镜像,所有其它镜像都继承它),类似java中的Object类
MAINTAINER The CentOS Project <cloud-ops@centos.org>
这个在上面文件中没有,这个的意思是作者和邮箱
ADD 要添加的压缩包
添加一个压缩包
LABEL 说明信息
各种描述,版本,发布日期等
CMD 默认提交数组
就是默认情况下帮我们提交的数组
比如
docker run -it centos
等价于
docker run -it centos /bin/bash
为什么不写呢,就是因为有CMD帮我们默认提交
2、DockerFile构建过程
基础规则 |
---|
每条保留字指令都必须为大写字母,后面必须至少跟一个参数 |
指令按从上到下顺序执行 |
#表示注释 |
每条指令都会创建一个新的镜像层,并对镜像进行提交 |
docker执行DockerFile流程 |
---|
docker从基础镜像运行一个容器 |
执行一条指令并对容器做出修改 |
执行类似docker commit的操作提交一个新的镜像层 |
docker再基于刚提交的镜像运行一个新的容器 |
执行dockerflie中的下一条指令直到所有指令都执行完成 |
总结 |
---|
dockerfile是软件的原材料 |
docker镜像是软件交付品 |
docker容器为软件的运行载体 |
dockerfile面向开发,镜像为交付标准,容器负责部署运行,三者相辅相成缺一不可 |
3、体系结构
FROM :基础镜像
指定当前镜像是基于哪个镜像的,比如centos是基于scrath衍生的
MAINTAINER
镜像维护者的姓名和邮箱
RUN
容器构建时需要运行的命令
EXPOSE
当前容器对外暴露出的端口号
WORKDIR
指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点,就是一进去容器,默认的工作目录
ENV
用来构建镜像过程中设置环境变量
比如:
ENV MY_PATH /usr/mytest
这个环境变量可以在后续任何RUN指令中使用,就像定义一个变量一样
例如
WORKDIR $MY_PATH
COPY
拷贝源路径文件和目录到镜像中目录中
COPY src dest
COPY ["src","dest"]
这两个都是一个意思,写法不同,代表将宿主机的src目录文件拷贝到镜像中dest目录中
只做拷贝,不做其他任何操作
ADD
将宿主机目录下的压缩文件拷贝进镜像,并且自动处理URL和解压压缩包
ADD centos-8-x86_64.tar.xz
自动寻找宿主机的对应压缩包路径,将其复制解压到镜像中
VOLUME
容器数据卷,用于数据保存和持久化工作
CMD
指定一个容器启动时要运行的命令,可以有多个,但只有最后一个生效,会被docker run之后的参数替换
指令格式
shell格式:CMD<命令>
exec格式:CMD["可执行文件","参数1","参数2"...]
参数列表格式:CMD["参数1","参数2"...] ,在指定了ENTRYPOINT指令后,用CMD指定具体的参数
ENTRYPOINT
指定一个容器启动时要运行的命令
ENTRPOINT 的目的和CMD一样,都是在指定容器启动程序及参数
和CMD不同的是,如果写多个,ENTRYPOINT都生效,而不是和CMD一样只有最后一个生效
ONBUILD
当构建一个被继承的DockerFile时运行的命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发
4、实际案例
Base镜像(scratch) |
---|
Docker Hub中99%的镜像都是通过base镜像中安装和配置需要的软件构建出来的 |
=================在根路径下mydocker目录中建立文件编写=====================
cd /mydocker
vim TestDockerFile
=======================================================================
一、编写一个自定义镜像
# 设置基础引用镜像为centos
FROM centos
# 设置环境变量,变量名为a,值为/tmp
ENV a /usr/local
# 引用环境变量设置创建容器后,终端默认登陆进来的工作目录为/usr/local
WORKDIR $a
# 运行命令,因为centos镜像没有vim和net-tools,就通过命令将其安装上
RUN yum -y install vim
RUN yum -y install net-tools
# 设置容器对外暴露的端口号
EXPOSE 80
# 设置容器启动时运行的命令
CMD /bin/base
=======================================================================
编写完成后按esc键
输入:wq命令保存并退出vim
cat TestDockerFile 查看是否保存编辑成功
=======================================================================
二、构建新镜像
docker build -t 新镜像名字:TAG . ------->看清楚命令最后面有一个点,不能丢
=======================================================================
docker build -f /mydocker/TestDockerFile -t mycentos:1.3 .
注意不要丢掉最后的点,点前面有空格的,此时就会找到我们创建的文件,并
以此创建一个mycentos镜像,版本为1.3
这个镜像会在centos的基础上额外的安装vim,net-tools,暴露端口为80,启动
默认目录为/usr/local,启动运行/bin/base
一定要等到Successfully字样出现后在做其它操作,否则可能构建失败
docker images
查询新镜像是否添加成功,运行后查看vim是否可以直接使用,ipconfig命令是否可以使用
=======================================================================
三、CMD命令
tomcat的DockerFile文件最后一行是
CMD ["catalina.sh","run"] 表示启动容器时如果末尾没有参数,会默认执行此命令,此命令表示启动tomcat
此时我执行这样的代码
docker run -it -p 7777:8080 tomcat ls -l
此时我们在末尾添加了参数,这样会取代CMD指令
现在就会出现打印出目录列表以后,不运行tomcat直接自杀的效果
或者我们可以自创容器,继承tomcat,然后写
CMD ls -l
此时这个新容器也会和上面一样的效果,因为CMD如果有多个,只执行最后一个
四、ENTRYPOINT命令
此命令比CMD强大,末尾有参数就追加执行不会覆盖
有多个也会追加执行