Docker入门知识点总结

学习资料:《开发者必备的 Docker 实践指南》

1、虚拟化技术

虚拟机,虚拟化技术。
虚拟化技术,将计算机物理资源进行抽象,转换为虚拟的计算机资源提供给程序使用的技术。
虚拟化技术一般分两种:硬件虚拟化和软件虚拟化。
我们一般使用软件虚拟化,即在计算机硬件和程序之间,有一套虚拟化操作系统;程序执行命令时,是先将指令发动到虚拟机中,然后虚拟机再将指令转为计算机识别的指令。

扩展:JRE的即时编译,在运行前,就将程序代码编译为当前计算机识别的指令;而不是当程序执行时才编译。

用于实现程序跨平台

我们常碰到的虚拟技术:JVM虚拟机,实现了应用跨平台部署,只需要目标计算机安装了对应的JVM虚拟机,同一套程序就可以部署运行在不同的平台,例如windows、mac和linux。

用于资源管理

虚拟化技术将计算机的物理资源加工成虚拟的计算资源,从而可以对其做很多的改动。例如,我们可以告诉程序,计算机只有4G的内存,而不管真实的物理机可能是8G还是16G。
如果物理机的内存是16G,但是部署的一个程序只需要使用4G,那么我们还可以部署其他的程序,将空闲的内存利用起来。
但是同一个物理机部署多个不同的应用程序,可能会出现多种情况:不同的程序使用同一个端口号,不同的程序使用同一套不同版本的工具等等。但是使用虚拟化技术,可以解决这些问题,将不同程序通过资源隔离的方式隔离开来,使程序运行在不同的虚拟环境中,互相不影响。

2、容器技术

容器技术其实不是虚拟化技术,它是支持应用程序的运行被隔离在一个独立的运行环境之中,这个独立环境就像一个容器,包裹着应用程序。
容器技术没有做指令转换,运行在容器中的应用程序自身必须支持在真实操作系统上运行,也就是必须遵循硬件平台的指令规则。
正是容器技术没有指令转换,所以在效率上完胜虚拟机。
容器技术最主要还是做到一个资源隔离的功能,因为没有指令转换,做不到跨平台的功能;容器中运行的应用程序还是需要关注底层的操作系统。

3、Docker 核心组件

镜像:

  • 增量式更新,每次的修改都会构建成一个新的镜像层,一个镜像由多个镜像层组成。因为只会对修改做镜像层,而不是修改出一个完整的镜像,节省存储空间。

容器:

  • 运行环境+镜像

网络:

  • 同时支持一个容器一个网络环境,多个容器一个网络,互相隔离+相互共享。
  • 通过一些技术,在容器中营造域名解析环境,容器间可通过域名互相访问,不需要调整具体配置,迁移非常方便。

数据卷:

  • 从宿主操作系统中挂载目录外,还能够建立独立的目录持久存放数据,或者在容器间共享。

4、镜像与容器

镜像:

  • 镜像ID:64个字符串
  • 镜像名称:username/repository:tag
    • username:用户名,没有就是Docker自身维护
    • respository:一般为程序名
    • tag:版本号,缺省使用latest,即最新版本

容器:
生命周期:创建、运行、停止

5、从镜像仓库获取镜像

docker pull:拉取镜像
docker search:查找镜像
docker images:查看本地所有镜像
docker inspect:查看具体镜像的详细信息
docker rmi:删除镜像
docker commit -m “”:提交镜像
docker tag:

  • 命名:docker tag 容器ID repository:tag
  • 改名:docker tag 旧repository:tag 新repository:tag

docker save:输出镜像,支持批量迁移,多个容器以空格符号间隔开

  • $ sudo docker save webapp:1.0 > webapp-1.0.tar
  • $ sudo docker save -o ./webapp-1.0.tar webapp:1.0

docker load:导入镜像

  • $ sudo docker load < webapp-1.0.tar
  • $ sudo docker load -i webapp-1.0.tar

docker export:导出镜像,等于 docker commit + docker save
docker import:导入镜像
Docker 提供的镜像仓库:Docker Hub

