容器三大特征(要素):

镜像(image)

容器(container)

仓库(repository)

仓库(Repository)是集中存放镜像的场所。 仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放多个仓库,每个仓库中又包含了多个镜像,每个镜像有不通的标签(tag)。、 仓库分为公开仓库(public)和私有仓库(private)两种形式。 最大的公开仓库是Docker Hub(https://hub.docker.com),存放了数量庞大的镜像提供用户下载。 国内的公开仓库包括阿里云,网易云等。

三要素小结

image.png

docker安装

支持Centos版本

Centos6.5(64-bit)版本及以上。 Centos7内核版本要求3.10以上. Centos6.5或更高的系统,内核版本要求2.6.32-431以上。 查看自己的内核: uname -r

docker 架构图

image.png

Centos6.8安装docker

  1. # 1、安装epel
  2. yum install -y epel-release
  3. # 2、安装docker
  4. yum install -y docker-io
  5. # 3、安装后的配置文件
  6. /etc/sysconfig/docker
  7. # 4、启动docker后台服务。
  8. service docker start
  9. # 5、验证
  10. docker version

Centos7安装docker

https://docs.docker.com/engine/install/centos/#prerequisites

镜像加速

# 阿里云(推荐)
https://dev.aliyun.com

Centos6配置方法

vim /etc/sysconfig/docker
将获得的自己账户下的阿里云加速地址配置进
other_args="--registry-mirror=https://自己的账号加速信息.mirror.aliyuncs.com"
保存退出,重启docker
service restart docker
验证是否成功:
ps -ef | grep docker

image.png

Centos7 ++配置方法

 mkdir -p /etc/docker
 tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://e53aervw.mirror.aliyuncs.com"]
}
EOF
 systemctl daemon-reload
 systemctl restart docker

Docker run hello-world

执行之后的输出
image.png

run干了什么?

image.png

Docker底层原理

Docker是怎么工作的

Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接收命令并管理运行在主机上的容器。容器,是一个运行时环境,就是鲸鱼背上的集装箱。

为什么Docker比较VM快

1、docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在cpu,内存利用率上docker将会在效率上有明显优势。
2、docker利用的是宿主机的内核,而不需要Guest OS.因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。从而避免引寻,加载操作系统内核这个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了这个过程,因此新建一个docker容器只需要几秒钟。
image.png

Docker 命令(部分)

帮助命令

# 查看docker基本信息
docker version
# 查看docker信息,比version更详细
docker info
# docker帮助命令
docker --help

镜像命令

列出本地主机上的镜像

docker images [options] 

options 选项:
-a : 列出本地所有的镜像(包含中间映像层)
-q : 只显示镜像ID
--digests : 显示镜像的摘要信息
--no-trunc : 显示完整的镜像信息

image.png
各选项说明

  • REPOSITORY : 表示镜像的仓库员
  • TAG : 镜像的标签
  • IMAGE ID : 镜像ID
  • CREATED : 镜像创建时间
  • SIZE : 镜像大小

同一个仓库源可以有多个TAG,代表这个仓库的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果不指定一个镜像的版本标签,例如只是用ubuntu,docker将默认使用Ubuntu:latest镜像。

docker search 某个镜像的名字

查询仓库中的镜像。
网址:https://hub.docker.com

docker search  [options]  镜像名字
options选项:
--no-trunc : 显示完整的镜像描述
-s : 列出收藏数不小于指定值的镜像
--automated : 只列出 automated build 类型的镜像

docker pull 某个镜像名字

下载镜像

docker pull tomcat[:TAG]

# docker pull tomcat 等价于 docker pull tomcat:latest

docker rmi 某个镜像名字ID

删除某个镜像

docker rmi -f 镜像ID(或唯一镜像名)           # 删除单个
docker rmi -f 镜像名1:TAG 镜像名2:TAG        # 删除多个
docker rmi -f $(docker images -qa)         # 删除全部

容器命令

有镜像才能创建容器,所以我们需要下载一个镜像(centos镜像) docker pull centos

docker run [options] image [command] [arg]

新建并启动容器
启动交互是容器

