Docker 核心技术与基本原理

1. Docker 简介

1.1 背景

      首先,我们需要了解一下Docker产生的背景。在我们的服务器中,可能需要部署多个Web应用,这些Web应用采用不同的JDK版本、Tomcat版本等。这样可能就会导致一个问题,当我们启动项目时,并没有按照我们的意愿来选择JDK的版本。因为其他Web应用的依赖配置对该应用产生了影响,每个应用之间的环境没有彼此隔离。

      当然,我们如果细心一点也可以做到每个应用只使用其所依赖的环境,可参考如何在一台计算机上安装多个 JDK ,看了之后你可能觉得好麻烦啊,为什么不一台计算机部署一个项目,这样就不会由于彼此依赖的环境没有被隔离而产生影响。

      很多时候,如果一台计算机上只部署一个项目,并不能够充分的利用CPU和内存,极大的浪费了硬件资源。为此,产生了虚拟机,虚拟机便是利用虚拟化技术以及宿主机的硬件资源,从而实现一台虚拟化的计算机,其效果可以说是等同于一台真实的计算机。

在这里插入图片描述

      从上图中可以看到,我们可以在一台计算机上开启 3 台虚拟机,这个时候便可以将项目部署到各自的虚拟机内。

      笔者在使用虚拟机的时候,由于原本是4GB的内存,开了三台虚拟机后真实的物理机变得极为卡顿,不得不加了内存条。同时,我们启动虚拟机的过程也极为缓慢,得好几分钟。随着分布式技术的发展,集群环境极为常见,我们对项目的一点改变,都需要使该项目所有的集群进行改变,非常繁琐,且效率低下。

      正是由于以上的种种不足,产生了Docker技术,总结为以下几点。

  • 开发和运维之间因为环境不同而导致的矛盾
  • 集群环境下每台机器可轻松部署相同的应用
  • DevOps(流水线)

1.2 简介

      Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

      Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时"在我的机器上可正常工作"的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为 LinuxWindows Server 应用发布新功能。

在这里插入图片描述

1.3 Docker 优点

  • 简化程序

      Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,便可以实现虚拟化。

      Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管理。方便快捷已经是Docker的最大优势,过去需要用数天乃至数周的任务,在Docker容器的处理下,只需要数秒就能完成。

  • 避免选择恐惧症

      如果你有选择恐惧症,还是资深患者。Docker 帮你打包你的纠结!比如Docker镜像;Docker 镜像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。比如Web应用、后台应用、数据库应用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。

  • 节省开支

      一方面, 云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然高价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化的方式。

1.4 Docker 和虚拟机

特性Docker虚拟机
启动秒级分钟级
硬盘使用一般为MB一般为GB
性能接近原本弱于原生
系统支持量单机支持上千个一般是几十个

2. Docker 架构

      Docker采用 C/S 架构,Client 通过接口与 Server 进程通信,从而实现容器的构建、运行和发布。

在这里插入图片描述

2.1 Host(宿主机)

      安装了Docker程序,并运行了Docker daemon的主机。

2.1.1 Docker Daemon(Docker 守护进程)

      运行在宿主机上,Docker守护进程,用户通过Docker client(Docker命令)与Docker daemon交互。

2.1.2 Images(镜像)

      将软件环境打包好的模板,用来创建容器的,一个镜像可以创建多个容器。

      镜像分层结构

在这里插入图片描述
      位于下层的镜像称为父镜像(Parent Image),最底层的称为基础镜像(Base lmage)。

      最上层为"可读写"层,其下的均为“只读”层。

2.1.3 Containers(容器)

      Docker的运行组件,启动一个镜像就是一个容器, 容器与容器之间相互隔离,并且互不影响。

2.2 Docker Client(Docker客户端)

      Docker命令行工具,用户是用Docker ClientDocker daemon进行通信并返回结果给用户,也可以使用其他工具通过Docker ApiDecker doemon通信。

2.3 Registry(仓库服务注册)

      经常会和仓库(Repository)混为一谈,实际上Registry上可以有多个仓库每个仓库可以看成是一个用户, 一个用户的仓库放了多个镜像。仓库分为公开仓库和私有仓库。

      最大的公开仓库是官方的Docker Hub,国内也有如阿里云、时速云等,可以给国内用户提供稳定快速的服务。用户也可以在本地网络内创建一个私有仓库。 当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上pull下来就可以了。