6、运行和管理容器

docker create:创建容器,此时容器只是创建状态,还未运行
docker start:启动容器
docker run:融合 docker create + docker start
docker ps:查看容器
docker rm:删除容器
docker stop:停止容器
docker exec:

  • docker exec nginx cat /etc/hostname:执行命令
  • docker exec -it nginx bash:进入容器,后续可以在这个打开的伪客户端执行命令
    • -i:保持输入流
    • -t:伪客户端

docker attach:衔接到容器,容器转为前台执行,执行 ctrl+C命令会停止容器

7、配置网络

三个核心概念:

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

五种Docker网络驱动:Bridge DriverHost DriverOverlay DriverMacLan DriverNone Driver
其中,Bridge 网络是 Docker 容器的默认网络驱动,简而言之其就是通过网桥来实现网络通讯 ( 网桥网络的实现可以基于硬件,也可以基于软件 )。而 Overlay 网络是借助 Docker 集群模块 Docker Swarm 来搭建的跨 Docker Daemon 网络,我们可以通过它搭建跨物理主机的虚拟网络,进而让不同物理机中运行的容器感知不到多个物理机的存在。

7.1、容器互联

要让一个容器连接到另外一个容器,我们可以在容器通过 docker create 或 docker run 创建时通过 --link 选项进行配置。
例如我们启动一个 webapp 容器和一个 mysql 容器,webapp 容器需要和 mysql 容器连接,因为 webapp 中使用到 mysql 数据库。

$ sudo docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql
$ sudo docker run -d --name webapp --link mysql webapp:latest

webapp 容器中链接 mysql 的 url 类似如下:

String url = "jdbc:mysql://mysql:3306/webapp";

在 Docker 中,提供了类似域名解析的功能,容器间互相连接,不再需要知道具体的IP地址,只需要使用容器别名进行连接,Docker 会帮我们进行解析。这是一个非常方便的功能,不管后续我们是利用 Docker Compose 还是 Docker swarm 去进行容器部署和容器编排,都不再需要关注容器之间的IP地址。
别名:
上面是通过别名来进行容器互联,那假设后续我们使用的不是 mysql,而是 oracle,那么 webapp 里面的 url 配置又要进行调整吗?
在这里,我们使用 --link : 的形式,连接到 MySQL 容器,并设置它的别名为 database。当我们要在 Web 应用中使用 MySQL 连接时,我们就可以使用 database 来代替连接地址了。

$ sudo docker run -d --name webapp --link mysql:dtabase webapp:latest

后续假设要调整为 oracle 的容器,只需要调整容器名就可以了。

7.2、端口暴露和映射

端口暴露

我们的应用在容器中运行,都会监听指定的端口号,如果我们只是单纯将容器间的网络打通了,是无法访问到里面的应用的,所以我们需要将应用监听的端口号给暴露出来。我们可以在容器创建时通过 --expose 选项来完成。

$ sudo docker run -d --name webapp --link mysql --expose 8080 webapp:latest

端口映射

上面的端口暴露仅仅是容器直接通过 Docker 网络进行互相访问,如果我们需要通过外网来访问容器中的应用,我们需要使用 Docker 提供的端口映射,即将容器中的端口号映射到宿主机操作系统的端口号上。
我们可以在容器创建时利用 -p 或者是 --publish 选项来完成,端口映射格式:-p ::。其中IP是宿主机操作系统的监听IP,用来控制监听的网卡,默认0.0.0.0,也就是监听所有网卡。host-port 指的是宿主机操作系统的端口号,container-port 指的是容器的端口号。

$ sudo docker run -d --name webapp --link mysql -p 8080:80 webapp:latest

7.3、管理网络

Docker 服务的默认子网

上面的容器互联,前提是容器都是处于同一个网络中,当所有容器都处于同一个子网中,才能互相进行数据交换。
启动 Docker 服务,默认会创建一个 Bridge 网络,而创建的容器在不指定网络的情况下,默认都会连接到这个网络,所以上面的 webapp 容器才能连接到 mysql 容器。
可以利用 docker inspect 容器名 来查看容器的网络情况。