docker run  [options]  image [command] [arg]
options 选项(常用):
--name="容器新名字" : 为容器指定一个名称
-d : 后台运行容器,并返回容器id,即启动守护式容器
-i : 以交互模式运行容器,通常与 -t 参数一起使用 ( 常用 )
-t : 为容器重新分配一个伪输入终端,通常与 -i 参数一起使用( 常用 )
-P : 随机端口映射
-p : 指定端口映射,有以下四种格式
     ip:hostPort:containerPort
     ip::containerPort
     hostPort:containerPort
     containerPort

例:启动一个Centos容器
docker run -it --name mycentos01  831691599b88 # 以交互模式启动一个名称为mycentos01的容器,启动容器使用的镜像id为831691599b88
docker run it 831691599b88   # 不指定容器名称,直接以交互模式启动容器,并且进入伪终端。

image.png

docker ps [options]

列出当前所有正在运行的容器

docker ps [options]
options选项(常用):
-a : 列出当前所有正在运行的容器+历史上运行过的
-l : 显示最近创建的容器
-n : 显示最近 n 个创建的容器
-q : 静默模式,只显示容器编号
--no-trunc : 不截断输出

退出容器的两种方式

容器停止退出
exit

容器不停止退出
ctrl+p+q

docker start 容器ID或容器名称

启动容器

docker restart 容器ID或容器名称

重启容器

docker stop 容器id或者容器名称

正常停止容器

docker kill 容器id或者名称

强制停止容器

docker rm 容器ID

删除已停止的容器
一次性删除多个容器

docker -rm -f $(docker ps -aq)
docker ps -aq | xargs docker rm

启动守护式容器

docker run -d 容器名(个人觉得这里应该写的是镜像名称,老师笔记有点问题)
# 使用镜像 centos:latest 以后台模式启动一个容器

问题:然后使用docker ps -a进行查看,发现容器已经退出。
很重要的一个说明:Docker容器后台运行,就必须有一个前台进程。
容器运行的命令如果不是那些一直挂起的命令(比如top,tail),就是会自动退出。
这个是docker的机制问题,比如web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start。
但是,这样做NGINX为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀,因为它觉得它没事可做了。
所以,最佳的解决方案是将要运行的程序以前台进程的形式运行。

查看docker日志

docker logs -f -t --tail 容器ID

-t : 加入时间戳
-f : 跟随最新的日志打印
--tail 数字 : 显示最后多少行

例:使用如下命令跑一个docker容器
docker run -d centos /bin/sh -c "while true;do echo hello lhh;sleep 2;done"

然后使用 docker ps 命令查出容器ID
image.png
通过 docker logs -f --tail 3 容器id查看日志
image.png

查看容器内运行的进程

docker top 容器ID

查看容器内部细节

docker inspect 容器ID

进入正在运行的容器并以命令行交互

docker exec -it 容器ID  bashShell
docker attach 容器ID  # 重新进入

上述两个命令的区别
  • attach直接进入容器启动命令的终端,不会启动新的进程

image.png
进入容器启动命令打开的终端。

  • exec 是在容器中打开新的终端,并且可以启动新的进程

image.png
执行完之后直接将bashShell命令的结果返回到宿主机的终端。
docker exec -it 容器ID /bin/bash 打开一个新的容器终端。效果同 attach

将容器内的内容拷贝到宿主机上

docker cp 容器ID:容器内路径   目的主机路径

image.png
image.png

容器命令小结

image.png
………………


Docker镜像原理

是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

  1. UnionFS(联合文件系统)

    UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。(举例,类似于吃的花卷) 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

  2. Docker镜像加载原理

    docker的镜像实际上由一层一层文件系统组成,这种层级的文件系统UnionFSbootfs(boot file system)主要包含bootloaderkernelbootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。 rootfs(root file system)在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如 Ubuntu,Centos等等。 image.png 问题:平时我们安装进虚拟机的Centos都是好几个G,为什么docker这里才215M? image.png 对于一个精简的OSrootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就行了。由此可见针对不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同发行版可以公用bootfs

  3. 分层镜像

    以pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的下载。 image.png

  4. 为什么Docker镜像要采用这种分层结构呢

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

特点

Docker镜像都是只读的 当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

Docker镜像commit操作补充

  • docker commit 提交容器副本,使之成为一个新的镜像
  • docker commit -m=”提交的描述信息” -a=”作者” 容器ID 要创建的目标镜像名:[标签名]
  • 案例演示

1、从Hub上下载tomcat镜像到本地并成功运行

docker run -it -p 8888:8080 tomcat  
-p  主机端口:docker容器端口
-P  随机分配端口
-i  交互
-t  终端