3. Docker 安装

      Docker提供了两个版本:社区版(CE)和企业版(EE)。

      操作系统要求:

      以Centos7为例,且Docker要求操作系统必须为64位,且Centos内核版本为3.1及以上。

      查看系统内核版本信息:uname -r

在这里插入图片描述

3.1 准备

      卸载旧版本:

yum list installed | grep docker
yum -y remove ......

      卸载后将保留/var/lib/docker的内容(镜像、容器、存储卷和网络等)。

rm -rf /var/lib/docker

      1. 安装依赖软件包

yum insta11 -y yum-utils device-mapper-persistent-data lvm2
#安装前可查看device-mapper-persi stent-data和1vm2是否已经安装
rpm -qa | grep device-mapper-persistent-data
rpm -qa | grep lvm2

      2. 设置 yum

yum-config-manager --add-repo https://down1oad.docker.com/1inux/centos/docker-ce.repo

      3. 更新 yum 软件包索引

yum makecache fast

3.2 安装

      安装最新版本 docker-ce

yum insta11 docker-ce -y

#安装指定版本docker-ce可使用以下命令查看
yum list docker-ce.x86_64 --showduplicates | sort -r

#安装完成之后可以使用命令查看
docker version

3.3 配置镜像加速

  1. 找到/etc/docker目录下的daemon.json文件,没有则直接vi daemon.json
  2. 加入以下配置
#填写自己的加速器地址
{
	"registry-mirrors": ["https://registry.docker-cn.com"]
}
  1. 通知 systemd 重载此配置文件
systemctl daemon-reload
  1. 重启 docker 服务
systemctl restart docker

4. Docker 常用操作

4.1 镜像常用操作

      查找镜像

docker search 关键词
# 搜索 docker hub 网站镜像的详细信息

      下载镜像

docker pull 镜像名:TAG
# TAG 表示版本,有些镜像的版本显式 latest,为最新版本

      查看镜像

docker images
# 查看本地所有镜像

      删除镜像

docker rmi -f 镜像ID或者镜像名:TAG
# 删除指定本地镜像
# -f 表示强制删除

      获取元信息

docker inspect 镜像ID或者镜像名:TAG
# 获取镜像的元信息,详细信息

4.2 容器常用操作

      运行

docker run --name 容器名 -i -t -p 主机端口:容器端口 -d -v 主机目录:容器目录:ro 镜像ID或镜像名:TAG

# --name 指定容器名,可自定义,不指定自动命名
# -i 以交互模式运行容器
# -t 分配一个伪终端,即命令行,通常 -it 组合来使用
# -p 指定映射端口,将主机端口映射到容器内的端口
# -d 后台运行容器
# -v 指定挂载主机目录到容器陌路,默认为 rw 读写模式,ro表示只读 

      容器列表

docker ps -a -q
# docker ps 查看正在运行的容器
# -a 查看所有容器(运行中、未运行)
# -q 只查看容器的ID

      启动容器

docker start 容器ID或容器名

      停止容器

docker stop 容器ID或容器名

      删除容器

docker rm -f 容器ID或容器名
# -f 表示强制删除

      进入正在运行容器

docker exec -it 容器ID或容器名 /bin/bash
# 进入正在运行的容器并且开启交互模式终端
# /bin/bash 是固有写法,作用是因为 docker 后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动bash
# 也可以用 docker exec 在运行中的容器执行命令

      查看日志

docker logs 容器ID或容器名

      拷贝文件

docker cp 主机文件路径 容器ID或容器名:容器路径  # 主机中文件拷贝到容器中
docker cp 容器ID或容器名:容器路径  主机文件路径 # 容器中文件拷贝到主机中

      获取容器元信息

docker inspect 容器ID或容器名

5. Docker 网络

      Docker允许通过外部访问容器或容器互联的方式来提供网络服务。

      安装Docker时,会自动安装一块Docker网卡称为docker0, 用于Docker各容器及宿主机的网络通信,网段为172.0.0.1

      Docker网络中有三个核心概念:沙盒(Sandbox) 、网络(Network) 、端点(Endpoint) 。

  • 沙盒,提供了容器的虚拟网络栈,也即端口套接字、IP路由表、防火墙等内容。隔离容器网络与宿主机网络,形成了完全独立的容器网络环境。
  • 网络,可以理解为Docker内部的虚拟子网,网络内的参与者相互可见并能够进行通讯。Docker的虚拟网络和宿主机网络是存在隔离关系的,其目的主要是形成容器间的安全通讯环境。
  • 端点,位于容器或网络隔离墙之上的洞,主要目的是形成-一个可以控制的突破封闭的网络环境的出入口。当容器的端点与网络的端点形成配对后,就如同在这两者之间搭建了桥梁,便能够进行数据传输了。

