1.docker基础命令
在我们学习具体的命令之前,我们先要注册一个docker的账号
https://www.docker.com/(进入网址即可注册)
镜像仓库命令
下面是使用实战
docker login
关键参数
○ -u : 登陆的用户名
○ -p : 登陆的密码
docker pull
关键参数
○ -a : 拉取所有 tagged 镜像
○ --disable-content-trust : 忽略镜像的校验 , 默认开启
可以直接拉取对应的名字+标签或者对应的digest也可以。
docker push
○ -a : 推送所有 tagged 镜像
○ --disable-content-trust : 忽略镜像的校验 , 默认开启
(不过由于中国ip被墙了,暂时无法推送到docker的仓库,后期可以改成阿里云或者私人仓库)
docker search
关键参数
○ --no-trunc : 显示完整的镜像描述;
○ -f < 过滤条件 >: 列出收藏数不小于指定值的镜像。
从 Docker Hub 查找所有镜像名包含 nginx ,并且 star 数大于 10 的镜像
docker search -f stars=10 nginx
docker logout
docker logout即可登出仓库
2.Docker Image**(镜像)**
1.Docker****镜像是什么
• Docker image 本质上是一个 read-only 只读文件, 这个文件包含了文件系统、
源码、库文件、依赖、工具等一些运行 application 所必须的文件。
• 我们可以把 Docker image 理解成一个模板, 可以通过这个模板实例化出来很多
容器。
• image 里面是一层层文件系统 Union FS 。联合文件系统,可以将几层目录挂载到
一起,形成一个虚拟文件系统。
每一层文件系统我们叫做一层 layer ,联合文件系统可以对每一层文件系统设置三
种权限,只读( readonly )、读写( readwrite )和写出( whiteout-able ),但是 docker
镜像中每一层文件系统都是只读的。
构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层
的修改,增加了一层文件系统。一层层往上叠加,上层的修改会覆盖底层该位置的可
见性,这也很容易理解,就像上层把底层遮住了一样。当你使用的时候,你只会看到
一个完全的整体,你不知道里面有几层,也不清楚每一层所做的修改是什么。
2.为什么需要镜像
在部署应用时,通过手工或写一些脚本的方式进行部署。这样部署面临问题就是云端
和本地环境一致问题。用户为每个应用打包过程比较繁琐,需要配置和给中修改等操
作,非常费劲。
然而, Docker 镜像就是为了解决这个小小的 打包 功能,突然一夜之间成名。那么,你
可能说 Docker 镜像就是个压缩包,是的,你猜对了,它就像一个压缩包文件。它是如
何解决 Paas 时代所面临的云端和本地一致性问题?很简单,它是把一个镜像制作成
一个完整的操作系统所有文件和对应的目录结构,这样的压缩包是跟你本地和测试环
境用的操作系统一摸一样。
docker 最大的贡献就是定义了容器镜像的分层的存储格式 , docker 镜像技术的基础
是联合文件系统 (UnionFS) ,其文件系统是分层的。这样既可以充分利用共享层,又可
以减少存储空间占用。
docker 镜像提供了一种打包应用程序和预配置服务器环境的便捷方式,可以很方便的
将其用于个人用途或与其他 Docker 用户公开 共享 。
删除本地镜像
镜像命令**[部分]**
1.docker images
关键参数
○ -a : 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);
○ --digests : 显示镜像的摘要信息;
○ -f : 显示满足条件的镜像;
○ --format : 指定返回值的模板文件;
○ --no-trunc : 显示完整的镜像信息;
○ -q : 只显示镜像 ID 。
2.docker image inspect
查看镜像详细信息
3. docker tag
4.docker rmi
○ -f : 强制删除;
○ --no-prune : 不移除该镜像的过程镜像,默认移除;
5.docker save
○ -o : 输出到的文件。
6.docker load
○ --input , -i : 指定导入的文件,代替 STDIN 。
○ --quiet , -q : 精简输出信息
7.docker history
○ -H , --human : 大小和日期采用人容易读的格式展现
○ --no-trunc : 显示全部信息,不要隔断;
○ -q, --quiet: 只显示镜像 id 信息;
8.docker image prune
删除不使用的镜像。
○ -a , --all : 删除全部不使用的镜像;
○ --filter filter: 指定过滤条件;
○ -f, --force : 不提示是否删除;
3.容器
什么是容器?
通俗地讲,容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要
的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容
器有初建、运行、停止、暂停和删除五种状态。
虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资
源限制。也就是说,在容器内部,无法看到主机上的进程、环境变量、网络等信息,
这是容器与直接运行在主机上进程的本质区别。
容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。
运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个
容器层,该层允许修改镜像的整个副本
为什么需要容器?
镜像是静态的文件,并不能提供服务,就像我拿了个 Linux 或者 Windows 的光盘一样,
只有安装到主机里面运行起来才能对外提供服务,我们才能使用。
容器带来哪些收益呢,参考我们之前讲解的为什么要虚拟化、容器化。
容器的生命周期
容器的生命周期是容器可能处于的状态。
- created :初建状态
- running :运行状态
- stopped :停止状态
- paused : 暂停状态
- deleted :删除状态
各生命周期之间的转换关系如图所示:
容器****OOM
Docker 在处理 OOM 事件时分为三种情况
1 )如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发 OOM 事件。
例如,在容器当中,部署了一个 web 服务。假设主机分配给此容器的内存上限为 1G ,
当脚本申请的内存大于 1G 时,此容器就会触发 OOM 事件。而在这种情况下,此容
器将会被强制关闭。
但需要注意的是,此时关闭容器的并非是 Docker Daemon ,而是宿主机操作系统。因
为一个容器其实就是一组运行在宿主机操作系统当中的进程,宿主机操作系统通过
cgroups 对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿
主机操作系统的内核 OOM 事件,因此最终是由宿主机内核来关闭这些进程 .
(2) 如果用户不想关闭这个容器,那么可以选择 --oom-kill-disable 来禁用 OOM-Killer 。
使用此参数时,仍需要注意,如果使用 -m 设置了此容器内存上限,那么当容器到达内
存资源上限时,主机不会关闭容器,但也不会继续向此容器继续分配资源,此时容器
将处于 hung 状态。只需要将最坏的情况封闭在一定范围之内,而不至于蔓延出去。
(3) 如果用户使用了 --oom-kill-disable ,但也没有使用 -m 来设定上限,因而此时此容器
将会尽可能多地使用主机内存资源。换言之,主机内存有多大,它就将用多大。
容器异常退出
每个容器内部都存在一个 Init 进程,容器中其他所有进程都是此进程的子进程。运行
的容器是因为 Init 进程在运行,如果一个子进程因为某种原因造成了退出,那么其父
进程也会同步退出,直至 Init 进程也退出。当 Init 进程退出时,也就代表着此容器被关
闭。 ocker 目前没有办法知道此时的进程退出属于正常退出还是异常退出。当出现容器
关闭情况时, Docker Daemon 会尝试再次重新将此容器由 Stopped 状态转为 Running
状态。只有设置了 --restart 参数的容器, Docker Daemon 才会去尝试启动,否则容器
会保持停止状态。
容器暂停
Docker" 剥夺 " 了此容器的 CPU 资源。而其他资源,如 Memory 资源、 Network 资源
等还保留未动。如此一来,失去了 CPU 资源的进程,是不会被主机内核系统所调度的,
所以此容器就处于 " 冰封 " 状态。
容器命令**[部分]**
1. docker run
功能
创建一个新的容器并运行一个命令
关键参数
○ -d: 后台运行容器,并返回容器 ID ;
○ -i: 以交互模式运行容器,通常与 -t 同时使用;
○ -P: 随机端口映射,容器内部端口 随机 映射到主机的端口
○ -p: 指定端口映射,格式为: 主机 ( 宿主 ) 端口 : 容器端口
○ -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
○ --name="nginx-lb": 为容器指定一个名称;
○ -h "mars": 指定容器的 hostname ;
○ -e username="ritchie": 设置环境变量;
○ --cpuset-cpus="0-2" or --cpuset-cpus="0,1,2": 绑定容器到指定 CPU 运行;
○ -m : 设置容器使用内存最大值;
○ --network="bridge": 指定容器的网络连接类型;
○ --link=[]: 添加链接到另一个容器;
○ --volume , -v: 绑定一个卷
○ --rm :shell 退出的时候自动删除容器
我们先先拉一个centos:7下来,然后运行这个容器。
映射端口的使用
其余的大家可以自己尝试,不过多赘述
2.docker ps
关键参数
○ -a : 显示所有的容器,包括未运行的。
○ -f : 根据条件过滤显示的内容。
○ --format : 指定返回值的模板文件。如 json 或者 table
○ -l : 显示 latest 的容器。
○ -n : 列出最近创建的 n 个容器。
○ --no-trunc : 不截断输出。
○ -q : 静默模式,只显示容器编号。
○ -s : 显示总的文件大小。
3.docker create
创建一个新的容器但不启动它
○ **-i:**以交互模式运行容器,通常与 -t 同时使用;
○ -P: 随机端口映射,容器内部端口 随机 映射到主机的端口
○ -p: 指定端口映射,格式为: 主机 ( 宿主 ) 端口 : 容器端口
○ -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
○ --name="nginx-lb": 为容器指定一个名称;
○ -h "mars": 指定容器的 hostname ;
○ -e username="ritchie": 设置环境变量;
○ --cpuset-cpus="0-2" or --cpuset-cpus="0,1,2": 绑定容器到指定 CPU 运行;
○ -m : 设置容器使用内存最大值;
○ --network="bridge": 指定容器的网络连接类型;
○ --link=[]: 添加链接到另一个容器;
○ --volume , -v: 绑定一个卷
○ --rm :shell 退出的时候自动删除容器
○ --restart : 自动重启
与docker run几乎一样,只是少一个-d选项。
4.docker logs
○ -f ,--follow: 跟踪日志输出
○ --since : 显示某个开始时间的所有日志
○ -t,--timestamps : 显示时间戳
○ -n , --tail : 仅列出最新 N 条容器日志
.
5. docker attach
连接到正在运行中的容器
○ --sig-proxy:是否将所有信号代理,默认是 true,如果设置为 false,退出的 话不会影响容器,否则退出会导致容器退出。
6. docker exec
在容器中执行命令
○ -d : 分离模式 : 在后台运行
○ -i : 即使没有附加也保持 STDIN 打开
○ -t : 分配一个伪终端
○ -e : 设置环境变量
○ -u,--user : 指定用户 "<name|uid>[:<group|gid>]"
○ -w,--workdir: 指定工作目录
(通常使用-it配合bash命令,进入容器进行操作)
7. docker start
8. docker stop
-s 发送SIGTERM信号
9. docker kill
-s发送SIGKILL信号
Docker stop 发送的是 SIGTERM信号,docker kill 发送的是 SIGKILL信号
10. docker restart
11. docker top
容器运行时不一定有 /bin/bash 终端来交互执行 top 命令,而且容器还不一定有
top 命令,可以使用 docker top 来实现查看 container 中正在运行的进程。
12. docker stats
○ --all , -a : 显示所有的容器,包括未运行的。
○ --format : 指定返回值的模板文件。如 table,json
○ --no-stream : 展示当前状态就直接退出了,不再实时更新。
○ --no-trunc : 不截断输出。
返回报文
CONTAINER ID 与 NAME: 容器 ID 与名称。
CPU % 与 MEM %: 容器使用的 CPU 和内存的百分比。
MEM USAGE / LIMIT: 容器正在使用的总内存,以及允许使用的内存总量。
NET I/O: 容器通过其网络接口发送和接收的数据量。
BLOCK I/O: 容器从主机上的块设备读取和写入的数据量。
PIDs: 容器创建的进程或线程数。
13. docker container inspect
○ -f : 指定返回值的模板文件。如 table 、 json
○ -s : 显示总的文件大小。
14. docker port
用于列出指定的容器的端口映射,或者查找将 PRIVATE_PORT NAT 到面向公众
的端口。
15. docker cp
在容器和宿主机之间拷贝文件
16. docker diff
检查容器里文件结构的更改
17. docker commit
从容器创建一个新的镜像。
○ -a : 提交的镜像作者;
○ -c : 使用 Dockerfile 指令来创建镜像;可以修改启动指令
○ -m : 提交时的说明文字;
○ -p : 在 commit 时,将容器暂停。
18.docker pause
暂停容器中所有的进程。
19. docker unpause
恢复容器中所有的进程。
20. docker rm
○ **-f :**通过 SIGKILL 信号强制删除一个运行中的容器。
21. docker export/import
○ **-o:**写入到文件。
○ -c : 应用 docker 指令创建镜像;
○ -m : 提交时的说明文字
22. docker wait
阻塞运行直到容器停止,然后打印出它的退出代码。
23. docker rename
重命名容器
24. docker container prune
○ -f, --force:不提示是否进行确认
25. docker update.
更新容器配置
○ --cpus**:**cpu 数量
○ --cpuset-cpus : 使用哪些 cpu
○ --memory : 内存限制
○ --memory-swap :交换内存
○ --cpu-period : 是用来指定容器对 CPU 的使用要在多长时间内做一次重新分
配
○ --cpu-quota : 是用来指定在这个周期内,最多可以有多少时间用来跑这个容
器
总结
常见问题
docker create 、 docker start 和 docker run 有什么区别?
docker create 命令从 Docker 映像创建一个全新的容器。但是,它不会立即运行它。
docker start 命令将启动任何已停止的容器。如果使用 docker create 命令创建容器,
则可以使用此命令启动它。
docker run 命令是创建和启动的组合,因为它创建了一个新容器并立即启动它。实际
上,如果 docker run 命令在您的系统上找不到上述映像,它可以从 Docker Hub 中提
取映像。
docker import 和 docker load 有什么区别?
想要了解 docker load 与 docker import 命令的区别,还必须知道 docker save
与 docker export 命令:
• docker save images_name :将一个镜像导出为文件,再使用 docker load 命
令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比 docker export 命令
导出的文件大,很好理解,因为会保存镜像的所有历史记录。
• docker export container_id :将一个容器导出为文件,再使用 docker
import 命令将容器导入成为一个新的镜像,但是相比 docker save 命令,容器文件
会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
既可以使用 docker load 命令来导入镜像库存储文件到本地镜像库,也可以使用
docker import 命令来导入一个容器快照到本地镜像库。
两者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将
保存完整记录,体积也会更大。
docker rm & docker rmi & docker prune 的差异?
docker rm : 删除一个或多个容器
docker rmi : 删除一个或多个镜像
docker prune : 用来删除不再使用的 docker 对象
Docker Volume(存储卷)
什么是存储卷**?**
存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上
的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,
容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。
在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。卷的本质是文件或者目
录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。
宿主机的 /data/web 目录与容器中的 /container/data/web 目录绑定关系,然后容器中的
进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿
主机的文件系统建立关联关系,使得 可以在宿主机和容器内共享数据库内容 ,让容器
直接访问宿主机中的内容,也可以宿主机向容器写入内容, 容器和宿主机的数据读写
是同步的
为什么需要存储卷**?**
- 数据丢失问题
容器按照业务类型,总体可以分为两类:
• 无状态的(数据不需要被持久化)
• 有状态的(数据需要被持久化)
显然,容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的
生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对
任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。
虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任
意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL 、 Kafka 等有状
态的业务。因此为了解决有状态业务的需求, Docker 提出了卷( Volume )的概念。 - 性能问题
UnionFS 对于修改删除等,一般效率非常低,如果对一于 I/O 要求比较高的应用,如
redis 在实现持化存储时,是在底层存储时的性能要求比较高。 - 宿主机和容器互访不方便
宿主机访问容器,或者容器访问要通过 docker cp 来完成,应用很难操作 - 容器和容器共享不方便
存储卷分类
目前 Docker 提供了三种方式将数据从宿主机挂载到容器中
• volume docker 管理卷 ,默认映射到宿主机的 /var/lib/docker/volumes 目录
下, 只需要在容器内指定容器的挂载点 是什么,而被绑定宿主机下的那个目录,是 由
容器引擎 daemon 自行创建一个空的目录 ,或者使用一个已经存在的目录,与存储卷
建立存储关系,这种方式极大解脱用户在使用卷时的耦合关系,缺陷是用户无法指定
那些使用目录,临时存储比较适合 ;
• bind mount 绑定数据卷 ,映射到宿主机指定路径下,在 宿主机上 的路径要人工的
指定一个特定的路径 , 在容器中也需要指定一个特定的路径 , 两个已知的路径建立关
联关系
• tmpfs mount 临时数据卷 ,映射到于宿主机内存中,一旦容器停止运行, tmpfs
mounts 会被移除,数据就会丢失,用于高性能的临时数据存储。
管理卷****Volume
创建卷
存储卷可以通过命令方式创建,也可以在创建容器的时候通过 -v and --mount 指定。
方式一:Volume命令操作
docker volume create
• 功能
○ 创建存储卷
○ -d, --driver : 指定驱动,默认是 local
○ --label : 指定元数据
创建匿名卷
创建命名卷
docker volume inspect
查看卷详细信息
• 关键参数
○ -f : 指定相应个格式,如 json
docker volume ls
• 功能
○ 列出卷
关键参数
○ --format : 指定相应个格式,如 json,table
○ --filter,-f: 过滤
○ -q: 仅显示名称
docker volume rm
• 功能
○ 删除卷,需要容器不使用。
• 关键参数
○ -f,--force: 强制删除
docker volume prune
• 功能
○ 删除不使用的本地卷
• 关键参数
○ --filter: 过滤
○ -f, --force : 不提示是否删除
方式二:-v或者**--mount****指定**
-v 和 -mount 都可以完成管理卷的创建
-v****参数
• 功能:
完成目录映射
docker run -v name:directory[:options]
• 参数
○ 第一个参数:卷名称
○ 第二个参数:卷映射到容器的目录
○ 第三个参数:选项,如 ro 表示 readonly
--mount****参数
• 功能:
完成目录映射
• 关键参数
○ type : 类型表示 bind , volume , or tmpfs
○ source , src :对于命名卷,这是卷的名称。对于匿名卷,省略此字段。
○ destination , dst,target :文件或目录挂载在容器中的路径
○ ro,readonly: 只读方式挂载
方式三:Dockerfile匿名卷
通过 Dockerfile 的 VOLUME 可以创建 docker 管理卷。这个我们后续在 Dockerfile
中详细讲解。
我们也可以通过 dockerfile 的 VOLUME 指令在镜像中创建 Data Volume ,这样只要
通过该镜像创建的容器都会存在挂载点,但值得注意的是通过 VOLUME 指令创建的挂
载点,无法指定主机上对应的目录,而是由 docker 随机生成的
绑定卷****bind mount
-v 和 -mount 都可以完成绑定卷的创建
创建卷
-v****参数创建卷
• 功能:
完成卷映射
参数
○ 第一个参数: 宿主机目录,这个和管理卷是不一样的
○ 第二个参数:卷映射到容器的目录
○ 第三个参数:选项,如 ro 表示 readonly
--mount****参数创建绑定卷
• 关键参数
○ type : 类型表示 bind , volume , or tmpfs
○ source , src : 宿主机目录,这个和管理卷是不一样的 。
○ destination , dst,target :文件或目录挂载在容器中的路径
○ ro,readonly: 只读方式挂载
临时卷****tmpfs
临时卷数据位于内存中,在容器和宿主机之外。
tmpfs****局限性
• 不同于卷和绑定挂载,不能在容器之间共享 tmpfs 挂载。
• 这个功能只有在 Linux 上运行 Docker 时才可用
创建卷
方式一:指定**--tmpfs****创建**
•
功能:
完成临时卷映射
方式二:--mount指定参数创建
• 功能
完成目录映射
•
关键参数
○ type : 类型表示 bind , volume , or tmpfs
○ destination , dst,target :挂载在容器中的路径
○ tmpfs-size : tmpfs 挂载的大小(以字节为单位)。默认无限制。
○ tmpfs-mode : tmpfs 的八进制文件模式。例如, 700 或 0770 。默认为 1777
或全局可写。
总结
常见问题
- 什么时候用 Volume ,什么时候用 bind 、 tmpfs ?
volume : volume 是 docker 的宿主机文件系统一部分,用于不需要规划具体目录的场
景
bind : bind mount 完全是依赖于主机的目录结构和操作系统,用于目录需要提前规划,
比如 mysql 的目录需要个空间大的,其他服务有不占用的时候,用 volume 就不太合
适了
tmpfs :用于敏感文件存储,文件不想存储的宿主机和容器的可写层之中
扩展思考:存储卷在实际研发中带来了哪些问题
- 跨主机使用
docker 存储卷是使用其所在的宿主机上的本地文件系统目录,也就是宿主机有一块磁
盘,这块磁盘并没有共享给其他的 docker 主机,容器在这宿主机上停止或删除,是可
以重新再创建的,但是不能调度到其他的主机上,这也是 docker 本身没有解决的问题,
所以 docker 存储卷默认就是 docker 所在主机的本地,但是自己搭建一个共享的 NFS
来存储 docker 存储的数据,也可以实现, 但是这个过程强依赖于运维人员的能力 。
所以未来应用的存储和数据往往分离,越来越多的分布式存储方案出现,如 s3 系列,
nfs 等。 - 启动参数未知
容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下
次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,
这就是容器编排工具的作用。
一般情况下,是使用命令来启动操作 docker, 但是可以通过文件来读,也就读文件来启
动,读所需要的存储卷等,但是它也只是操作一个容器,如果要几十上百个容器操作,
就需要 专业的容器编排工具
这种一般像开源的 k8s ,各个云厂商也有自己的企业版编排软件。 - 复杂场景仍然需要运维
对于有状态要持久的集群化组件,如 mysql 的主从。部署维护一个 Mysql 主从需要运
维知识、经验整合进去才能实现所谓的部署,扩展或缩容,出现问题后修复,必须要
了解集群的规模有多大,有多少个主节点,有多少个从节点,主节点上有多少个库,
这些都要一清二楚,才能修复故障,这些就 强依赖于运维经验
这种复杂的场景往往还是需要人力,很难有完美的工具出现。
Docker Network(网络)
Docker****为什么需要网络管理
容器的网络默认与宿主机及其他容器都是相互隔离, 但同时我们也要考虑下面的一些
问题, 比如
• 多个容器之间是如何通信的
• 容器和宿主机是如何通信的
• 容器和外界主机是如何通信的
• 容器中要运行一些网络应用( 如 nginx 、 web 应用、数据库等 ) ,如果要让外部也可
以访问这些容器内运行的网络应用应该如何实现
• 容器不想让它的网络与宿主机、与其他容器隔离应该如何实现
• 容器根本不需要网络的时候应该如何实现
• 容器需要更高的定制化网络(如定制特殊的集群网络、定制容器间的局域网)应
该如何实现
• 上述的这些问题都需要我们对容器的网络进行合理的管理才能解决,这就体现出了容
器网络管理的重要性。
Docker****网络架构简介
Docker 容器网络是为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作
系统的网络环境中独立出来,形成容器自有的网络设备、 IP 协议栈、端口套接字、 IP
路由表、防火墙等等与网络相关的模块。
Docker 为实现容器网络,主要采用的架构由三部分组成: CNM 、 Libnetwork 和驱动。
CNM
Docker 网络架构采用的设计规范是 CNM ( Container Network Model )。 CNM 中规定
了 Docker 网络的基础组成要素: Sandbox 、 Endpoint 、 Network 。
• Sandbox:提供了容器的虚拟网络栈,也即端口、套接字、 IP 路由表、防火墙、
DNS 配置等内容。主要用于隔离容器网络与宿主机网络,形成了完全独立的容器网络
环境。
• Network: Docker 内部的虚拟子网,使得网络内的参与者能够进行通讯。
• Endpoint:就是虚拟网络的接口,就像普通网络接口一样, Endpoint 的主要职责
是负责创建连接。 Endpoint 类似于常见的网络适配器,那也就意味着一个 Endpoint 只
能接入某一个网络, 当容器需要接入到多个网络,就需要多个 Endpoint 。
如上图所示,容器 B 有两个 Endpoint 并且分别接入 Networkd A 和 Network B 。那么
容器 A 和容器 B 之间是可以实现通信的,因为都接入了 NetworkA 。但是容器 A 和容
器 C 不可以通过容器 B 的两个 Endpoint 通信。
Libnetwork
Libnetwork 是 CNM 的一个标准实现。 Libnetwork 是开源库,采用 Go 语言编写(跨
平台的),也是 Docker 所使用的库, Docker 网络架构的核心代码都在这个库中。
Libnetwork 实现了 CNM 中定义的全部三个组件,此外它还实现了本地服务发现、基
于 Ingress 的容器负载均衡,以及网络控制层和管理层等功能。
驱动
驱动主要负责实现数据层相关内容,例如网络的连通性和隔离性是由驱动来处理的。
驱动通过实现特定网络类型的方式扩展了 Docker 网络栈,例如桥接网络和覆盖网络。
Docker 内置了若干驱动,通常被称作原生驱动或者本地驱动。例如 Bridge Driver 、
Host Driver 、 Overlay Driver 、 MacVLan Driver 、 IPVLan Driver 、 None Driver 等
等。每个驱动负责创建其上所有网络资源的创建和管理。
常见网络类型
1. bridge 网络
bridge 驱动会在 Docker 管理的主机上创建一个 Linux 网桥。默认情况下,网桥上
的容器可以相互通信。也可以通过 bridge 驱动程序配置,实现对外部容器的访问。
Docker 容器的默认网络驱动 . 当我们需要多个容器在同一个 Docker 主机上通信时,桥
接网络是最佳选择。
2. host 网络
对于独立容器,移除容器和 Docker 主机之间的网络隔离,并直接使用主机的网络。
当网络堆栈不应该与 Docker 主机隔离,但是希望容器的其他资源被隔离时,主机网络
是最佳选择。
3. container 网络
这个模式指定新创建的容器和引进存在的一个容器共享一个网络 ,而不是和宿主
机共享。新创建的容器不会创建自己的网卡,配置自己的 ip ,而是和一个指定的容器
共享 ip ,端口等,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离
的。两个容器的进程可以通过 lo 网卡设备通信
4. none 网络
Docker 容器拥有自己的 Network Namespace ,但是,并不为 Docker 容器进行任
何网络配置。也就是说,这个 Docker 容器没有网卡、 IP 、路由等信息。容器完全网络
隔离。
5. overlay 网络
借助 Docker 集群模块 Docker Swarm 搭建的跨 Docker Daemon 网络。将多个
Docker 守护进程连接在一起,使集群服务能够相互通信。当我们需要运行在不同
Docker 主机上的容器进行通信时,或者当多个应用程序使用集群服务协同工作时,覆
盖网络是最佳选择。
另外,在 Docker 安装时,会自动安装一块 Docker 网卡称为 docker0,它是一个网 桥设备,主要用于 Docker 各容器及宿主机的网络通信。
docker****网络管理命令
docker network create
• 功能
○ 创建自定义网络
•
关键参数
○ -d, --driver : 网络驱动
○ --gateway : 网关地址
○ --subnet : 表示网段的 CIDR 格式的子网
○ --ipv6 : 启用 ipv6
• 样例
Shell
docker network create --driver=bridge --subnet=192.168.0.0/16 br0
docker network inspect
• 功能
○ 查看网络详情.
• 关键参数
○ -f,--format: 指定格式
• 样例
Shell
docker network inspect mynetwork
docker network connect
• 功能
○ 于将容器连接到网络。可以按名称或 ID 连接容器。 一旦连接,容器可以与同
一网络中的其他容器通信。
• 关键参数
○ --ip : 指定 IP 地址
○ --ip6 : 指定 IPv6 地址
• 样例
Shell
将正在运行的容器连接到网络
$ docker network connect multi-host-network my_container1
启动时将容器连接到网络
还可以使用 docker run --network=<network-name> 选项启动容器并立即将其连
接到网络。
$ docker run -itd --network=multi-host-network busybox-container
指定容器的 IP 地址
可以指定要分配给容器网络接口的 IP 地址。
$ docker network connect --ip 10.10.36.122 multi-host-network container2
docker network disconnect
• 功能
○ 断开网络
• 语法
Shell
docker network disconnect [OPTIONS] NETWORK CONTAINER
• 关键参数
○ -f: 强制退出
• 样例
Shell
$ docker network disconnect multi-host-network my_container1
docker network prune
• 功能
○ 删除不使用的网络
• 语法
Shell
docker network prune [OPTIONS]
• 关键参数
○ -f, --force : 不提示
Shell
docker network prune
docker network rm
• 功能
○ 删除 1 个或者多个网络
• 语法
Shell
docker network rm NETWORK [NETWORK...]
• 关键参数
○ -f: 强制退出
docker network rm br0
docker network ls
• 功能
○ 列出网络
• 语法
Shell
docker network ls [OPTIONS]
• 别名
Shell
docker network list
• 关键参数
○ -f, --filter: 指定过滤条件
○ --format: 指定格式
○ --no-trunc: 不截断
○ -q, --quiet : 仅仅显示 id
• 样例
Shell
docker network list
网络详解
docker Bridge****网络
网络介绍
Docker Bridge 网络采用内置的 bridge 驱动, bridge 驱动底层采用的是 Linux 内核中
Linux bridge 技术。就网络而言, bridge 网络是在网络段之间转发流量的链路层设备,
而网桥可以是在主机内核中运行的硬件设备或软件设备;就 Docker 而言,桥接网络使
用软件网桥 docker0 ,它允许连接到同一网桥网络的容器进行通信,同时提供与未连
接到该网桥网络容器的隔离。
默认情况下,创建的容器在没有使用 --network 参数指定要加入的 docker 网络时,
默认都是加入 Docker 默认的单机桥接网络,即下面的 name 为 bridge 的网络。
默认的 bridge 网络会被映射到内核中为 docker0 的网桥上。
Docker 默认的 bridge 网络和 Linux 内核中的 docker0 网桥是一一对应的关系。
bridge 是 Docker 对网络的命名,而 docker0 是内核中网桥的名字。
docker Host****网络
网络介绍
Docker 容器运行默认都会分配独立的 Network Namespace 隔离子系统, 但是如果基
于 host 网络模式,容器将不会获得一个独立的 Network Namespace ,而是和宿主机
共用同一个 Network Namespace ,容器将不会虚拟出自己的网卡, IP 等,而是直接使
用宿主机的 IP 和端口。
连接到 host 网络的容器共享宿主机的网络栈,容器的网络配置与宿主机完全一样。我
们可以通过 --network=host 指定使用 host 网络。
使用场景
• 之前我们提到 bridge 网络在通信的时候需要进行端口转发以及 NAT 地址转换,
这势必会消耗掉一些资源以及性能。
• 那么直接使用 host 网络最大的好处就是性能好,如果容器对网络传输效率有较高
的要求,建议选择 host 网络。当然也会牺牲一些东西,比如要考虑端口冲突问题,其
他服务已经被占用的端口就不能再使用了
docker Container****网络
网络介绍
Docker Container 的 other container 网络模式是 Docker 中一种较为特别的网络的模
式。之所以称为 "other container 模式 " ,是因为这个模式下的 Docker Container ,会使
用其他容器的网络环境。之所以称为 " 特别 " ,是因为这个模式下容器的网络隔离性会处
于 bridge 桥接模式与 host 模式之间。 Docker Container 共享其他容器的网络环境,则
至少这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的
容器存在网络隔离。
使用场景
在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容
器,传输效率较高。但是两个容器之间存在依赖,如果依赖容器重启了,会导致另外
一个服务的网络不可用。
docker none****网络
网络介绍
none 网络就是指没有网络。挂在这个网络下的容器除了 lo ( 本地回环 ) ,没有其他任何
网卡。
使用场景
• 针对一些对安全性要求比较高并且不需要联网的应用, 可以使用 none 网络, 比
如生成随机密码, 避免生成密码被第三方获取。
• 一些第三方的应用可能需要 docker 帮忙创建一个没有网络的容器, 网络由第三
方自己来配置。
Docker Compose(容器编排)
什么是****Docker Compose
docker-compose 是 Docker 官方的开源项目,使用 python 编写,实现上调用了
Docker 服务的 API 进行容器管理及编排,其官方定义为定义和运行多个 Docker 容器
的应用。
docker-compose 中有两个非常重要的概念 :
•
服务 ( service ) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
•
项目 ( project ) :由一组关联的应用容器组成的一个完整业务单元,在 docker
compose.yml 文件中定义 , 整个 docker-compose.yml 定义一个项目。
Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周
期管理。 通过 compose 可以方便的管理多个服务。
为什么要****Docker Compose
• Docker 是一个轻量化的应用程序, Docker 官方推荐每个 Docker 容器中只运行一
个进程 。
• 如果一个应用需要涉及到 MySQL 、 nginx 等环境, 那么我们需要分别为应用、数
据库和 nginx 创建单独的 docker 容器,然后分别启动容器。
• 想象一下,当我们构建好 Docker 之后,每次启动应用,都至少需要 docker run
三次, 或者写一些脚本来实现, 这样会比较繁琐。
• 另外,这些 docker 容器都是分散独立的,也不方便镜像管理。那既然这些 docker
容器 都是为了同一个应用服务,我们就应该把它们放到一起,这就引出了 docker
compose 来解决这类型的问题
Docker Compose****的功能
- 使用步骤
Compose 使用的步骤:
• 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中
一起运行。
• 最后,执行 docker compose up 命令来启动并运行整个应用程序。 - 核心功能
Compose 具有管理应用程序整个生命周期的命令:
• 启动,停止和重建服务
• 查看正在运行的服务的状态
• 流式传输运行服务的日志输出
• 在服务上运行一次性命令
文件基本结构及常见指令
YAML
version: "3.8" # 定义版本, 表示当前使用的 docker-compose 语法的版本
services: # 服务,可以存在多个
servicename: # 服务名字,它也是内部 bridge 网络可以使用的 DNS name,
如果不是集群模式相当于 docker run 的时候指定的一个名称,
#集群(Swarm)模式是多个容器的逻辑抽象
image: # 必选,镜像的名字
command: # 可选,如果设置,则会覆盖默认镜像里的 CMD 命令
environment: # 可选,等价于 docker container run 里的 --env 选项
设置环境变量
volumes: # 可选,等价于 docker container run 里的 -v 选项 绑定数据
卷
networks: # 可选,等价于 docker container run 里的 --network 选项
指定网络
ports: # 可选,等价于 docker container run 里的 -p 选项指定端口映
射
expose: # 可选,指定容器暴露的端口
build: #构建目录
depends_on: #服务依赖配置
env_file: #环境变量文件
servicename2:
image:
command:
networks:
ports:
servicename3:
#...
volumes: # 可选,等价于 docker volume create
networks: # 可选,等价于 docker network create
常见字段格式语法
image
指定容器运行的镜像。以下格式都可以:
command
覆盖容器启动的默认命令。
entrypoint
覆盖容器默认的 entrypoint 。
也可以是以下格式:
Shell
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non
zts-20100525/xdebug.so - -d
- memory_limit=-1
- vendor/bin/phpunit
environment
添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以
确保 YML 解析器不会将其转换为 True 或 False 。
networks
指定容器运行的网络:
配置容器网络
如果要配置更多的信息,例如下图配置ipv4地址的信息
volumes
将主机的数据卷或者文件挂载到容器里。
ports
指定端口映射。以下格式都可以:
expose
暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定内部端口为参数:
build
指定为构建镜像上下文路径:
例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:
• context:上下文路径。
• dockerfile:指定构建镜像的 Dockerfile 文件名。
• args:添加构建参数,这是只能在构建过程中访问的环境变量。
• labels:设置构建镜像的标签。
depends_on
设置依赖关系。
• docker compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和
redis ,才会启动 web 。
• docker compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,
docker compose up web 还将创建并启动 db 和 redis 。
• docker compose stop :按依赖关系顺序停止服务。在以下示例中, web 在 db 和
redis 之前停止。
env_file
从文件添加环境变量。可以是单个值或列表的多个值。
Docker Compose****命令清单
官网参考地址:https://docs.docker.com/compose/reference/
命令格式
对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的
服务或者容器。如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服
务都会受到命令影响。
docker-compose 命令的基本的使用格式为
常见选项说明
• -f, --file 指定使用的 Compose 模板文件,默认为 docker-compose.yml ,可
以多次指定
• -p, --project-name 指定项目名称,默认将使用所在目录名称作为项目名
常见命令说明
up
该命令的作用十分强大,它会尝试自动完成包括构建镜像、(重新)创建服务、启动服
务并关联服务相关容器的一系列操作,可以直接通过该命令来启动一个项目。
• -d 在后台运行服务容器, 推荐在生产环境下使用该选项
• --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用
• --no-recreate 如果容器已经存在了,则不重新创建,不能与 --force
recreate 同时使用
down
停止所有容器,并删除容器和网络
• -v, --volumes 删除容器同时删除目录映射
run
该命令可以在指定服务容器上执行相关的命令
• -d 后台运行容器
• --name NAME 为容器指定一个名字
• --entrypoint CMD 覆盖默认的容器启动指令
• -e KEY=VAL 设置环境变量值,可多次使用选项来设置多个环境变量
• -u, --user="" 指定运行容器的用户名或者 uid
• --rm 运行命令后自动删除容器
• -p, --publish=[] 映射容器端口到本地主机
至此,学完这些就已经可以基本使用好docker了,本文到此结束,感谢观看。