docker run -it -P tomcat 
-P  随机端口

image.png
2、故意删除上一步镜像生产tomcat容器的文档
3、也即当前的Tomcat运行实例是一个没有文档内容的容器,以它为模板commit一个没有doc的tomcat新镜像atguigu/tomcat2

#由于版本问题,最新的tomcat中默认就没有那些文件,所以我自己在目录中创建了一个index.html
#                 作者名         描述              容器id       命名空间   镜像名    版本号
docker commit -a="xuliang" -m="add index.html"  7154d4cf4d2a atxuliang/tomcat01:1.1

image.png

4、启动我们新的镜像并和原来的对比
image.png

Docker容器数据卷(做数据持久化)

  • 容器数据卷用 v 命令添加

docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

是什么

有点类似于redis里面的rdb和aof

docker理念:

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

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

能干嘛

1、容器的持久化

2、容器间继承+共享数据

卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能绕过Union File System 提供一些用于持续存储或共享数据的特性:

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此docker不会在容器删除的时候删除其挂载的数据卷。

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

数据卷

在容器内添加数据卷

1、直接命令添加

1.1 命令
docker run -it -v  /宿主机绝对路径目录:/容器内目录  镜像名
docker run -it -v  /myDataVolume:/dataVolumeContainer centos
#执行命令的时候宿主机绝对路径目录和容器内的目录不必要一定存在,docker会自动帮助我们创建。

1.2 查看数据卷是否挂载成功
docker inspect  容器id

执行完命令之后出现如下图中圈起来的信息则表示挂载成功。
image.png

1.3容器和宿主机之间数据共享

当确认数据卷挂载成功之后即可在指定的目录中记录数据,此时无论是在容器中记录还是再宿主机上记录,他们的数据都将共享。

image.png
容器停止退出后,主机修改后数据是否同步?
image.png

1.4命令(带权限)

docker run -it -v /宿主机绝对路径目录:/容器内目录:``ro `` 镜像名

如果不带权限的话,创建的数据卷读写权限为true,如下图: image.png

                                             权限:只读   read only  简写 ro 
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro  镜像名
docker run -it -v /myDataVolume:/dataVolumeContainer:ro  centos

如果带权限的话,容器数据卷的权限将根据设定的值来定,如:docker run -it -v /myDataVolume:/dataVolumeContainer:ro centos 启动容器之后,数据卷的权限如下图: image.png

2、DockerFile添加

需求

1、根目录下新建mydocker文件夹进入
2、可在Dockerfile中使用VOLUME指令给镜像添加一个或多个数据卷

VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2","/dataVolumeContainer3"] 说明:使用 VOLUME 指令添加数据卷 只指定容器内的 出于可移植和分享的考虑, 用 -v 主机目录:容器目录 这种方法不能够直接在Dockerfile中实现 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。

3、File构建

# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,------success1"
CMD /bin/bash

# 将上面的Dockerfile 翻译成docker命令大致如下
# docker run -it -v /host1:/dataVolumeContainer1  -v /host2:/dataVolumeContainer2  centos  /bin/bash

4、build后生成镜像。——> 获得一个新镜像xuliang/centos

docker build -f /mydocker/Dockerfile -t xuliang/centos . image.png

5、run运行容器

docker run -it 8fd3faa5af7c image.png

6、通过上述步骤,容器内的卷目录地址已经知道,对应的主机目录地址在哪?

image.png image.png

  • Docker挂载主机目录Docker访问出现 cannot open directory .: Permission denied

解决办法: 在挂载目录后面多加一个 --privileged=true 参数即可。 例:docker run -it -v /myDataVolume:/dataVolumeContainer ----privileged=true 镜像名

7、主机对应默认地址

数据卷容器

是什么

命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

总体介绍

以上一步新建的镜像 xuliang/centos 为模板并运行容器dc01,dc02,dco3 它们已经具有容器卷: /dataVolumeCentainer1 /dataVolumeCentainer1

容器间传递共享( —volumes-from)

1、先启动一个父容器 ——> 在dataVolumeContainer2新增内容
2、dc02/dc03继承自dc01

--volumes-from 命令

3、回到dc01可以看到02、03各自添加的都能共享了
4、删除dc01、dc02修改后dc03可否访问? 可以
5、删除dc02后dc03可否访问 可以
6、新建dc04继承dc03后再删除dc03 可已
7、结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