创建网络

在 Docker 里,我们也能够创建网络,形成自己定义虚拟子网的目的。
docker CLI 里与网络相关的命令都以 docker network 开头,其中创建网络的命令是 docker network create。
在 Docker 里,我们也能够创建网络,形成自己定义虚拟子网的目的。

$ sudo docker network create -d bridge individual

docker CLI 里与网络相关的命令都以 docker network 开头,其中创建网络的命令是 docker network create。
假设两个容器处于不同的网络中,那么是无法通过 --link 来进行连接的,启动容器时会报错。

8、管理和存储数据

容器讲究随用随开,随停随删。假设我们没有将容器运行期间的数据给持久化下来,那么当停止和删除容器时,数据也一起被删除掉。
Docker 容器文件系统基于 UnionFS 来支持挂载不同类型的文件系统都统一的目录结构中,我们只需要将宿主操作系统中,文件系统里的文件或目录挂载到容器中,便能够让容器内外共享这个文件。
由于通过这种方式可以互通容器内外的文件,那么文件数据持久化和操作容器内文件的问题就自然而然的解决了。

8.1、挂载方式

Bind Mount:能够直接将宿主操作系统中的目录和文件挂载到容器内的文件系统中,通过指定容器外的路径和容器内的路径(绝对路径),就可以形成挂载映射关系,在容器内外对文件的读写,都是相互可见的。
Volume:也是从宿主操作系统中挂载目录到容器内,只不过这个挂载的目录由 Docker 进行管理,我们只需要指定容器内的目录,不需要关心具体挂载到了宿主操作系统中的哪里。
Tmpfs Mount:支持挂载系统内存中的一部分到容器的文件系统里,不过由于内存和容器的特征,它的存储并不是持久的,其中的内容会随着容器的停止而消失。

8.2、挂载文件到容器

创建容器时可以通过 -v 或 --volume 选项来指定内外挂载的对应目录或文件,格式为:-v : 或 --volume :。挂载的目录或文件默认是读写,我们可以在后面加上:ro来指定只读。

$ sudo docker run -d --name webapp --link mysql -p 8080:80 -v /webapp/html:/usr/local/html:ro webapp:latest

其中 host-path 和 container-path 分别代表宿主操作系统中的目录和容器中的目录。这里需要注意的是,为了避免混淆,Docker 这里强制定义目录时必须使用绝对路径,不能使用相对路径。

8.3、挂载临时文件到容器

与挂载宿主操作系统目录或文件不同,挂载临时文件目录要通过 --tmpfs 这个选项来完成。由于内存的具体位置不需要我们来指定,这个选项里我们只需要传递挂载到容器内的目录即可。

$ sudo docker run -d --name webapp --tmpfs /webapp/cache webapp:latest

挂载临时文件,由于是挂载到内存中,适用于读写速度要求高,数据不需要持久化。

8.4、数据卷

Docker 还创造了数据卷 ( Volume ) 这个概念。数据卷的本质其实依然是宿主操作系统上的一个目录,只不过这个目录存放在 Docker 内部,接受 Docker 的管理。
在使用数据卷进行挂载时,我们不需要知道数据具体存储在了宿主操作系统的何处,只需要给定容器中的哪个目录会被挂载即可。
我们依然可以使用 -v 或 --volume 选项来定义数据卷的挂载。

$ sudo docker run -d --name webapp -v /webapp/storage webapp:latest

我们可以利用 docker inspect 命令来查看容器的信息,其中也是关注 Mounts 即可。数据卷的 Type 为 volume,其中我们还需要特别关注 source 和 name 字段。
其中 Source 是 Docker 为我们分配用于挂载的宿主机目录,其位于 Docker 的资源区域 ( 这里是默认的 /var/lib/docker ) 内。当然,我们并不需要关心这个目录,一切对它的管理都已经在 Docker 内实现了。
为了方便识别数据卷,我们可以像命名容器一样为数据卷命名,这里的 Name 就是数据卷的命名。在我们未给出数据卷命名的时候,Docker 会采用数据卷的 ID 命名数据卷。我们也可以通过 -v : 这种形式来命名数据卷。