5.1 Docker的四种网络模式

      Docker服务在启动的时候会创建三种网络,bridgehostnone, 还有一种共享容器的模式container

在这里插入图片描述

5.1.1 Bridge

      桥接模式,主要用来对外通信的,docker 容器默认的网络使用的就是 bridge

      使用 bridge 模式配置容器指定的网络配置

# 配置容器的主机名
docker run --name t1 --network bridge -h [自定义主机名] -it --rm busybox

# 自定义 DNS
docker run --name t1 --network bridge --dns 114.114 -it --rm busy

# 给 host 文件添加一条
docker run --name t1 --network bridge --add--host [hostname]:[ip] -it --rm busy

5.1.2 Host

      host 类型的网络就是主机网络的意思,绑定到这种网络上面的容器,内部使用的端口直接绑定在主机上对应的端口,而如果容器服务没有使用端口,则无影响。(不需要进行端口映射了)

docker run --name tomcat -d --network host tomcat

5.1.3 None

      从某种意义上来说,none 应该算不上网络了,因为它不使用任何网络,会形成一个封闭的网络容。

5.1.4 container

      共享一个容器的 network namespace,和 host 模式差不多,只是这里不是使用宿主机网络,而是使用的容器网络。

5.2 开放端口

      Docker0NAT 桥,所以容器一般获得的是私有网络地址

      给 docker run 命令使用 -p 选项即可实现端口映射,无需手动添加规则

  • -p 选项的使用
    • -p <containerPort>
      • 将指定的容器端口映射到主机所有地址的一个动态端口。
    • -p <hostPort>:<containerPort>
      • 将容器端口<containerPort>映射到主机指定<ip>的动态端口
    • -p <ip>::<containerPort>
      • 将指定的容器端口<containerPort>映射到主机指定<ip>的动态端口
    • -p <ip>:<hostPort>:<containerPort>
      • 将指定的容器端口<containerPort>映射到主机指定<ip>的端口<hostPort>
  • 动态端口指随机端口,可以用使用docker port命令查看具体映射结果
  • -P 暴露所有端口(所有端口指构建镜像时EXPOSE的端口)

自定义docker0桥的网络属性信息:/etc/docker/daemon.json文件

{
    "bip":"192.168.1.5/24",
    "fixed-cidr":"10.20.0.0/16",
    "fixed-cidr-v6":"2001:db8::/64",
    "mtu":1500,
    "default-gateway":"10.20.1.1",
    "dns":["10.20.1.2","10.20.1.3"]
}

      核心选项为bip,即bridge ip,用于指定docker0桥自身的IP地址;其他选项可通过此地址计算出

      创建自定义的桥

docker network create -d bridge --subnet "127.26.0.0/16" --gateway "127.26.0.1" mybr0

      注意,对网络修改后,需要删除之前的容器,否则 docker 启动失败,因为之前容器的网络配置被修改

6. 创建镜像

      有时候从 Docker 镜像仓库中“下载的镜像不能满足要求,我们可以基于一个基础镜像构建一个自己的镜像

      两种方式:

●更新镜像:使用docker commit命令

●构建镜像:使用docker build命令,需要创建Dockerfile文件

6.1 更新镜像

      先使用基础镜像创建一个容器, 然后对容器内容进行更改,然后使用docker commit命令提交为一个新的镜像(以tomcat为例)。

  1. 根据基础镜像,创建容器
docker run --name mytomcat -p 80:8080 -d tomcat
  1. 修改容器内容
docker exec -it mytomcat /bin/bash
cd webapps/R0OT
rm -f index. jsp
echo he11o world > index. htm1
exit
  1. 提交为新镜像
docker commit -m="描述消息" -a="作者” 容器ID或容器名镜像名:TAG
#例:
# docker commit -m="修改了首页" -a="wangzhao" mytomcat wangzhao/tomcat:v1.0
  1. 使用新镜像运行容器