DockerFile解析

是什么

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

构建三步骤:

  1. 编写Dockerfile文件
  2. docker buile
  3. docker run

文件什么样?如下:

# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,------success1"
CMD /bin/bash

DockerFile构建过程解析

DockerFile内容基础知识

1、每条保留字指令都必须为大写字母且后面至少要跟随一个参数
2、指令从上到下,顺序执行
3、# 表示注释
4、每条指令都会创建一个新的镜像层,并对镜像进行提交

Docker执行DockerFile的大致流程

1、docker从基础镜像运行一个容器
2、执行一条指令并对容器作出修改
3、执行类似docker commit的操作提交一个新的镜像层
4、docker再基于刚提交的镜像运行一个新容器
5、执行dockerfiel中的下一条指令,直到所有指令都执行完成。

小总结

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

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

DockerFile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系基石。 image.png

DockerFile体系结构(保留关键字)

  • FROM : 基础镜像,当前新镜像是基于哪个镜像的
  • MAINTAINER : 镜像维护者的姓名和邮箱地址
  • RUN : 容器构建时需要运行的命令
  • EXPOSE :当前容器对外暴露出的端口
  • WORKDIR :指定在创建容器后,终端默认登录进来工作目录,一个落脚点。
  • ENV :用来在构建镜像过程中设置环境变量
  • ADD :将宿主机目录下的文件拷贝进镜像,且ADD命令会自动处理URL和解压tar包。
  • COPY :a、类似ADD,拷贝文件和目录到镜像中。b、将从构建上下文目录中<源路径>的文件/目录复制到新的一层镜像内的<目标路径>位置
  • VOLUME :容器数据卷,用于数据保存和持久化工作
  • CMD :a、指定一个容器启动时要运行的命令。b、DockerFile 中可以有多个CMD命令,但只有最后一个生效,CMD会被docker run之后的参数替换
  • ENTRYPOINT :a、指定一个容器启动时要运行的命令。b、ENTRYPOINT和CMD一样,都是在指定容器启动程序及参数。
  • ONBUILD :当构建一个被继承的DockerFile时运行命令,父镜像在被子继承后,父镜像的onbuild被触发。

    案例

    Base镜像

    docker hub中99%的镜像都是通过在baes镜像中安装和配置需要的软件构建出来的

自定义镜像mycentos

  1. 编写

Hub默认Centos镜像什么情况? image.png 准备编写dockerfile文件,大致内容如下

FROM centos
ENV mypath /tmp
WORKDIR $mypath
RUN yum -y install vim
RUN yum install -y net-tools
EXPOSE 80
CMD /bin/bash

myCentos内容Dockerfile 内容如下:

FROM centos
MAINTAINER xuliang<xuliang_in@163.com>

ENV mypath /usr/local
WORKDIR $mypath

RUN yum install -y net-tools vim
RUN yum clean all

EXPOSE 80

CMD echo $mypath
CMD echo "success-------ok"
CMD /bin/bash
  1. 构建 ——> docker build -t 新镜像名字:TAG .

image.png image.png

  1. 运行 docker run -it 新镜像名字:TAG
  2. 列出镜像的变更历史 docker history 镜像id

image.png

CMD/ENTRYPOINT镜像案例

1、都是指定一个容器启动时要运行的命令 2、CMD Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换 case —> tomcat的讲解演示 |docker run it -p 7777:8080 tomcat ls -l 这样执行之后tomcat是没有启动的。 3、ENTRYPO docker run 之后的参数会被当做参数传递给 ENTRYPOINT ,之后形成新的命令组合。 case : a、制作CMD版可以查询IP信息的容器

FROM centos
RUN yum install -y curl
CMD [ "curl","-s","http://ip.cn" ]

b、问题 c、WHY d、制作ENTROYPOINT版查询IP信息的容器

自定义镜像tomcat9

1、mkdir -p /zzyyuse/mydockerfile/tomcat9
2、在上述目录下touch c.txt
3、将jdk和tomcat安装的压缩包拷贝进上一步目录
apache-tomcat-9.0.37.tar.gz jdk-14.0.2_linux-x64_bin.tar.gz
4、在/zzyyuse/mydockerfile/tomcat9目录下新建Dockerfile文件
5、构建
6、run
7、验证
8、结合前述的容器卷将测试的web服务test发布。

小总结