共享数据卷

我们使用 -v 选项挂载数据卷时,如果数据卷不存在,Docker 会为我们自动创建和分配宿主操作系统的目录,而如果同名数据卷已经存在,则会直接引用。
我们还可以通过 docker volume 相关命令来操作数据卷:

  • docker volume create:创建数据卷
  • docker volume rm:删除指定数据卷
  • docker volume prune:删除没有被容器引用的数据卷
  • docker volume ls:查看数据卷列表

9、Dockerfile

Dockerfile 是 Docker 中用于定义镜像自动化构建流程的配置文件,在 Dockerfile 中,包含了构建镜像过程中需要执行的命令和其他操作。通过 Dockerfile 我们可以更加清晰、明确的给定 Docker 镜像的制作过程,而由于其仅是简单、小体积的文件,在网络等其他介质中传递的速度极快,能够更快的帮助我们实现容器迁移和集群部署。

9.1、Dockerfile 结构

总体上来说,我们可以将 Dockerfile 理解为一个由上往下执行指令的脚本文件。当我们调用构建命令让 Docker 通过我们给出的 Dockerfile 构建镜像时,Docker 会逐一按顺序解析 Dockerfile 中的指令,并根据它们不同的含义执行不同的操作。
如果进行细分,我们可以将 Dockerfile 的指令简单分为五大类。

  • 基础指令:用于定义新镜像的基础和性质。
  • 控制指令:是指导镜像构建的核心部分,用于描述镜像在构建过程中需要执行的命令。
  • 引入指令:用于将外部文件直接引入到构建镜像内部。
  • 执行指令:能够为基于镜像所创建的容器,指定在启动时需要执行的脚本或命令。
  • 配置指令:对镜像以及基于镜像所创建的容器,可以通过配置指令对其网络、用户等内容进行配置。

9.2、Dockerfile 指令

FROM:我们一般不会从零开始搭建镜像,而是选择一个已存在的镜像作为新镜像的基础,即基础镜像。
RUN:向控制台发送命令,执行的命令对文件系统的修改会被记录下来,形成镜像的变化。
ENTRYPOINT 和 CMD:基于镜像启动的容器,在容器启动时会根据镜像所定义的一条命令来启动容器中进程号为 1 的进程。而这个命令的定义,就是通过 Dockerfile 中的 ENTRYPOINT 和 CMD 实现的。
EXPOSE:暴露端口号。
VOLUME:绑定数据卷。
COPY 和 ADD:从宿主机的文件系统里面拷贝内容到镜像文件系统中。ADD 支持网络端URL和自动进行解压,COPY不支持。
ARG:创建参数变量,可以在构建镜像时传入对应变量值
ENV:创建环境变量,环境变量在 Dockerfile 里设置默认值,也可在构建镜像时传入对应的变量值进行覆盖;环境变量和参数变量的区别是:环境变量在容器运行的程序中也可以获取到。

9.3、构建镜像

构建镜像的命令为 docker build

$ sudo docker build 目标目录

可利用 -t 选项指定新镜像的名称,可利用 -f 选项单独给出 Dockerfile 文件路径,否则默认从当前目录查找 Dockerfile 文件。

$ sudo docker build -t 新镜像名称 -f 目标目录

可利用 --bulid-arg 选项指定变量值

$ sudo docker build --build-arg TOMCAT_VERSION=8.0.53 -t 新镜像名称 -f 目标目录

9.4、合并命令

在使用 RUN 执行命令时,如果是多个命令,我们建议使用 \ 符号进行换行分割;因为每执行一个命令,Docker 都会基于上条命令的结果启动一个容器,然后执行命令并将结果打包城一个镜像层,如此反复最后才会形成镜像;利用合并命令,我们可以避免创建大量的镜像层,避免镜像构建过程中返回创建容器,从而提高镜像创建的速度。

10、Docker Compose

由于 Docker 采用轻量级容器的设计,每个容器一般只运行一个软件,而目前绝大多数应用系统都绝不是一个软件所能组成的。