docker run --name tom -p 8080:8080 -d wangzhao/tomcat:v1. 0

6.2 Dockerfile 构建镜像

6.2.1 Dockerfile 是什么

      Dockerfile是一个文本文档,其中包含用户可以在命令行上调用来构建镜像的所有命令。使用docker build 用户可以创建自动执行的构建,该构建可以连续执行多个命令行指令。

在这里插入图片描述

6.2.2 Dockerfile 格式

  • 格式
    • # 注释
    • 指令
  • 指令不区分大小写
    • 但是约定为,指令是大写,参数是小写的形式
  • Dockerfile 中的指令按序执行
  • Dockerfile 第一个指令必须是FROM,用来指定构建镜像的基础镜像

6.2.3 使用 Dockerfile 构建 SpringBoot 应用镜像

一、准备
  1. 把你的 SpringBoot 项目打包成可执行 jar 包
  2. 把 jar 包上传到 linux 服务器
二、构建
  1. jar 包路径下创建 Dockerfile 文件vi Dockerfile
#指定基础镜像,本地没有会从dockerHub pu11下来
FROM java:8

#从宿主机的当前目录下拷贝可执行jar包复制到基础镜像的根目录下
ADD xxxxx.jar /xxxxx.jar

#镜像要暴露的端口,如要使用端口,在执行docker run命令时使用-p生效
EXPOSE 80

#在镜像运行为容器后执行的命令
ENTRYPOINT ["java","-jar","/xxxxx.jar"]
  1. 使用docker build命令构建镜像,基本语法
docker build -t wangzhao/lemoncinema:v1 .
# -f 指定dockerfile 文件的路径
# -t 指定镜像名字和TAG
# . 指当前目录,这里实际需要一个上下文路径

在这里插入图片描述

三、运行
docker run --name lemoncinema -p 80:8080 664118cc3020

在这里插入图片描述

6.2.4 Dockerfile 常用指令

FROM

      FROM 指令是最重要的一个并且必须为Dockerfile文件的第一个非注释行,用于为镜像文件构建过程指定基础镜像,后续的指令运行于此镜像提供的运行环境。

      这个基础镜像可以是任何可用镜像,默认情况下docker build会从本地仓库找指定的镜像文件,如果不存在就会从Docker Hub上拉取。

      语法:

FROM <image>
FROM <image>:<tag>
MAINTAINER(将被废弃)

      Dockerfile 的制作者提供的本人详细信息

      Dockerfile 不限制 MAINTAINER 出现的位置,但是推荐放到FROM指令之后

      语法:

MAINTAINER <name>

      name可以是任何文本信息,一般用作者名称或者邮箱

LABEL(作用同MAINTAINER)

      给镜像指定各种元数据

      语法:

LABEL <key>=<value> <key>=<value> <key>=<value>...

      一个Dockerfile可以写多个LABEL,但是不推荐这么做,Dockerfile每一条指令都会生成一层镜像,如果LABEL太长可以使用\符号换行。

      构建的镜像会继承继承镜像的LABEL,并且会去掉重复的,但如果值不同,则后面的值会覆盖前面的值。

COPY

      用于从宿主机复制文件到创建的新镜像文件

      语法:

