直接上瘾!百万人都在学的 Docker
1、环境简介
1.1、系统简介
1.1.1、Docker 简介
💡Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。
一个完整的 Docker 有以下几个部分组成:
dockerClient 客户端
Docker Daemon 守护进程
Docker Image 镜像
DockerContainer 容器
Docker 引擎 Docker Engine 是 C/S 架构,主要有以下部件组成:
服务器(Docker daemon):后台运行的 Docker daemon 进程。Daemon 进程用于管理 Docker 对象,包括镜像(images)、容器(containers)、网络(networks)、数据卷(data volumes)。
REST 接口:同 daemon 交互的 REST API 接口。
客户端(Docker client):命令行(CLI)交互客户端。客户端使用 REST API 接口同 Docker daemon 进行访问。Docker 服务的架构图如图 1-1 所示。
图 1-1 Docker 服务的架构图
1.1.2、Docker 平台组成
图 1-2 Docker 服务组成图
运行一个 Docker 服务,组成包括 Docker daemon 服务器、Docker Client 客户端、Docker Image 镜像、Docker Registry 库、Docker Contrainer 容器,如图 1-2 所示。
(1)Docker 镜像:是一个只读模板,用于创建 Docker 容器,由 Dockerfile 文本描述镜像的内容。镜像定义类似“面对对象的类”,从一个基础镜像(Base Image)开始。构建一个镜像实际就是安装、配置和运行的过程,Docker 镜像基于 UnionFS 把以上过程进行分层(Layer)存储,这样更新镜像可以只更新变化的层。Docker 的描述文件为 Dockerfile,Dockerfile 是一个文本文件,基本指令包括:
FROM:定义基础镜像。
MAINTAINER :作者或维护者。
RUN:运行 linux 命令。
ADD:增加文件或目录。
EVN:定义环境变量。
CMD:运行进程。
(2)Docker 容器:是一个镜像的运行实例。容器有镜像创建,运行过程例如:
运行 ubuntu 操作系统镜像,-i 前台交互模型,运行命令为/bin/bash
拉(pull)镜像,Docker Engine 检查 ubuntu 镜像是否存在,如果本地已经存在,使用该镜像创建容器,如果不存在,Docker Engine 从镜像库拉镜像。
使用该镜像创建新容器。
分配文件系统,挂载一个读写层,在读写从加载镜像。
分配网络/网桥接口,创建一个网络接口,让容器和主机通信。
从可用的 IP 池选择 IP 地址,分配给容器。
执行命令/bin/bash。
捕获和提供执行结果。
(3)Docker 仓库:Docker 仓库是 Docker 镜像库。Docker Registry 也是一个容器。Docker Hub 是 Docker 公司提供的互联网公共镜像仓库。可以构建自己本地的镜像仓库,国内有些公司也构建了镜像仓库。包括阿里云、新浪等。Docker 集群服务:Docker 集群服务运行承租的 Docker 节点一起工作。目前支持 swarm 模式。
一个 Docker Registry 节点中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
一般而言,一个仓库包含的是同一个软件的不同版本的镜像,而标签则用于对应于软件的的不同版本。
可以通过 <仓库名>:<标签> 的格式来指定具体是哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
以Ubuntu镜像为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,14.04, 16.04。可以通过 ubuntu:14.04,或者 ubuntu:16.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest。
1.2、预装环境说明
1.2.1、软件版本说明
宿主机系统:CentOS 7.9
Docker 版本: 1.13.1
1.2.2、基础环境配置
💡本次实验环境采用下面的基础环境 1-4 步骤进行基础设置,请勿遗漏。
1.2.2.1.关闭 selinux
1.2.2.2.关闭防火墙
1.2.2.3.删除 iptables 防火墙规则
1.2.2.4.修改系统内核
2、服务安装
2.1、安装 Docker 服务
2.1.1、CentOS 安装 Docker
2.1.2、Ubuntu 安装 Docker
3、镜像
在之前的介绍中,我们知道镜像是 Docker 的三大组件之一。 Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker 会从镜像仓库下载(默认是 Docker Hub 公共 注册服务器中的仓库)。 本章将介绍更多关于镜像的内容,包括: 从仓库获取镜像; 管理本地主机上的镜像; 介绍镜像实现的基本原理。
本节将介绍更多关于镜像的内容,包括:
从仓库获取镜像;
管理本地主机上的镜像;
介绍镜像实现的基本原理。
3.1、设置镜像加速(阿里云)
点击此处设置阿里云镜像加速服务:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
修改为阿里云镜像加速
3.2、拉取镜像(pull)
可以使用 docker pull 命令来从仓库获取所需要的镜像。 这里使用 nginx 镜像作为演示
3.3、列出镜像(images)
在列出信息中,可以看到几个字段信息
来自于哪个仓库(REPOSITORY)---> docker.io/nginx
比如 nginx 镜像的标记(TAG),比如 latest
它的 ID 号(唯一)---> b692a91e4e15
创建时间 ---> 2 days ago
镜像大小 ---> 142 MB
3.4、创建镜像(commit/import/Dockerfile)
3.4.1、使用 commit 创建镜像
💡其中, -m 来指定提交的说明信息,跟我们使用的版本控制工具一样; -a 可以指定更新的用户信息;之后是用来创建镜像 的容器的 ID;最后指定目标镜像的仓库名和 tag 信息。创建成功后会返回这个镜像的 ID 信息。
3.4.2、使用 Dockerfile 创建镜像
Dockerfile 是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker 通过读取 Dockerfile 中的指令自动生成映像。
3.4.3、Dockerfile 详解
Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。
Dockerfile 基本的语法如下
使用 # 来注释
MAINTAINER 镜像作者信息
FROM 指令告诉 Docker 使用哪个镜像作为基础
RUN 开头的指令会在创建中运行,比如安装一个软件包,在这里使用 yum 来安装了一些软件
COPY 从 Docker 宿主机复制文件至创建的新镜像文件
ADD 类似于 COPY 指令,ADD 支持 tar 文件和 URL 路径
WORKDIR 用于为 Dockerfile 中所有的 RUN、CMD、ENTRYPOINT、COPY、ADD 指定设定工作目录
VOLUME 数据卷,用于在 image 中创建挂载点目录,以挂载 Docker host 上的卷或者其他容器上的卷
EXPOSE 为容器打开指定的监听端口以实现与外部通信
ENV 用于为镜像定义所需的环境变量,可以被 Dockerfile 文件中其他命令调用(ENV、ADD、COPY、RUN、CMD)
CMD 启动容器指定默认要运行的程序或命令,默认"/bin/sh -c"运行
ENTRYPOINT 类型 CMD 指令的功能,用于为容器指定默认运行程序或命令
USER 指定当前用户
3.4.3.1、FROM
格式为 FROM <IMAGE> 或 FROM <IMAGE>:TAG。
第一条指令必须为 FROM 指令。并且,如果在同一个 Dockerfile 中创建多个镜像时,可以使用多个 FROM 指令(每个镜像 一次)。
3.4.3.2、MAINTAINER
格式为 MAINTAINER <AUTHOR_NAME> ,指定维护者信息。
3.4.3.3、RUN
格式为:
RUN <Command>
RUN ["executable", "param1", "param2"]
前者将在 shell 终端中运行命令,即 /bin/sh -c ;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实 现,例如 RUN ["/bin/bash", "-c", "echo Build_Dockerfile"] 。
每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。
3.4.3.4、COPY
格式:
COPY <src>... <dest>
COPY ["<src1>",... "<dest>"]
和 RUN 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。
复制本地主机的 <src>.(为 Dockerfile 所在目录的相对路径)到容器中的<dest>。
当使用本地目录为源目录时,推荐使用 COPY 。
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像 内的 <目标路径> 位置。比如:
<源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则,如:
COPY /root/* /mnt/
COPY /root/*.html /usr/share/nginx/html/
<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工 作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存 在会在复制文件前先行创建缺失目录。 此外,还需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留。比如 读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建 相关文件都在使用 Git 进行管理的时候。
3.4.3.5、ADD
格式为 ADD <src> <dest>。
该命令将复制指定的 <drc> 到容器中的<Dest> 。
其中<drc>可以是 Dockerfile 所在目录的一个相对路径;也可以是 一个 URL;还可以是一个 tar 文件(自动解压为目录)。
3.4.3.6、WORKDIR
格式为 WORKDIR <Your_Work_Dir>
为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。
可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如
最终路径为 /mnt/dir1/dir2
3.4.3.7、USER
格式为 USER <用户名>
USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR 是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及 ENTRYPOINT 这类命令的身份。
注意: USER 只是切换用户,该用户必须事先存在
3.4.3.8、VOLUME
格式为 VOLUME ["/data"] 。
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
3.4.3.9、EXPOSE
格式为 EXPOSE [...] 。
告诉 Docker 服务端容器暴露的端口号,供互联系统使用。
这只是一个声明,在运行时并不 会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映 射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
3.4.3.10、ENV
格式有两种:
ENV <KEY> <VALUE>
ENV <KEY>=<VALUE>
这个指令就是设置环境变量,无论是后面的其它指令,如 RUN ,还是运行时的应用,都可以直接使用这里定义的环境变量。定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
这里的例子演示了定义 MYSQL 的用户和密码
3.4.3.11、CMD
支持三种格式,分别是:
CMD ["executable","param1","param2"] 使用 exec 执行(推荐);
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。<br />如果指定了多条命令,只有最后一条会被执行。
如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如, centos 镜像默认的 CMD 是 /bin/bash ,如果我们直接 docker run -it centos ,会直接进入 bash 。
也可以在运行时指定运行别的命令,如 docker run -it centos cat /etc/redhat-release。这就是用 cat /etc/redhat-release 命令替换了默认的 /bin/bash 命令
在指令格式上,一般推荐使用** exec **格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 " ,而不要使用单引号。
如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行 执行。比如:
CMD echo $USERNAME 在实际执行中,会将其转换为
CMD ["sh","-c","echo $USERNAME"]
这就是为什么我们可以使用环境变量的原因,因为这些环境变量会被 shell 进行解 析处理。 提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出 现的一个混淆。
3.4.3.12、ENTRYPOINT
ENTRYPOINT 成为 入口点
ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式和 shell 格 式。
拥有两种格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2 (shell 中执行)。
配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。 每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参 数。 ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。 当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行 时,将变为:
<ENTRYPOINT> "CMD"
3.4.4、Dockerfile 演示
3.4.4.1、构建带有 openssh-server 功能的容器镜像
centos-7 镜像为基础镜像,安装 openssh-server 服务,暴露端口 22,容器开机运行 sshd
编写完成 Dockerfile 后可以使用 docker build 来生成镜像。
其中 -t 标记来添加 tag,指定新的镜像的用户信息。
“.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径
3.5、标记(tag)
info 以阿里云为例,稍后会在仓库小节进行详细描述
3.6、上传镜像(push)
以阿里云为例,稍后会在仓库小节进行详细描述
3.7、导出/导入(save/load)
如果要导出镜像到本地文件,可以使用 docker save 命令。
可以使用 docker load 从导出的本地文件中再导入到本地镜像库
3.8、使用 supermin5 构建镜像
使用 supermin5 命令构建 centos7 系统的 docker 镜像,镜像名称为 centos-7,镜像预装 yum、net-tools、initscripts 和 vi 命令
3.9、删除镜像(rmi)
4、容器
容器是 Docker 又一核心概念。
简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作 系统(提供了运行态环境和其他系统环境)和跑在上面的应用。
本节将具体介绍如何来管理一个容器,包括创建、启动和停止等
4.1、查看容器
4.2、启动/停止容器
4.2.1、创建并启动新容器
常用附加参数:
-d 在后台运行容器并打印容器 ID
-t 选项让 Docker 分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
-i 则让容器的标准输入保持打开。
-p 映射端口 宿主机端口:容器端口
-P 随机映射端口
-v 绑定卷
-w 设置工作目录
--rm 退出容器自动删除
--restart 重启条件,若宿主机开机要求该容器也运行 那么请设置 --restart=always
--name 设置容器名称
4.2.2、启动已停止的容器
4.2.3、停止正在运行的容器
4.3、删除容器
4.4、连接容器
在使用 -d 参数时,容器启动后会进入后台。 某些时候需要进入容器进行操作,包括使用 docker attach 命令或 docker exec 命令,推荐使用 docker exec 命令
4.4.1、attach 命令
使用 attach 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗 口因命令阻塞时,其他窗口也无法执行操作了。
当使用 attach 退出时,容器也会退出
4.4.2、exec 命令
docker exec 后边可以跟多个参数,一般使用 -i -t 参数。 只用 -i 参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示 符,但命令执行结果仍然可以返回。 当 -i -t 参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符。
4.5、导入导出容器
4.5.1、导出容器
4.5.2、导入容器
5、仓库
仓库(Repository)是集中存放镜像的地方。
一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓 库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。
例如对于仓库地址 registry.cn-hangzhou.aliyuncs.com/fl_test/docker_demo 来说
registry.cn-hangzhou.aliyuncs.com 是注册服务器地址
fl_test 是仓库名
docker_demo 为镜像名称
5.1、远程仓库
目前 Docker 官方维护了一个公共仓库 Docker Hub,其中已经包括了超过 15,000 的镜像。大部分需求,都可以通过在 Docker Hub 中直接下载镜像来实现。
下面以阿里云容器镜像服务为大家演示
5.1.1、创建阿里云镜像仓库
点击创建阿里云镜像仓库(杭州站):https://cr.console.aliyun.com/cn-hangzhou/instance/dashboard
仓库信息--->设置 命名空间 仓库名称 仓库类型 以及 说明
设置代码源 ---->本地仓库
5.1.2、登录远程仓库
可以通过执行 docker login 命令来输入用户名、密码和邮箱来完成注册和登录。 注册成功后,本地用户目录的 .dockercfg 中将保存用户的认证信息。
5.2、本地私有仓库
有时候出于安全和网络情况考虑,云上仓库并不方便,那么,用户可以创建一个本地仓库供私人使用。 本节介绍如何使用本地仓库。 docker-registry 是官方提供的工具,可以用于构建私有的镜像仓库。
5.2.1、安装并运行本地 registry 仓库
5.2.2、查看仓库中镜像
6、数据管理
6.1、数据卷
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷可以在容器之间共享和重用
对数据卷的修改会立马生效
对数据卷的更新,不会影响镜像
卷会一直存在,直到没有容器使用
数据卷的使用,类似于 Linux 下对目录或文件进行 mount。
6.1.1、创建数据卷
6.1.2、挂载数据卷
6.1.3、删除数据卷
数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在 容器被删除后自动删除 数据卷 ,并且也不存在垃圾回收这样的机制来处理没有任 何容器引用的 数据卷 。如果需要在删除容器的同时移除数据卷。可以在删除容器 的时候使用 docker rm -v 这个命令。
无主的数据卷可能会占据很多空间,要清理请使用以下命令
6.2、挂载主机目录
6.2.1、挂载主机目录作为数据卷
也可以使用 -v 标记也可以指定挂载一个本地主机的目录到容器中去。
上面的命令加载主机的 /root/web 目录到容器的** /usr/share/nginx/html 目录。
这个功能在进行测试的时候十分方便,比如 用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它。
注意:Dockerfile 中不支持*这种用法,这是因为 Dockerfile 是为了移植和分享用的。然而,不同操作系统的路径格式不一 样,所以目前还不能支持。
Docker 挂载数据卷的默认权限是读写,用户也可以通过 :ro 指定为只读。
6.2.2、挂载主机文件作为数据卷
同样,使用 -v 来进行挂载,从主机挂载单个文件到容器
6.3、容器间共享卷
在这个案例中,将使用三个 nginx 容器进行演示,分别为 nginxweb1、nginxweb2、nginxweb3
7、网络管理
7.1、映射网络
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。 使用 docker ps 可以看到,本地主机的 49153 被映射到了容器的 80 端口。此时访问本机的 49153 端口即可访问容器 内 web 应用提供的界面。
7.2、使用主机网络
可以使用 --network=host 参数来直接使用宿主机网络
7.3、容器互联
7.3.1、新建网络
-d 参数指定 Docker 网络类型,有 bridge overlay 。其中 overlay 网络 类型用于 Swarm mode,在本小节中你可以忽略它。
7.3.2、容器互联
7.3.3、ping 测试
7.4、自定义 docker0 网络
7.4.1、移除原有网络
7.4.1.1、安装 btctl 命令
7.4.1.2、查询网桥信息
7.4.1.3、关闭 docker 服务
7.4.1.4、停止 docker0 网桥
7.4.1.5、删除 docker0 网桥
7.4.1.6、查询所有网桥信息
7.4.2、自定义新网络
7.4.2.1、创建新网桥 bridge0
7.4.2.2、查询创建的 bridge0
7.4.2.3、设置新网桥的网络段地址
7.4.2.4、启动 bridge0 网桥
7.4.2.5、查询 bridge0 网桥信息
7.4.2.6、添加新网桥到配置文件
7.4.2.7、加载配置文件,重启 docker 服务
7.4.3、使用新网络部署应用
7.4.3.1、创建一个 nginx 容器
7.4.3.2、查看容器的状态
7.4.3.3、查看容器的 bridge
8、Nginx 负载均衡(轮询)
8.1、创建测试网页
8.2、创建测试容器 nginx1 nginx2
8.3、创建 nginx.conf 配置文件
配置文件中的 172.31.36.113 为宿主机的内网 IP 地址,请按实际情况修改
8.4、创建 nginx 负载均衡容器
8.5、负载测试
版权声明: 本文为 InfoQ 作者【指剑】的原创文章。
原文链接:【http://xie.infoq.cn/article/2743d4908271072bd5346ac83】。文章转载请联系作者。
评论