10.1、未使用 Docker Compose 来搭建容器群

例如我们此时需要在本地部署一套 wabapp 运行的环境(包含数据存储和缓存),那么我们可以分别利用 docker run 去运行一个 mysql 容器和一个 redis 容器,然后利用 Dockerfile 为 webapp(配置比较繁杂) 定义镜像构建的逻辑,并且在运行 webapp 容器时,需要利用 --link 选项与其他容器进行互联系。

虽然我们之前提到了容器间互相连接、交换数据的各种方法,通过这些方法足以搭建起完整的用于应用系统运行的容器群,但是这显然还不够,这个容器群的搭建需要执行太多命令,更重要的是需要考虑太多应用和容器间的依赖关系处理,是一波令人头大的操作。

10.2、使用 Docker Compose 来搭建容器群

在未使用 Docker Compose 来搭建容器群时,虽然我们利用 docker run 命令就可以完成,但是关于容器间的依赖不能在一个地方进行统一管理,而是需要利用命令选项来完成。
Docker 提供了 Docker Compose,虽然 Docker Compose 目前也是由 Docker 官方主要维护,但其却不属于 Docker Engine 的一部分,而是一个独立的软件。所以如果我们要在 Linux 中使用它,还必须要单独下载使用。
Docker Compose 是一个由 Python 编写的软件,在拥有 Python 运行环境的机器上,我们可以直接运行它,不需要其它的操作。

10.2.1、使用 Docker Compose 的步骤,可以简单分成三步。

  1. 如果需要的话,编写容器所需镜像的 Dockerfile;( 也可以使用现有的镜像 )
  2. 编写用于配置容器的 docker-compose.yml;
  3. 使用 docker-compose 命令启动应用。

其中最重要的是步骤2,docker-compose 配置文件中 services 模块完整地描述了整个容器群中,每个容器的配置(镜像或Dockerfile文件、端口号、数据卷、环境配置等)和容器间的依赖关系。

10.2.2、启动和停止

docker-compose up:根据 docker-compose.ymal 文件,创建所有容器、网络和数据卷,并将他们启动。

  • 默认是在前台运行,可添加 -d 选项在后台运行
  • 默认是在当前目录找 docker-compose.ymal 文件,可通过 -f 选项指定文件路径

docker-compose down:停止所有容器
docker-compose logs:查看容器日志

10.3、配置项

services:容器群里面所有相关服务配置

  • build:基于 Dockerfile 构建镜像
  • image:直接使用镜像
  • depends_on:声明依赖
  • volumes:文件挂载
  • ports:端口映射

volumes:数据卷
networks:网络配置

11、Docker swarm

如果容器都在同一个子网中,Docker 提供了类似域名解析的功能,通过容器名可以进行网络互联。那假设容器都在不同 Docker 环境中,如何实现跨主机网络呢?此时需要 Overlay Network ,它能够跨越物理主机的限制,让多个处于不同 Docker daemon 实例中的容器连接到同一个网络,并且让这些容器感觉这个网络与其他类型的网络没有区别。
要搭建 Overlay Network 网络,我们就要用到 Docker Swarm 这个工具了。Docker Swarm 是 Docker 内置的集群工具,它能够帮助我们更轻松地将服务部署到 Docker daemon 的集群之中。
在真实的服务部署里,我们通常是使用 Docker Compose 来定义集群,而通过 Docker Swarm 来部署集群。
Docker Swarm 部署集群步骤:

  1. 通过 docker swarm init 来初始化集群,在集群初始化后,当前 Docker 实例就自动成为了集群的管理节点。
  2. 其他 Docker 实例可以通过运行这里所打印的 docker swarm join 命令来加入集群
  3. 通过 docker network create 命令来建立 Overlay 网络
    1. $ sudo docker network create --driver overlay --attachable mesh
  4. Docker Compose 文件网络配置添加上面创建的 Overlay 网络
networks:
	mesh:
		external: true
  1. Docker Compose 文件中,其他服务添加上面创建的 Overlay 网络

services:

  redis:
    image: redis:3.2
    networks:
      - mesh
......省略......

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值