COPY <src>...<dest>
COPY ["<src>",..."<dest>""]
# <src>:要复制的源文件或者目录,可以使用通配符
# <dest>: 目标路径,即正在创建的 image 的文件系统路径:建议<dest>使用绝对路径,否则 COPY 指令则以WORKDIR为其起始路径

      注意:如果你的路径中有空白符,通常会使用第二种格式

      规则:

  • <src>必须是build上下文中的路径,不能是其父目录中的文件
  • 如果<src>是目录,则其内部我呢见或子目录会被递归复制,但<src>目录自身不会被复制
  • 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,则必须以/符号结尾
  • 如果<dest>不存在,将会被自动创建,包括其父目录路径
ADD

      基本用法和COPY指令一样,ADD 支持使用TAR文件和URL路径

      语法:

ADD <src>...<dest>
ADD ["<src>",..."<dest>"]

      规则:

  • COPY 规则相同
  • 如果<src>为URL并且<dest>没有以/结尾,则<src>指定文件将被下载到<dest>
  • 如果<src>为本地系统上的压缩格式的tar文件,它会展开成一个目录;但是通过URL获取的tar文件不会自动解压
  • 如果<src>有多个,直接或间接使用了通配符指定多个资源,则<dest>必须是目录并且以\结尾
WORKDIR

      用于为 Dockerfile 中所有的RUNCMDENTRYPOINTCOPYADD指定工作目录,只会影响当前WORKDIR之后的指令。

      语法:

WORKDIR <dirpath>

      在Dockerfile文件中,WORKDIR可以出现多次,路径可以是相对路径,但是它是相对于前一个WORKDIR指令指定的路径。

      另外,WORKDIR可以是ENV指定的变量。

VOLUME

      用来创建挂载点,可以挂载宿主机上的卷或者其他容器上的卷。

      语法:

VOLUME <mountpoint>
VOLUME ["<mountpoint>"]

      不能指定宿主机中的目录,宿主机挂载的目录是自动生成的。

ENV

      用来给镜像定义所需要的环境变量,并且可以被Dockerfile文件中位于其后的其他指令(如ENV、ADD、COPY等)所调用,调用格式:$varivale_name或者${variable_name}

      语法:

ENV <KEY> <VALUE>
ENV <KEY>=<VALUE>...

第一种格式中,<key>之后的所有内容都会被视为value的组成部分,所以一次只能设置一个变量。

第一种格式可以一个设置多个变量,如果<value>当中有空格可以使用\进行转义或者对value加引号进行标识,另外\也可以用来续行

ARG

      用法同ENV

      语法:

ARG <name>[=<default value>]

      指定一个变量,可以在docker build 创建镜像的使用,使用--build-arg <varname>=<value>来指定参数

RUN

      用来指定docker build过程中运行指定的命令

      语法:

RUN <command>
RUN ["<executable>", "<paraml>", "<param2>"]

      第一种格式里面的参数一般是一个shell命令,以/bin/sh -c来运行它。

      第二种格式中的参数是一个JSON格式的数组,其中<executable>是要运行的命令,后面是传递给命令的选项或者参数;但是这种格式不用用/bin/sh -c发起,所以常见的shell操作像变量替换和通配符替换不会进行;如果你运行的命令依赖shell特性,可以替换成类型一下的格式

RUN ["/bin/bash", "-c", "<executable>", "<paraml>"]
CMD

      容器启动时运行的命令

      语法:

CMD <command>
CMD ["executable", "param1", "param2"]
CMD ["<param1>","<param2>"]

      前两种语法和RUN相同

      第三种语法用于为ENTRYPOINT指令提供默认参数

      RUN和CMD区别

  • RUN 指令运行于镜像文件构建过程中,CMD 则运行于基于Dockerfile构建的镜像文件启动为一个容器的时候
  • CMD指令的主要目的在于给启动的容器指定默认要运行的程序,且在运行结束后,容器也将终止;不过,CMD命令可以被docker run 的命令行选项给覆盖
  • Dockerfile中可以存在多个CMD指令,但是只有最后一个会生效
ENTRYPOINT

      类似于CMD指令功能,用于给容器指定默认运行程序

      语法:

ENTRYPOINT <command>
ENTRYPOINT ["<executable>","<paraml>","<param2>"]

      和CMD不同的是ENTRYPOINT启动的程序不会被docker run命令指定的参数所覆盖,而且,这些命令行参数会被当做参数传递给ENTRYPOINT指定的程序(但是,docker run命令的--entrypoint参数可以覆盖ENTRYPOINT

      docker run命令传入的参数会覆盖CMD指令的内容并且附加到ENTRYPONT命令作为其参数使用。

      同样,Dockerfile中可以存在多个ENTRYPOINT指令,但是只有最后一个会生效。

      Dockerfile中如果既有CMD又有ENTRYPOINT,并且CMD是一个完整的可执行命令,那么谁在最后谁生效。

ONBUILD

      用来在 Dockerfile 中定义一个触发器

      语法:

ONBUILD <instruction>

      Dockerfile 用来构建镜像文件,镜像文件也可以当成是基础镜像被另外一个Dockerfile用作FROM指令参数。

      在后面这个Dockerfile中的FROM指令在构建过程中执行的时候,会触发基础镜像里面的ONBUILD指令。

      ONBUILD不能自我嵌套,ONBUILD不会触发FROMMAINTAINER指令。

      在ONBUILD指令中使用ADDCOPY要小心,因为新构建过程中的上下文在缺少指定的源文件的时候会失效。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值