马哥 Linux SRE + AIOps智能运维文档
第 29 章 / 42

企业级容器技术 Docker

关于本文档 · 贡献者 · 文档协议 · 致谢

关于本文档

文档名称:《企业级容器技术 Docker》

使用协议:《知识共享公共许可协议(CCPL)》

贡献者

贡献者名称 贡献
度
文档变更记录 个人主页
马哥(马永亮) 主编 http://github.com/iKubernet
es/
杰哥(张士杰) 作者 70页 http://blogs.studylinux.net/
王晓春 作者 399页,版本迭代升级,修订和内容丰富 http://www.wangxiaochun.c
om

文档协议

署名要求 :使用本系列文档,您必须保留本页中的文档来源信息,具体请参考《知识共享 (Creative Commons) 署名4.0公共许可协议国际版》。

非商业化使用 :遵循《知识共享公共许可协议(CCPL)》,并且您不能将本文档用于马哥教育相关业务之外的其他任何商业用途。

您的权利 :遵循本协议后,在马哥教育相关业务之外的领域,您将有以下使用权限:

共享 — 允许以非商业性质复制本作品。

改编 — 在原基础上修改、转换或以本作品为基础进行重新编辑并用于个人非商业使用。

致谢

本文档中,部分素材参考了相关项目的文档,以及通过搜索引擎获得的内容,这里先一并向相关的贡献者表示感谢。

← 上一章:企业级公有云阿里云 | 返回总目录 | 下一章:企业级反向代理 Haproxy →


内容概述

  • Docker 介绍和安装

  • Docker 基本操作

  • 容器镜像制作和管理

  • 数据卷管理

  • 网络管理

  • 镜像仓库管理

  • 容器编排管理工具 Docker Compose

容器资源限制

1 Docker 介绍和基础操作

Container 即容器,平时生活中指的是可以装下其它物品的工具, 以方便人类归纳放置物品 、存储和异地运输 ,比如人类使用的衣柜 、行李箱、 背包等可以成为容器,Container 除了容器以外,另一个意思是集装箱, 很多码头工人将很多装有不同物品但却整齐划一的箱子装载到停靠在岸边大船,然后方便的运来运去。

为什么这些集装箱可以很方便的运来运去呢?因为它们大小一致标准化尺寸的箱子,并且可以安全的隔离开,所以当我们使用 Container 来形容容器的时候,就是我们想要让容器达到一个可以打包,符合标准的状态。

集装箱标准尺寸重量

类型 大小 内长m 内宽 内高 门高 门宽 容积 载 皮
m m m m m³ 重T 重T
普通箱 20GP 5.898 2.352 2.385 2.280 2.343 28.00 18 2.3
普通箱 40GP 12.032 2.352 2.385 2.280 2.343 57.00 28 3.4
高箱 40HC 12.032 2.352 2.690 2.585 2.343 67.00 28 4.0

但今天我们所说的容器是一种 IT 技术。容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用装起来。这样,应用与应用之间就有了边界而不会相互干扰;同时装在沙盒里面的应用,也可以很方便的被搬来搬去,这也是 PaaS 想要的最理想的状态( 可移植性,标准化,隔离性 )。

容器是软件工业上的集装箱的技术,集装箱的标准化,减少了包装成本,大大提高货物运输和装卸效率,是传统运输行业的重大变革。早期的软件项目中软件更新,发布低效,开发测试发布周期很长,很难敏捷。有了容器技术,就可以利用其标准化的特点,大幅提高生产效率。

容器技术是虚拟化、云计算、大数据之后的一门新兴的并且是炙手可热的新技术, 容器技术提高了硬件资源利用率、 方便了企业的业务快速横向扩容(可以达到秒级快速扩容)、 实现了业务宕机自愈功能 (配合K8S可以实现,但OpenStack无此功能),因此未来数年会是一个容器愈发流行的时代 ,这是一个对于 IT 行业来说非常有影响和价值的技术,而对于IT行业的从业者来说, 熟练掌握容器技术无疑是一个很有前景的行业工作机会。

1.1 Docker 介绍

1.1.1 容器历史

虽然 docker 把容器技术推向了巅峰,但容器技术却不是从 docker 诞生的。实际上,容器技术连新技术都算不上,因为它的诞生和使用确实有些年头了。下面的一串名称可能有的你都没有听说过,但它们的确都是容器技术的应用:

1、Chroot Jail

就是我们常见的 chroot 命令的用法。它在 1979 年的时候就出现了,被认为是最早的容器化技术之一。 它可以把一个进程的文件系统隔离起来。

2、The FreeBSD Jail

Freebsd Jail (监狱)实现了操作系统级别的虚拟化,它是操作系统级别虚拟化技术的先驱之一。2000年, 伴随FreeBSD4.0版的发布

3、Linux VServer

使用添加到 Linux 内核的系统级别的虚拟化功能实现的专用虚拟服务器。允许创建许多独立的虚拟专用服务器(VPS),这些虚拟专用服务器在单个物理服务器上全速同时运行,从而有效地共享硬件资源。 VPS提供与传统Linux服务器几乎相同的操作环境。可以在这样的VPS上启动所有服务(例如ssh,邮件, Web和数据库服务器),而无需(或者在特殊情况下只需进行很少的修改),就像在任何真实服务器上一样。

每个VPS都有自己的用户帐户数据库和root密码,并且与其他虚拟服务器隔离,但它们共享相同的硬件资源

2003年11月1日 VServer 1.0 发布

官网:http://linux-vserver.org/

4、Solaris Containers

它也是操作系统级别的虚拟化技术,专为 X86 和 SPARC 系统设计。Solaris 容器是系统资源控制和通过 "区域" 提供边界隔离的组合。

5、OpenVZ

OpenVZ 是一种 Linux 中操作系统级别的虚拟化技术。 它允许创建多个安全隔离的 Linux 容器,即 VPS。

6、Process Containers

Process 容器由 Google 的工程师开发,一般被称为 cgroups。

7、LXC

LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求

Linux Container提供了在单一可控主机节点上支持多个相互隔离的server container同时执行的机制。 Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机, 因为lxc是一种操作系统层次上的资源的虚拟化。

8、Warden

在最初阶段,Warden 使用 LXC 作为容器运行时。 如今已被 CloudFoundy 取代。

9、LMCTFY

LMCTY 是 Let me contain that for you 的缩写。它是 Google 的容器技术栈的开源版本。 Google 的工程师一直在与 docker 的 libertainer 团队合作,并将 libertainer 的核心概念进行抽象并移植到此项目中。该项目的进展不明,估计会被 libcontainer 取代。

10、Docker

Docker 是一个可以将应用程序及其依赖打包到几乎可以在任何服务器上运行的容器的工具。

11、RKT

RKT 是 Rocket 的缩写,它是一个专注于安全和开放标准的应用程序容器引擎。

综上所述正如我们所看到的,docker 并不是第一个容器化技术,但它的确是最知名的一个。

1.1.2 Docker 是什么

Docker (码头工人)是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司(后由于 Docker 开源后大受欢迎就将公司改名为 Docker Inc ,总部位于美国加州的旧金山)内部的一个开源的 PAAS 服务 (Platform as a ServiceService )的业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。

Docker 是基于 Linux 内核实现,Docker 最早采用 LXC 技术 ,LXC 是 Linux 原生支持的容器技术 ,可以提供轻量级的虚拟化 ,可以说 docker 就是基于 LXC 发展起来的,提供 LXC 的高级封装,标准的配置方法,在LXC的基础之上,docker提供了一系列更强大的功能。而虚拟化技术 KVM(KernelKernelbased Virtual Machine Machine) 基于模块实现, 后来Docker 改为自己研发并开源的 runc 技术运行容器,彻底抛弃了LXC。

Docker 相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端/服务端架构,使用远程API来管理和创建容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是 build(构建)、ship(运输)、 run(运行),Docker遵从apache 2.0协议,并通过(namespace及cgroup 等)来提供容器的资源隔离与安全保障等,所以Docke容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机6-8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机.类似于VM但是在原理和应用上和VM的差别还是很大的,并且docker的专业叫法是应用容器(Application Container)。

Docker 的主要目标

Build, Ship and Run Any App, Anywhere,即通过对应用组件的封装(Packaging)、分发 (Distribution)、部署(Deployment)、运行(Runtime)等生命周期的管理,达到应用组件级别的 “一次封装,到处运行”。这里的应用组件,既可以是一个Web应用,也可以是一套数据库服务,甚至是一个操作系统。将应用运行在Docker 容器上,可以实现跨平台,跨服务器,只需一次配置准备好相关的应用环境,即可实现到处运行,保证研发和生产环境的一致性,解决了应用和运行环境的兼容性问题, 从而极大提升了部署效率,减少故障的可能性

使用Docker 容器化封装应用程序的意义:

统一基础设施环境-docker环境

硬件的组成配置

操作系统的版本运行时环境的异构

统一程序打包(装箱)方式-docker镜像

java 程序

go 程序

python 程序

nodejs 程序

统一程序部署(运行)方式-docker容器

java-jar...→ docker run...

go 二进制程序 → docker run... python manage.py runserver... → docker run... npm run dev ... → docker run...

1.1.3 Docker 和虚拟机,物理主机

容器和虚拟机技术比较

  • 传统虚拟机是虚拟出一个主机硬件,并且运行一个完整的操作系统 ,然后在这个系统上安装和运行软件

  • 容器内的应用直接运行在宿主机的内核之上,容器并没有自己的内核,也不需要虚拟硬件,相当轻量化每个容器间是互相隔离,每个容器内都有一个属于自己的独立文件系统,独立的进程空间,网络空间,用户空间等,所以在同一个宿主机上的多个容器之间彼此不会相互影响

容器和虚拟机表现比较

  • 资源利用率更高: 开销更小,不需要启动单独的虚拟机OS内核占用硬件资源,可以将服务器性能压榨至极致.虚拟机一般会有5-20%的损耗,容器运行基本无损耗,所以生产中一台物理机只能运行数十个虚拟机,但是一般可以运行数百个容器

  • 启动速度更快: 可以在数秒内完成启动

  • 占用空间更小: 容器一般占用的磁盘空间以MB为单位,而虚拟机以GB

  • 集成性更好: 和 CI/CD(持续集成/持续部署)相关技术结合性更好,实现打包镜像发布测试可以一键运行,做到自动化并快速的部署管理,实现高效的开发生命周期

使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能损耗,我们创建虚拟机的目的是为了运行应用程序,比如Nginx、PHP、Tomcat等web程序,使用虚拟机无疑带来了一些不必要的资源开销,但是容器技术则基于减少中间运行环节带来较大的性能提升。

根据实验,一个运行着CentOS的KVM虚拟机启动后,在不做优化的情况下,虚拟机自己就需要占用 100~200 MB内存。此外,用户应用运行在虚拟机里面,它对宿主机操作系统的调用就不可避免地要经过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗非常大。

比如: 一台96G内存的物理服务器,为了运行java程序的虚拟机一般需要分配8G内存/4核的资源,只能运行13台左右虚拟机,但是改为在docker容器上运行Java程序,每个容器只需要分配4G内存即可,同样的物理服务器就可以运行25个左右容器,运行数量相当于提高一倍,可以大幅节省IT支出,通常情况下至少可节约一半以上的物理设备

1.1.4 Docker 的组成

docker 官网: http://www.docker.com

帮助文档链接: https://docs.docker.com/

docker 镜像: https://hub.docker.com/

docker 中文网站: http://www.docker.org.cn/

  • Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机, node节点

  • Docker 服务端(Server): Docker守护进程,运行docker容器

  • Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API

  • Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合

  • Docker 仓库(Registry): 保存镜像的仓库,官方仓库: https://hub.docker.com/,可以搭建私有仓库

  • harbor

  • Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中的程序启动后生成的进程

1.1.5 Namespace

一个宿主机运行了N个容器,多个容器共用一个 OS,必然带来的以下问题:

  • 怎么样保证每个容器都有不同的文件系统并且能互不影响?

  • 一个docker主进程内的各个容器都是其子进程,那么如果实现同一个主进程下不同类型的子进程? 各个容器子进程间能相互通信(内存数据)吗?

  • 每个容器怎么解决IP及端口分配的问题?

  • 多个容器的主机名能一样吗?

  • 每个容器都要不要有root用户?怎么解决账户重名问题?

namespace是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间被部署在内核,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统空间、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:

隔离类型 功能 系统调用参数 内核
版本
MNT Namespace(mount) 提供磁盘挂载点和文件系统的隔离能力 CLONE_NEWNS 2.4.19
IPC Namespace(Inter-
Process Communication)
提供进程间通信的隔离能力,
包括信号量,消息队列和共享内存
CLONE_NEWIPC 2.6.19
UTS Namespace(UNIX
Timesharing System)
提供内核,主机名和域名隔离能力 CLONE_NEWUTS 2.6.19
PID Namespace(Process
Identification)
提供进程隔离能力 CLONE_NEWPID 2.6.24
Net Namespace(network) 提供网络隔离能力,包括网络设备,网络栈,端口等 CLONE_NEWNET 2.6.29
User Namespace(user) 提供用户隔离能力,包括用户和组 CLONE_NEWUSER 3.8

1.1.6 Control groups

Linux Cgroups的全称是Linux Control Groups,是Linux内核的一个功能.最早是由Google的工程师(主要是Paul Menage和Rohit Seth)在2006年发起,最早的名称为 进程容器 (process containers)。在 2007年时,因为在Linux内核中,容器(container)这个名词有许多不同的意义,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。自那以后,又添加了很多功能。

如果不对一个容器做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug 程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如CPU、内存等

Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操作)。

Cgroups在内核层默认已经开启,从CentOS 和 Ubuntu 不同版本对比,显然内核较新的支持的功能更多。

Centos 8.1 cgroups:

[root@centos8 ~]#cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
[root@centos8 ~]#grep CGROUP /boot/config-4.18.0-147.el8.x86_64
CONFIG_CGROUPS=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_SOCK_CGROUP_DATA=y
# CONFIG_BLK_CGROUP_IOLATENCY is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y
[root@centos8 ~]#

Centos 7.6 cgroups:

[root@centos7 ~]#cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@centos7 ~]#grep CGROUP /boot/config-3.10.0-957.el7.x86_64
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_SCHED=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_NETPRIO_CGROUP=y

ubuntu cgroups:

[root@ubuntu1804 ~]#grep CGROUP  /boot/config-4.15.0-29-generic
CONFIG_CGROUPS=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_BPF=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_SOCK_CGROUP_DATA=y
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y

cgroups 中内存模块:

[root@ubuntu1804 ~]#grep MEMCG  /boot/config-4.15.0-29-generic
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
# CONFIG_MEMCG_SWAP_ENABLED is not set
CONFIG_SLUB_MEMCG_SYSFS_ON=y

1.1.7 容器管理工具

有了以上的chroot、namespace、cgroups就具备了基础的容器运行环境,但是还需要有相应的容器创建与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需要解决,于是容器管理技术出现了。目前主要是使用docker,早期使用 LXC

1.1.7.1 LXC

LXC: Linux Container。可以提供轻量级的虚拟化功能,以便隔离进程和资源,包括一系列容器的管理工具软件,如,lxc-create,lxc-start,lxc-attach等,但这技术功能不完善,目前较少使用

官方网站: https://linuxcontainers.org/

案例: Ubuntu安装和使用 LXC

[root@ubuntu1804 ~]#apt install lxc lxd
Reading package lists... Done
Building dependency tree
Reading state information... Done
lxd is already the newest version (3.0.3-0ubuntu1~18.04.1).
lxc is already the newest version (3.0.3-0ubuntu1~18.04.1).
......
[root@ubuntu1804 ~]#lxc-checkconfig   #检查内核对lcx的支持状况,必须全部为lcx
Kernel configuration not found at /proc/config.gz; searching...
Kernel configuration found at /boot/config-4.15.0-29-generic
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
......
[root@ubuntu1804 ~]#lxc-create -t download --name alpine1 --  --dist alpine  --
release 3.9 --arch amd64
Setting up the GPG keyring
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs
You just created an Alpinelinux 3.9 x86_64 (20200121_13:00) container.
[root@ubuntu1804 ~]#lxc-start alpine1    #启动lxc容器
[root@ubuntu1804 ~]#lxc-attach alpine1   #进入lxc容器
~ # ifconfig
eth0      Link encap:Ethernet  HWaddr 00:16:3E:DF:9E:45
          inet addr:10.0.1.51  Bcast:10.0.1.255  Mask:255.255.255.0
          inet6 addr: fe80::216:3eff:fedf:9e45/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:23 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2484 (2.4 KiB)  TX bytes:1726 (1.6 KiB)
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
~ # uname -r
4.15.0-29-generic
~ # uname -a
Linux alpine12 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018
x86_64 Linux
~ # cat /etc/issue
Welcome to Alpine Linux 9
Kernel \r on an \m (\l)
~ # exit
[root@ubuntu1804 ~]#

命令选项说明:

-t模板: -t选项后面跟的是模板,模式可以认为是一个原型,用来说明需要一个什么样的容器(比如容器里
面需不需要有vim, apache等软件).模板实际上就是一个脚本文件(位于/usr/share/lxc/templates目
录),我们这里指定download模板(lxc-create会调用lxc-download脚本,该脚本位于刚说的模板目录
中)是说明我们目前没有自己模板,需要下载官方的模板
--name容器名称:   为创建的容器命名
-- : --用来说明后面的参数是传递给download脚本的,告诉脚本需要下载什么样的模板
--dist操作系统名称:  指定操作系统
--release操作系统: 指定操作系统,可以是各种Linux的变种
--arch架构:  指定架构,是x86还是arm,是32位还是64位

lxc启动容器依赖于模板,清华模板源: https://mirrors.tuna.tsinghua.edu.cn/help/lxc-images/,但是做模板相对较难,需要手动一步步创构建文件系统、准备基础目录及可执行程序等,而且在大规模使用容器的场景很难横向扩展,另外后期代码升级也需要重新从头构建模板,基于以上种种原因便有了 docker

1.1.7.2 docker

Docker 相当于增强版的LXC,功能更为强大和易用,也是当前最主流的容器前端管理工具

Docker 先启动一个容器也需要一个外部模板,也称为镜像,docke的镜像可以保存在一个公共的地方共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。

Docker的镜像是分层的,镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到宿主机上对应容器的目录,但是容器内的数据在删除容器后也会被随之删除。

1.1.7.3 pouch

项目网点: https://github.com/alibaba/pouch

Pouch (小袋子)起源于 2011 年,并于2017年11月19日上午,在中国开源年会现场,阿里巴巴正式开源了基于 Apache 2.0 协议的容器技术 Pouch。Pouch 是一款轻量级的容器技术,拥有快速高效、可移植性高、资源占用少等特性,主要帮助阿里更快的做到内部业务的交付,同时提高超大规模下数据中心的物理资源利用率

目前的容器方案大多基于 Linux 内核提供的 cgroup 和 namespace 来实现隔离,然后这样轻量级方案存在弊端:

容器间,容器与宿主间,共享同一个内核内核实现的隔离资源,维度不足

面对如此的内核现状,阿里巴巴采取了三个方面的工作,来解决容器的安全问题:

用户态增强容器的隔离维度,比如网络带宽、磁盘使用量等给内核提交 patch,修复容器的资源可见性问题,cgroup 方面的 bug

实现基于 Hypervisor 的容器,通过创建新内核来实现容器隔离

1.1.7.4 Podman

虽然目前 Docker 是管理 Linux 容器最好的工具,注意没有之一,但是podman的横空出现即将改变这一点

什么是Podman?

Podman即Pod Manager tool,从名称上可以看出和kubernets的pod的密切联系,不过就其功能来说,简而言之: alias docker = podman ,是CentOS 8 新集成的功能,或许不久的未来会代替docker

Podman是一个为 Kubernetes 而生的开源的容器管理工具,原来是 CRI-O(即容器运行时接口CRI 和开放容器计划OCI) 项目的一部分,后来被分离成一个单独的项目叫 libpod。其可在大多数Linux平台上使用,它是一种无守护程序的容器引擎,用于在Linux系统上开发,管理和运行任何符合Open Container Initiative(OCI)标准的容器和容器镜像。

Podman 提供了一个与Docker兼容的命令行前端,Podman 里面87%的指令都和Docker CLI 相同,因此可以简单地为Docker CLI别名,即“ alias docker = podman”,事实上,podman使用的一些库也是 docker的一部分。

CRI-O is an implementation of the Kubernetes CRI (Container Runtime Interface) to
enable using OCI (Open Container Initiative) compatible runtimes

官网地址: https://podman.io/

项目地址: https://github.com/containers/libpod

Podman 和docker不同之处

  • docker 需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman 不需要

启动容器的方式不同:

docker cli 命令通过API跟 Docker Engine( 引擎 ) 交互告诉它我想创建一个container,然后 docker Engine 才会调用 OCI container runtime(runc) 来启动一个container。这代表 container的process(进程)不会是 Docker CLI 的 child process( 子进程 ) ,而是 Docker Engine 的 child process 。

Podman 是直接给 OCI containner runtime(runc) 进行交互来创建container的,所以 container process 直接是 podman 的 child process 。

  • 因为docke有docker daemon,所以docker启动的容器支持 -- restart 策略,但是podman不支持 docker需要使用root用户来创建容器。 这可能会产生安全风险,尤其是当用户知道docker run命令的--privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行

  • docker在Linux上作为守护进程运行扼杀了容器社区的创新。 如果要更改容器的工作方式,则需要更改docker守护程序并将这些更改推送到上游。 没有守护进程,容器基础结构更加模块化,更容易进行更改。 podman的无守护进程架构更加灵活和安全。

1.1.8 Docker 的优势

  • 快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上

  • 高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率

节省开支: 提高服务器利用率,降低IT支出

  • 简化配置: 将运行环境打包保存至容器,使用时直接启动即可

  • 环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题

  • 快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台

  • 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响

1.1.9 Docker 的缺点

  • 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底

  • 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐

  • 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费

1.1.10 容器的相关技术

1.1.10.1 容器规范

OCI 官网:https://opencontainers.org/

容器技术除了的docker之外,还有coreOS的rkt,还有阿里的Pouch,为了保证容器生态的标准性和健康可持续发展,包括Linux 基金会、Docker、微软、红帽谷歌和IBM等公司在2015年6月共同成立了一个叫Open Container Initiative(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI一共发布了两个规范, 分别是runtime spec 和 image format spec ,有了这两个规范,不同的容器公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。

1.1.10.2 容器 runtime

runtime是真正运行容器的地方,因此为了运行不同的容器runtime需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境

runtime 类型:

  • Lxc: linux上早期的runtime,在 2013 年 Docker 刚发布的时候,就是采用lxc作为runtime, Docker 把 LXC 复杂的容器创建与使用方式简化为 Docker 自己的一套命令体系。随着Docker的发展,原有的LXC不能满足Docker的需求,比如跨平台功能

  • Libcontainer: 随着 Docker 的不断发展,重新定义容器的实现标准,将底层实现都抽象化到 Libcontainer 的接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用

namespace、cgroups 技术抑或是使用 systemd 等其他方案,只要实现了 Libcontainer 定义的一组接口,Docker 都可以运行。这也为 Docker 实现全面的跨平台带来了可能。 runc : 早期libcontainer是Docker公司控制的一个开源项目,OCI的成立后,Docker把libcontainer 项目移交给了OCI组织,runC就是在libcontainer的基础上进化而来,目前Docker默认的runtime, runc遵守OCI规范

rkt: 是CoreOS开发的容器runtime,也符合OCI规范,所以使用rktruntime也可以运行Docker容器

对于容器运行时主要有两个级别:Low Level(使用接近内核层) 和 High Level(使用接近用户层)目前,市面上常用的容器引擎有很多,主要有下图的那几种。

dockershim, containerd 和cri-o都是遵循CRI的容器运行时,我们称他们为高层级运行时(High-level Runtime)

其他的容器运营厂商最底层的runc仍然是Docker在维护的。

Google,CoreOS,RedHat都推出自已的运行时:lmctfy,rkt,cri-o,但到目前Docker仍然是最主流的容器引擎技术。

Docker 的运行机制

范例: 查看docker的 runtime

[root@ubuntu1804 ~]#docker info
Client:
 Debug Mode: false
Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 1
 Server Version: 19.03.5
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog
 Swarm: inactive
 Runtimes: runc         #Runtimes
 Default Runtime: runc  #runtime
 Init Binary: docker-init
 containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339
 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
 init version: fec3683
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 4.15.0-29-generic
 Operating System: Ubuntu 18.04.1 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 1
 Total Memory: 962MiB
 Name: ubuntu1804.wang.org
 ID: G2JQ:M4DG:CW74:EETR:GU5U:OROC:ZN2F:RKSA:YQY2:XJYX:OHG7:SSVE
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
127.0.0.0/8
 Live Restore Enabled: false
WARNING: No swap limit support
1.1.10.3 容器管理工具

管理工具连接runtime与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给 runtime执行。

lxc 是lxd 的管理工具

Runc的管理工具是 docker engine ,docker engine包含后台deamon和cli两部分,大家经常提到的Docker就是指的docker engine

Rkt的管理工具是rkt cli

范例: 查看docker engine

[root@ubuntu1804 ~]#docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 1307:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 1307:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
[root@ubuntu1804 ~]#
1.1.10.4 镜像仓库 Registry

统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库

  • Docker hub: docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用阿里云,网易等第三方镜像的公共仓库

  • Image registry: docker 官方提供的私有仓库部署工具,无web管理界面,目前使用较少 Harbor: vmware 提供的自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用

范例: 镜像地址格式

docker.io/library/alpine
harbor.wang.org/project/centos:7.2.1511
registry.cn-hangzhou.aliyuncs.com/wangxiaochun/wang:v1
172.18.200.101/project/centos: latest
172.18.200.101/project/java-7.0.59:v1
1.1.10.5 容器编排工具

当多个容器在多个主机运行的时候,单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎

容器编排通常包括容器管理、调度、集群定义和服务发现等功能

  • Docker compose : docker 官方实现单机的容器的编排工具 Docker swarm: docker 官方开发的容器编排引擎,支持overlay network

Mesos+Marathon: Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的集群组员调度平台,mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能

  • Kubernetes: google领导开发的容器编排引擎,内部项目为Borg,且其同时支持 docker 和 CoreOS,当前已成为容器编排工具事实上的标准

1.2 Docker安装及基础命令介绍

1.2.1 Docker 安装准备

官方网址: https://www.docker.com/

OS系统版本选择:

Docker 目前已经支持多种操作系统的安装运行,比如Ubuntu、CentOS、Redhat、Debian、Fedora, 甚至是还支持了Mac和Windows,在linux系统上需要内核版本在3.10或以上

Docker版本选择:

Docker版本号之前一直是0.X版本或1.X版本,从2013年3月13日发布第一个版本0.1.1-1开始一直到2017 年02月08日发布1.13.1版

从2017年3月1号开始改为每个季度发布一次稳定版,其版本号规则也统一变更为YY.MM,第一个版本为17.03.0, 例如17.09表示是2017年9月份发布的

Docker之前没有区分版本,但是2017年推出(将docker更名为)新的项目Moby,github地址: https://git hub.com/moby/moby,Moby项目属于Docker项目的全新上游,Docker将是一个隶属于的Moby的子产品,而且之后的版本之后开始区分为 CE(Docker Community Edition,社区版本)和 EE(Docker Enterprise Edition,企业收费版),CE社区版本和EE企业版本都是每个季度发布一个新版本,但是EE 版本提供后期安全维护1年,而CE版本是4个月,以下为官方原文:

https://blog.docker.com/2017/03/docker-enterprise-edition/

Docker CE and EE are released quarterly, and CE also has a monthly “Edge” option.
Each Docker EE release is supported and maintained for one year and receives
security and critical bugfixes during that period. We are also improving Docker
CE maintainability by maintaining each quarterly CE release for 4 months. That
gets Docker CE users a new 1-month window to update from one version to the
next.

如果要布署到 kubernetes上,需要查看相关kubernetes对docker版本要求的说明,比如:

https://github.com/kubernetes/kubernetes/blob/v1.17.2/CHANGELOG-1.17.md

1.2.2 Docker 安装和删除方法

官方文档 : https://docs.docker.com/engine/install/

阿里云文档: https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11gu

HCWE

1.2.2.1 Ubuntu 安装和删除 Docker

官方文档: https://docs.docker.com/install/linux/docker-ce/ubuntu/

Ubuntu 14.04/16.04/18.04/20.04 安装docker

# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-
properties-common
# step 2: 安装GPG证书
curl-fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key
add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-
ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
apt-cache madison docker-ce
 docker-ce | 5:19.03.5~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.4~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.3~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.2~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.1~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:19.03.0~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.9~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.8~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.7~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.6~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.5~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.4~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.3~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.2~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.1~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 5:18.09.0~3-0~ubuntu-bionic | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.3~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.2~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.1~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.06.0~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
 docker-ce | 18.03.1~ce~3-0~ubuntu | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu bionic/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的5:17.03.1~ce-0~ubuntu-xenial)
sudo apt-get -y install docker-ce=[VERSION] docker-ce-cli=[VERSION]
#示例:指定版本安装
apt-get -y install docker-ce=5:18.09.9~3-0~ubuntu-bionic  docker-ce-
cli=5:18.09.9~3-0~ubuntu-bionic

删除docker

[root@ubuntu ~]#apt purge docker-ce
[root@ubuntu ~]#rm -rf /var/lib/docker

范例: 内置仓库安装docker

[root@ubuntu2004 ~]#apt -y install docker.io
[root@ubuntu2004 ~]#docker version
Client:
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.16.2
 Git commit:        20.10.12-0ubuntu2~20.04.1
 Built:             Wed Apr  602:14:38 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Server:
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.2
  Git commit:       20.10.12-0ubuntu2~20.04.1
  Built:            Thu Feb 1015:03:35 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.5.9-0ubuntu1~20.04.4
  GitCommit:
 runc:
  Version:          1.1.0-0ubuntu1~20.04.1
  GitCommit:
 docker-init:
  Version:          0.19.0
  GitCommit:
[root@ubuntu2004 ~]#docker info
Client:
 Context:    default
 Debug Mode: false
Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 20.10.12
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog
 Swarm: inactive
 Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
 Default Runtime: runc
 Init Binary: docker-init
 containerd version:
 runc version:
 init version:
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 5.4.0-89-generic
 Operating System: Ubuntu 20.04.3 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.913GiB
 Name: ubuntu2004.wang.org
 ID: UF2A:GX7G:OIWE:W35O:EFSB:5WBH:AYCZ:N37P:YCIF:4AXD:D3IL:NCI4
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
127.0.0.0/8
 Live Restore Enabled: false
WARNING: No swap limit support

范例: 安装指定版本

# step 1: 安装必要的一些系统工具
[root@ubuntu2004 ~]#sudo apt-get update
[root@ubuntu2004 ~]#sudo apt-get -y install apt-transport-https ca-certificates
curl software-properties-common
# step 2: 安装GPG证书
[root@ubuntu2004 ~]#curl -fsSL https://mirrors.aliyun.com/docker-
ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
[root@ubuntu2004 ~]#sudo add-apt-repository "deb [arch=amd64]
https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
[root@ubuntu2004 ~]#sudo apt-get -y update
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
[root@ubuntu2004 ~]#apt-cache madison docker-ce
#   docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu xenial/stable amd64 Packages
#   docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]
[root@ubuntu2004 ~]#apt-cache madison docker-ce
 docker-ce | 5:20.10.17~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.16~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.15~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.14~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.13~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.12~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.11~3-0~ubuntu-focal | https://mirrors.aliyun.com/docker-
ce/linux/ubuntu focal/stable amd64 Packages
[root@ubuntu2004 ~]#apt install docker-ce=5:20.10.10~3-0~ubuntu-focal docker-ce-
cli=5:20.10.10~3-0~ubuntu-focal
[root@ubuntu2004 ~]#docker version
Client: Docker Engine - Community
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 2507:42:59 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Server: Docker Engine - Community
 Engine:
  Version:          20.10.10
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       e2f740d
  Built:            Mon Oct 2507:41:08 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.6
  GitCommit:        10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
 runc:
  Version:          1.1.2
  GitCommit:        v1.1.2-0-ga916309
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
1.2.2.2 CentOS 安装和删除Docker

官方文档: https://docs.docker.com/install/linux/docker-ce/centos/

CentOS 6 因内核太旧,即使支持安装docker,但会有各种问题,不建议安装

CentOS 7 的 extras 源虽然可以安装docker,但包比较旧,建议从官方源或镜像源站点下载安装docker

CentOS 8 有新技术 podman 代替 docker

因此建议在CentOS 7 上安装 docker

#extras 源中包名为docker
[root@centos7 ~]#yum list docker
Loaded plugins: fastestmirror
Repository base is listed more than once in the configuration
Repository extras is listed more than once in the configuration
Loading mirror speeds from cached hostfile
 * base: mirrors.tuna.tsinghua.edu.cn
 * extras: mirrors.tuna.tsinghua.edu.cn
 * updates: mirrors.tuna.tsinghua.edu.cn
Available Packages
docker.x86_64      2:1.13.1-103.git7f2769b.el7.centos
extras

下载rpm包安装:

官方rpm包下载地址:

https://download.docker.com/linux/centos/7/x86_64/stable/Packages/

阿里镜像下载地址:

https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/

通过yum源安装:

由于官网的yum源太慢,下面使用阿里云的Yum源进行安装

rm-rf /etc/yum.repos.d/*
#CentOS 7 安装docker依赖三个yum源:Base,Extras,docker-ce
wget-O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-
7.repo
wget-O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
wget-O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-
ce/linux/centos/docker-ce.repo
yum clean all
yum -y install docker-ce
systemctl enable --now docker

删除 docker

[root@centos7 ~]#yum remove docker-ce
#删除docker资源存放的相关文件
[root@centos7 ~]#rm -rf /var/lib/docker

范例: 安装指定版本

[root@rocky8 ~]#cat /etc/yum.repos.d/docker.repo
[docker-ce]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
gpgcheck=0
[root@rocky8 ~]#yum list docker-ce --showduplicates
Last metadata expiration check: 0:07:05 ago on Fri 01 Jul 2022 11:11:54 AM CST.
Installed Packages
docker-ce.x86_64 3:20.10.10-3.el8
@docker-ce
Available Packages
docker-ce.x86_64 3:19.03.13-3.el8
docker-ce
docker-ce.x86_64 3:19.03.14-3.el8
docker-ce
docker-ce.x86_64 3:19.03.15-3.el8
docker-ce
docker-ce.x86_64 3:20.10.0-3.el8
docker-ce
docker-ce.x86_64 3:20.10.1-3.el8
docker-ce
docker-ce.x86_64 3:20.10.2-3.el8
docker-ce
docker-ce.x86_64 3:20.10.3-3.el8
docker-ce
docker-ce.x86_64 3:20.10.4-3.el8
docker-ce
docker-ce.x86_64 3:20.10.5-3.el8
docker-ce
docker-ce.x86_64 3:20.10.6-3.el8
docker-ce
docker-ce.x86_64 3:20.10.7-3.el8
docker-ce
docker-ce.x86_64 3:20.10.8-3.el8
docker-ce
docker-ce.x86_64 3:20.10.9-3.el8
docker-ce
docker-ce.x86_64 3:20.10.10-3.el8
docker-ce
docker-ce.x86_64 3:20.10.11-3.el8
docker-ce
docker-ce.x86_64
3:20.10.12-3.el8
docker-ce
docker-ce.x86_64 3:20.10.13-3.el8
docker-ce
docker-ce.x86_64 3:20.10.14-3.el8
docker-ce
docker-ce.x86_64 3:20.10.15-3.el8
docker-ce
docker-ce.x86_64 3:20.10.16-3.el8
docker-ce
docker-ce.x86_64 3:20.10.17-3.el8
docker-ce
[root@rocky8 ~]#
[root@rocky8 ~]#yum install docker-ce-3:20.10.10-3.el8 docker-ce-cli-1:20.10.10-
3.el8
[root@rocky8 ~]#docker version
Client: Docker Engine - Community
 Version:           20.10.10
 API version:       1.41
 Go version:        go1.16.9
 Git commit:        b485636
 Built:             Mon Oct 25 07:42:56 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker
daemon running?
[root@rocky8 ~]#systemctl enable --now docker.service
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service →
/usr/lib/systemd/system/docker.service.

范例: CentOS 7 基于阿里云的安装docker方法

阿里云说明: https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11s UMKNV

# step 1: 安装必要的一些系统工具
yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-
ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装Docker-CE
yum makecache fast
yum -y install docker-ce
# Step 4: 开启Docker服务

service docker start

# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有
将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ee.repo
#   将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
#   Loading mirror speeds from cached hostfile
#   Loaded plugins: branch, fastestmirror, langpacks
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-
stable
#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-
stable
#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-
stable
#   Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
yum -y install docker-ce-[VERSION]
#示例
[root@centos7 ~]#yum -y install docker-ce-19.03.12-3.el7

范例: 在CentOS 7上安装指定版本的docker

[root@centos7 ~]#cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@centos7 ~]#ls /etc/yum.repos.d/
backup  base.repo
[root@centos7 ~]#wget -P /etc/yum.repos.d/ https://mirrors.aliyun.com/docker-
ce/linux/centos/docker-ce.repo
Saving to: ‘/etc/yum.repos.d/docker-ce.repo’
100%[====================================================================>]
2,640       --.-K/s   in 0s
2020-01-2321:56:21 (505 MB/s) - ‘/etc/yum.repos.d/docker-ce.repo’ saved
[2640/2640]
[root@centos7 ~]#ls /etc/yum.repos.d/
backup  base.repo  docker-ce.repo
[root@centos7 ~]#yum clean all
Loaded plugins: fastestmirror
Cleaning repos: base docker-ce-stable epel extras
Cleaning up list of fastest mirrors
[root@centos7 ~]#yum repolist
repo id                    repo name
status
base                       CentOS
10,019
docker-ce-stable/x86_64    Docker CE Stable - x86_64
63
epel/7/x86_64              EPEL
13,513
extras/7/x86_64            extras
307
repolist: 23,902
[root@centos7 ~]#yum list docker-ce* --showduplicates | sort -r
Loading mirror speeds from cached hostfile
Loaded plugins: fastestmirror
docker-ce.x86_643:19.03.5-3.el7 docker-ce-stable
docker-ce.x86_643:19.03.4-3.el7 docker-ce-stable
docker-ce.x86_643:19.03.3-3.el7 docker-ce-stable
docker-ce.x86_643:19.03.2-3.el7 docker-ce-stable
docker-ce.x86_643:19.03.1-3.el7 docker-ce-stable
docker-ce.x86_643:19.03.0-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.9-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.8-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.7-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.6-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.5-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.4-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.3-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.2-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_643:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_6418.06.3.ce-3.el7 docker-ce-stable
docker-ce.x86_6418.06.2.ce-3.el7 docker-ce-stable
docker-ce.x86_6418.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_6418.06.0.ce-3.el7 docker-ce-stable
docker-ce.x86_6418.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6418.03.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.12.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.12.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.09.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.09.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.06.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.06.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.06.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.03.3.ce-1.el7 docker-ce-stable
docker-ce.x86_6417.03.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_6417.03.0.ce-1.el7.centos docker-ce-stable
docker-ce-selinux.noarch17.03.3.ce-1.el7 docker-ce-stable
docker-ce-selinux.noarch17.03.2.ce-1.el7.centos docker-ce-stable
docker-ce-selinux.noarch17.03.1.ce-1.el7.centos docker-ce-stable
docker-ce-selinux.noarch17.03.0.ce-1.el7.centos docker-ce-stable
docker-ce-cli.x86_641:19.03.5-3.el7 docker-ce-stable
docker-ce-cli.x86_641:19.03.4-3.el7 docker-ce-stable
docker-ce-cli.x86_641:19.03.3-3.el7 docker-ce-stable
docker-ce-cli.x86_641:19.03.2-3.el7 docker-ce-stable
docker-ce-cli.x86_641:19.03.1-3.el7 docker-ce-stable
docker-ce-cli.x86_641:19.03.0-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.9-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.8-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.7-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.6-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.5-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.4-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.3-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.2-3.el7 docker-ce-stable
docker-ce-cli.x86_641:18.09.1-3.el7 docker-ce-stable

docker-ce-cli.x86_64 1:18.09.0-3.el7 docker-ce-stable Available Packages

[root@centos7 ~]#yum -y install docker-ce-18.09.9-3.el7 docker-ce-cli-18.09.9-
3.el7
Dependencies Resolved
=========================
=========
Package
=======================================================
Arch Version
Repository
=========================
Size
=======================================================
=========
Installing:
docker-ce x86_643:18.09.9-3.el7
docker-ce-stable 21 M
docker-ce-cli x86_641:18.09.9-3.el7
docker-ce-stable 16 M
Installingfor dependenci
audit-libs-python
es:
x86_642.8.4-4.el7
base 76 k
checkpolicy x86_642.5-8.el7
base 295 k
container-selinux noarch2:2.107-3.el7
extras 39 k
containerd.io x86_641.2.10-3.2.el7
docker-ce-stable 23 M
libcgroup x86_640.41-20.el7
base 66 k
libsemanage-python x86_642.5-14.el7
base 113 k
policycoreutils-python x86_642.5-29.el7
base 456 k
python-IPy noarch0.75-6.el7
base 32 k
setools-libs
base
x86_643.3.8-4.el7
620 k
Transaction Summary
================================================================================
==============================
Install  2 Packages (+9 Dependent packages)
Total download size: 62 M
Installed size: 258 M
Downloading packages:
(1/4): container-selinux-2.107-3.el7.noarch.rpm
     |  39 kB  00:00:00
warning: /var/cache/yum/x86_64/7/docker-ce-stable/packages/containerd.io-1.2.10-
3.2.el7.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 621e9f35: NOKEY
Public key for containerd.io-1.2.10-3.2.el7.x86_64.rpm is not installed
(2/4): containerd.io-1.2.10-3.2.el7.x86_64.rpm
      |  23 MB  00:00:03
(3/4): docker-ce-18.09.9-3.el7.x86_64.rpm
     |  21 MB  00:00:04
(4/4): docker-ce-cli-18.09.9-3.el7.x86_64.rpm
     |  16 MB  00:00:01
Complete!
[root@centos7 ~]#docker version
Client:
 Version:           18.09.9
 API version:       1.39
 Go version:        go1.11.13
 Git commit:        039a7df9ba
 Built:             Wed Sep  416:51:21 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker
daemon running?
[root@centos7 ~]#systemctl enable --now docker
[root@centos7 ~]#docker version
Client:
 Version:           18.09.9
 API version:       1.39
 Go version:        go1.11.13
 Git commit:        039a7df9ba
 Built:             Wed Sep  416:51:21 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Server: Docker Engine - Community
 Engine:
  Version:          18.09.9
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.11.13
  Git commit:       039a7df
  Built:            Wed Sep  416:22:32 2019
  OS/Arch:          linux/amd64
  Experimental:     false
[root@centos7 ~]#

范例: 在CentOS8安装docker

[root@centos8 ~]#tee  /etc/yum.repos.d/docker.repo  <<EOF
[docker]
name=docker
gpgcheck=0
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
EOF
[root@centos8 ~]#dnf -y install docker-ce
1.2.2.3 Linux 二进制安装

本方法适用于无法上网或无法通过包安装方式安装的主机上安装docker

安装文档: https://docs.docker.com/install/linux/docker-ce/binaries/

二进制安装下载路径

https://download.docker.com/linux/

https://mirrors.aliyun.com/docker-ce/linux/static/stable/x86_64/

范例: 在CentOS8上实现二进制安装docker

[root@centos8 ~]#wget
https://download.docker.com/linux/static/stable/x86_64/docker-19.03.5.tgz
[root@centos8 ~]#tar xvf docker-19.03.5.tgz
docker/
docker/docker-init
docker/docker
docker/dockerd
docker/runc
docker/ctr
docker/docker-proxy
docker/containerd
docker/containerd-shim
[root@centos8 ~]#cp docker/* /usr/bin/
#启动dockerd服务
[root@centos8 ~]#dockerd &>/dev/null &
[root@centos8 ~]#docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 1307:22:05 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 1307:28:45 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
[root@centos8 ~]#docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.

2. The Docker daemon pulled the "hello-world" image from the Docker Hub.

(amd64)

3. The Docker daemon created a new container from that image which runs the

executable that produces the output you are currently reading.

4. The Docker daemon streamed that output to the Docker client, which sent it

to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/
For more examples and ideas, visit:
 https://docs.docker.com/get-started/
[root@centos8 ~]#pstree -p
systemd(1)─┬─NetworkManager(660)─┬─{NetworkManager}(669)
           │                     └─{NetworkManager}(671)
           ├─VGAuthService(662)
           ├─agetty(718)
           ├─atd(712)
           ├─auditd(625)───{auditd}(627)
           ├─automount(905)─┬─{automount}(912)
           │                ├─{automount}(913)
           │                ├─{automount}(930)
           │                └─{automount}(937)
           ├─containerd(679)─┬─{containerd}(693)
           │                 ├─{containerd}(694)
           │                 ├─{containerd}(696)
           │                 ├─{containerd}(704)
           │                 ├─{containerd}(705)
           │                 ├─{containerd}(707)
           │                 └─{containerd}(708)
           ├─crond(713)
           ├─dbus-daemon(658)
           ├─dockerd(908)─┬─{dockerd}(922)
           │              ├─{dockerd}(923)
           │              ├─{dockerd}(925)
           │              ├─{dockerd}(944)
           │              ├─{dockerd}(1028)
           │              ├─{dockerd}(1100)
           │              └─{dockerd}(1114)
           ├─polkitd(659)─┬─{polkitd}(670)
           │              ├─{polkitd}(672)
           │              ├─{polkitd}(677)
           │              ├─{polkitd}(678)
           │              └─{polkitd}(701)
           ├─rngd(664)───{rngd}(666)
           ├─rsyslogd(906)─┬─{rsyslogd}(911)
           │               └─{rsyslogd}(914)
           ├─sshd(675)───sshd(1370)───sshd(1382)───bash(1383)───pstree(1441)
           ├─sssd(661)─┬─sssd_be(688)
           │           └─sssd_nss(703)
           ├─systemd(1373)───(sd-pam)(1376)
           ├─systemd-journal(551)
           ├─systemd-logind(709)
           ├─systemd-udevd(580)
           ├─tuned(674)─┬─{tuned}(915)
           │            ├─{tuned}(934)
           │            └─{tuned}(948)
           └─vmtoolsd(663)

范例: 创建 service文件

[root@centos8 ~]#cat > /lib/systemd/system/docker.service <<-EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues
still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix://var/run/docker.sock
ExecReload=/bin/kill -s HUP \$MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker
containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
[root@centos8 ~]#systemctl daemon-reload
[root@centos8 ~]#systemctl enable --now docker

范例: 创建相关的service文件,此方式新版有问题

#创建相关的service文件,此方式新版有问题
[root@centos8 ~]#groupadd -r docker
#将Ubuntu1804或CentOS7基于包方式安装的相关文件复制到相应目录下
[root@ubuntu1804 ~]#ll /lib/systemd/system/docker.*
-rw-r--r--1 root root 1683 Jun 2223:44 /lib/systemd/system/docker.service
-rw-r--r--1 root root  197 Jun 2223:44 /lib/systemd/system/docker.socket
[root@ubuntu1804 ~]#ll /lib/systemd/system/containerd.service
-rw-r--r--1 root root 1085 May  22020 /lib/systemd/system/containerd.service
[root@ubuntu1804 ~]#cat /lib/systemd/system/docker.socket
[Unit]
Description=Docker Socket for the API
PartOf=docker.service
[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
[root@ubuntu1804 ~]#cat /lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues
still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd
229.
# Both the old, and new location are accepted by systemd 229 and up, so using the
old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd
230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old
name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
# set delegate yes so that systemd does not reset the cgroups of docker
containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
[Install]
WantedBy=multi-user.target
[root@ubuntu1804 ~]#cat  /lib/systemd/system/containerd.service
#   Copyright 2018-2020 Docker Inc.
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#       http://www.apache.org/licenses/LICENSE-2.0
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd
KillMode=process
Delegate=yes
LimitNOFILE=1048576
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
[Install]
WantedBy=multi-user.target
[root@ubuntu1804 ~]#scp /lib/systemd/system/docker.*
/lib/systemd/system/containerd.service  10.0.0.8:/lib/systemd/system/
The authenticity of host '10.0.0.8 (10.0.0.8)' can't be established.
ECDSA key fingerprint is SHA256:8mUO3Wy13Ktt5pRBKaOU40avmw1x0gH5XTPK48CEWoM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.8' (ECDSA) to the list of known hosts.
root@10.0.0.8's password:
docker.service                                             100% 1683650.8KB/s
00:00  docker.socket                                              100%  197
303.3KB/s   00:00
containerd.service                                         100%  487516.6KB/s
00:00
[root@centos8 ~]#systemctl daemon-reload
[root@centos8 ~]#systemctl enable --now docker

范例: 一键离线安装二进制 docker

#!/bin/bash
#
#********************************************************************
#Author:            wangxiaochun
#QQ:                29308620
#Date:              2022-10-14
#FileName:          install_docker_offline.sh
#URL:               http://www.wangxiaochun.com
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************
DOCKER_VERSION=20.10.19
#DOCKER_VERSION=20.10.10
#URL=https://mirrors.aliyun.com
URL=https://download.docker.com
prepare () {
if [ ! -e docker-${DOCKER_VERSION}.tgz ];then
#wget ${URL}/docker-
ce/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz
wget${URL}/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz
fi
    [ $?-ne0  ] && { echo"文件下载失败"; exit; }
}
install_docker () {
    tar xf docker-${DOCKER_VERSION}.tgz -C /usr/local/
cp /usr/local/docker/* /usr/bin/
cat > /lib/systemd/system/docker.service <<-EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues
still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix://var/run/docker.sock
ExecReload=/bin/kill -s HUP \$MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker
containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
}
start_docker (){
    systemctl enable --now docker
    docker info
}
config_docker () {
mkdir-p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
    {
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
     }
EOF
    systemctl restart docker
}
prepare
install_docker
config_docker
start_docker
1.2.2.4 安装 podman

范例: 在CentOS8上安装podman

#在CentOS8上安装docker会自动安装podman,docker工具只是一个脚本,调用了Podman
[root@centos8 ~]#dnf install docker
[root@centos8 ~]#rpm -ql podman-docker
/usr/bin/docker
[root@centos8 ~]#cat /usr/bin/docker
#!/bin/sh
[ -f /etc/containers/nodocker ] || \
echo"Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet
msg." >&2
exec /usr/bin/podman "$@"
[root@centos8 ~]#podman version
Version:            1.4.2-stable2
RemoteAPI Version:  1
Go Version:         go1.12.8
OS/Arch:            linux/amd64
#修改拉取镜像的地址的顺序,提高速度
[root@centos8 ~]#vim /etc/containers/registries.conf
[registries.search]
registries = ['docker.io','quay.io','registry.redhat.io',
'registry.access.redhat.com']
1.2.2.5 在不同系统上实现一键安装 docker 脚本

1.2.2.5.1 基于 ubuntu 18.04和20.04 的一键安装 docker 脚本

[root@ubuntu1804 ~]#cat install_docker_ubuntu.sh
#!/bin/bash
#Description: Install docker on Ubuntu18.04 and 20.04
#Version:1.0
#Date:2020-01-22
COLOR="echo -e \\033[1;31m"
END="\033[m"
DOCKER_VERSION="5:19.03.5~3-0~ubuntu-bionic"
install_docker(){
dpkg -s docker-ce &> /dev/null && ${COLOR}"Docker已安装,退出"${END} && exit
apt update
apt  -y install apt-transport-https ca-certificates curl software-properties-
common
#curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key
add -
#add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-
ce/linux/ubuntu $(lsb_release -cs) stable"
curl-fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg |
sudo apt-key add -
add-apt-repository "deb [arch=amd64]
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs)
stable"
apt update
${COLOR}"Docker有以下版本"${END}
apt-cache madison docker-ce
${COLOR}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep5
apt -y  install docker-ce=${DOCKER_VERSION}docker-ce-cli=${DOCKER_VERSION}
mkdir-p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl enable --now docker
docker version && ${COLOR}"Docker 安装成功"${END} ||  ${COLOR}"Docker 安装失
败"${END}
}
install_docker
1.2.2.5.2 基于 CentOS 8 实现一键安装 docker 脚本

1.2.2.5.2.1 脚本1

利用阿里云的基于CentOS8的docker yum源实现

#!/bin/bash
#
#********************************************************************
#Author:        wangxiaochun
#QQ:            29308620
#Date:          2020-11-13
#FileName:      install_docker_for_centos8.sh
#URL:           http://www.wangxiaochun.com
#Description:       The test script
#Copyright (C):     2020 All rights reserved
#********************************************************************
. /etc/init.d/functions
COLOR="echo -e \\E[1;32m"
END="\\E[0m"
DOCKER_VERSION="-19.03.13-3.el8"
install_docker() {
    rpm -q docker-ce &> /dev/null && action "Docker已安装" && exit
${COLOR}"开始安装 Docker....."${END}
sleep1
cat >  /etc/yum.repos.d/docker.repo  <<EOF
[docker]
name=docker
gpgcheck=0
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-
ce/linux/centos/8/x86_64/stable/
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
EOF
    yum clean all
    yum -y install docker-ce$DOCKER_VERSION docker-ce-cli$DOCKER_VERSION  \
        || { ${COLOR}"Base,Extras的yum源失败,请检查yum源配置"${END};exit; }
mkdir-p /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
 }
EOF
    systemctl enable --now docker
    docker version && ${COLOR}"Docker安装成功"${END} || ${COLOR}"Docker安装失
败"${END}
}
install_docker

1.2.2.5.2.2 脚本2

早期CentOS8无yum仓库,可以利用下面脚本安装docker

#!/bin/bash
#
#********************************************************************
#Author:           wangxiaochun
#QQ:               29308620
#Date:             2020-02-27
#FileName:         install_docker_for_centos8.sh
#URL:              http://www.wangxiaochun.com
#Description:      The test script
#Copyright (C):    2020 All rights reserved
#********************************************************************
. /etc/init.d/functions
COLOR="echo -e \\E[1;32m"
END="\\E[0m"
DOCKER_VERSION="-19.03.8-3.el7"
install_docker() {
${COLOR}"开始安装 Docker....."${END}
sleep1
#wget -P /etc/yum.repos.d/ https://mirrors.aliyun.com/docker-
ce/linux/centos/docker-ce.repo  || { ${COLOR}"互联网连接失败,请检查网络配
置!"${END};exit; }
wget-P /etc/yum.repos.d/ https://mirrors.tuna.tsinghua.edu.cn/docker-
ce/linux/centos/docker-ce.repo  || { ${COLOR}"互联网连接失败,请检查网络配
置!"${END};exit; }
    yum clean all
    dnf -y install https://mirrors.aliyun.com/docker-
ce/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
    yum -y install docker-ce$DOCKER_VERSION docker-ce-cli$DOCKER_VERSION  \
        || { ${COLOR}"Base,Extras的yum源失败,请检查yum源配置"${END};exit; }
mkdir-p /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
 }
EOF
    systemctl enable --now docker
    docker version && ${COLOR}"Docker安装成功"${END} || ${COLOR}"Docker安装失
败"${END}
}
rpm -q docker &> /dev/null && action "Docker已安装" || install_docker
1.2.2.5.3 基于 CentOS 7 实现一键安装docker 脚本
[root@centos7 ~]#cat install_docker_for_centos7.sh
#!/bin/bash
#
#********************************************************************
#Author:           wangxiaochun
#QQ:               29308620
#Date:             2020-02-27
#FileName:         install_docker_for_centos7.sh
#URL:              http://www.wangxiaochun.com
#Description:      The test script
#Copyright (C):    2020 All rights reserved
#********************************************************************
. /etc/init.d/functions
COLOR="echo -e \\033[1;31m"
END="\033[m"
VERSION="19.03.5-3.el7"
rpm -q docker-ce &> /dev/null && action "Docker已安装" && exit
wget-P /etc/yum.repos.d/ https://mirrors.tuna.tsinghua.edu.cn/docker-
ce/linux/centos/docker-ce.repo  || { ${COLOR}"互联网连接失败,请检查网络配
置!"${END};exit; }
#wget -P /etc/yum.repos.d/ https://mirrors.aliyun.com/docker-
ce/linux/centos/docker-ce.repo  || { ${COLOR}"互联网连接失败,请检查网络配
置!"${END};exit; }
yum clean all
yum -y install docker-ce-$VERSION docker-ce-cli-$VERSION || {
${COLOR}"Base,Extras的yum源失败,请检查yum源配置"${END};exit; }
#使用阿里做镜像加速
mkdir-p /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
 }
EOF
systemctl enable --now docker
docker version && ${COLOR}"Docker安装成功"${END} || ${COLOR}"Docker安装失败"${END}

1.2.2.5.4 通用安装docker脚本

[root@ubuntu1804 ~]#curl -fsSL get.docker.com -o get-docker.sh
[root@ubuntu1804 ~]#sh get-docker.sh --mirror Aliyun

1.2.3 Docker 程序环境

环境配置文件:

/etc/sysconfig/docker-network
/etc/sysconfig/docker-storage
/etc/sysconfig/docker

Unit File:

/usr/lib/systemd/system/docker.service

docker-ce 配置文件:

/etc/docker/daemon.json

Docker Registry配置文件:

/etc/containers/registries.conf

范例: ubuntu 查看docker相关文件

#服务器端相关文件
[root@ubuntu1804 ~]#dpkg -L docker-ce
/.
/etc
/etc/default
/etc/default/docker
/etc/init
/etc/init/docker.conf
/etc/init.d
/etc/init.d/docker
/lib
/lib/systemd
/lib/systemd/system
/lib/systemd/system/docker.service
/lib/systemd/system/docker.socket
/usr
/usr/bin
/usr/bin/docker-init
/usr/bin/docker-proxy
/usr/bin/dockerd
/usr/share
/usr/share/doc
/usr/share/doc/docker-ce
/usr/share/doc/docker-ce/README.md
/usr/share/doc/docker-ce/changelog.Debian.gz
/var
/var/lib
/var/lib/docker-engine
/var/lib/docker-engine/distribution_based_engine.json
#客户端相关文件
[root@ubuntu1804 ~]#dpkg -L docker-ce-cli
/.
/usr
/usr/bin
/usr/bin/docker
/usr/libexec
/usr/libexec/docker
/usr/libexec/docker/cli-plugins
/usr/libexec/docker/cli-plugins/docker-app
/usr/libexec/docker/cli-plugins/docker-buildx
/usr/share
/usr/share/bash-completion
/usr/share/bash-completion/completions
/usr/share/bash-completion/completions/docker
/usr/share/doc
/usr/share/doc/docker-ce-cli
/usr/share/doc/docker-ce-cli/changelog.Debian.gz
/usr/share/fish
/usr/share/fish/vendor_completions.d
/usr/share/fish/vendor_completions.d/docker.fish
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/docker-attach.1.gz
/usr/share/man/man1/docker-build.1.gz
/usr/share/man/man1/docker-builder-build.1.gz
/usr/share/man/man1/docker-builder-prune.1.gz
/usr/share/man/man1/docker-builder.1.gz
/usr/share/man/man1/docker-checkpoint-create.1.gz
/usr/share/man/man1/docker-checkpoint-ls.1.gz
/usr/share/man/man1/docker-checkpoint-rm.1.gz
/usr/share/man/man1/docker-checkpoint.1.gz
/usr/share/man/man1/docker-commit.1.gz
/usr/share/man/man1/docker-config-create.1.gz
/usr/share/man/man1/docker-config-inspect.1.gz
/usr/share/man/man1/docker-config-ls.1.gz
/usr/share/man/man1/docker-config-rm.1.gz
/usr/share/man/man1/docker-config.1.gz
/usr/share/man/man1/docker-container-attach.1.gz
/usr/share/man/man1/docker-container-commit.1.gz
/usr/share/man/man1/docker-container-cp.1.gz
/usr/share/man/man1/docker-container-create.1.gz
/usr/share/man/man1/docker-container-diff.1.gz
/usr/share/man/man1/docker-container-exec.1.gz
/usr/share/man/man1/docker-container-export.1.gz
/usr/share/man/man1/docker-container-inspect.1.gz
/usr/share/man/man1/docker-container-kill.1.gz
/usr/share/man/man1/docker-container-logs.1.gz
/usr/share/man/man1/docker-container-ls.1.gz
/usr/share/man/man1/docker-container-pause.1.gz
/usr/share/man/man1/docker-container-port.1.gz
/usr/share/man/man1/docker-container-prune.1.gz
/usr/share/man/man1/docker-container-rename.1.gz
/usr/share/man/man1/docker-container-restart.1.gz
/usr/share/man/man1/docker-container-rm.1.gz
/usr/share/man/man1/docker-container-run.1.gz
/usr/share/man/man1/docker-container-start.1.gz
/usr/share/man/man1/docker-container-stats.1.gz
/usr/share/man/man1/docker-container-stop.1.gz
/usr/share/man/man1/docker-container-top.1.gz
/usr/share/man/man1/docker-container-unpause.1.gz
/usr/share/man/man1/docker-container-update.1.gz
/usr/share/man/man1/docker-container-wait.1.gz
/usr/share/man/man1/docker-container.1.gz
/usr/share/man/man1/docker-context-create.1.gz
/usr/share/man/man1/docker-context-export.1.gz
/usr/share/man/man1/docker-context-import.1.gz
/usr/share/man/man1/docker-context-inspect.1.gz
/usr/share/man/man1/docker-context-ls.1.gz
/usr/share/man/man1/docker-context-rm.1.gz
/usr/share/man/man1/docker-context-update.1.gz
/usr/share/man/man1/docker-context-use.1.gz
/usr/share/man/man1/docker-context.1.gz
/usr/share/man/man1/docker-cp.1.gz
/usr/share/man/man1/docker-create.1.gz
/usr/share/man/man1/docker-deploy.1.gz
/usr/share/man/man1/docker-diff.1.gz
/usr/share/man/man1/docker-engine-activate.1.gz
/usr/share/man/man1/docker-engine-check.1.gz
/usr/share/man/man1/docker-engine-update.1.gz
/usr/share/man/man1/docker-engine.1.gz
/usr/share/man/man1/docker-events.1.gz
/usr/share/man/man1/docker-exec.1.gz
/usr/share/man/man1/docker-export.1.gz
/usr/share/man/man1/docker-history.1.gz
/usr/share/man/man1/docker-image-build.1.gz
/usr/share/man/man1/docker-image-history.1.gz
/usr/share/man/man1/docker-image-import.1.gz
/usr/share/man/man1/docker-image-inspect.1.gz
/usr/share/man/man1/docker-image-load.1.gz
/usr/share/man/man1/docker-image-ls.1.gz
/usr/share/man/man1/docker-image-prune.1.gz
/usr/share/man/man1/docker-image-pull.1.gz
/usr/share/man/man1/docker-image-push.1.gz
/usr/share/man/man1/docker-image-rm.1.gz
/usr/share/man/man1/docker-image-save.1.gz
/usr/share/man/man1/docker-image-tag.1.gz
/usr/share/man/man1/docker-image.1.gz
/usr/share/man/man1/docker-images.1.gz
/usr/share/man/man1/docker-import.1.gz
  • /usr/share/man/man1/docker-info.1.gz

  • /usr/share/man/man1/docker-inspect.1.gz

/usr/share/man/man1/docker-kill.1.gz
/usr/share/man/man1/docker-load.1.gz
  • /usr/share/man/man1/docker-login.1.gz

  • /usr/share/man/man1/docker-logout.1.gz

  • /usr/share/man/man1/docker-logs.1.gz

  • /usr/share/man/man1/docker-manifest-annotate.1.gz

/usr/share/man/man1/docker-manifest-create.1.gz
  • /usr/share/man/man1/docker-manifest-inspect.1.gz

  • /usr/share/man/man1/docker-manifest-push.1.gz

/usr/share/man/man1/docker-manifest.1.gz
/usr/share/man/man1/docker-network-connect.1.gz
/usr/share/man/man1/docker-network-create.1.gz
/usr/share/man/man1/docker-network-disconnect.1.gz
/usr/share/man/man1/docker-network-inspect.1.gz
/usr/share/man/man1/docker-network-ls.1.gz
/usr/share/man/man1/docker-network-prune.1.gz
/usr/share/man/man1/docker-network-rm.1.gz
/usr/share/man/man1/docker-network.1.gz
/usr/share/man/man1/docker-node-demote.1.gz
/usr/share/man/man1/docker-node-inspect.1.gz
/usr/share/man/man1/docker-node-ls.1.gz
/usr/share/man/man1/docker-node-promote.1.gz
/usr/share/man/man1/docker-node-ps.1.gz
/usr/share/man/man1/docker-node-rm.1.gz
/usr/share/man/man1/docker-node-update.1.gz
/usr/share/man/man1/docker-node.1.gz
/usr/share/man/man1/docker-pause.1.gz
/usr/share/man/man1/docker-plugin-create.1.gz
/usr/share/man/man1/docker-plugin-disable.1.gz
/usr/share/man/man1/docker-plugin-enable.1.gz
/usr/share/man/man1/docker-plugin-inspect.1.gz
/usr/share/man/man1/docker-plugin-install.1.gz
/usr/share/man/man1/docker-plugin-ls.1.gz
/usr/share/man/man1/docker-plugin-push.1.gz
/usr/share/man/man1/docker-plugin-rm.1.gz
/usr/share/man/man1/docker-plugin-set.1.gz
/usr/share/man/man1/docker-plugin-upgrade.1.gz
/usr/share/man/man1/docker-plugin.1.gz
/usr/share/man/man1/docker-port.1.gz
/usr/share/man/man1/docker-ps.1.gz
/usr/share/man/man1/docker-pull.1.gz
/usr/share/man/man1/docker-push.1.gz
/usr/share/man/man1/docker-rename.1.gz
/usr/share/man/man1/docker-restart.1.gz
/usr/share/man/man1/docker-rm.1.gz
/usr/share/man/man1/docker-rmi.1.gz
/usr/share/man/man1/docker-run.1.gz
/usr/share/man/man1/docker-save.1.gz
/usr/share/man/man1/docker-search.1.gz
/usr/share/man/man1/docker-secret-create.1.gz
/usr/share/man/man1/docker-secret-inspect.1.gz
/usr/share/man/man1/docker-secret-ls.1.gz
/usr/share/man/man1/docker-secret-rm.1.gz
/usr/share/man/man1/docker-secret.1.gz
/usr/share/man/man1/docker-service-create.1.gz
/usr/share/man/man1/docker-service-inspect.1.gz
/usr/share/man/man1/docker-service-logs.1.gz
/usr/share/man/man1/docker-service-ls.1.gz
/usr/share/man/man1/docker-service-ps.1.gz
/usr/share/man/man1/docker-service-rm.1.gz
/usr/share/man/man1/docker-service-rollback.1.gz
/usr/share/man/man1/docker-service-scale.1.gz
/usr/share/man/man1/docker-service-update.1.gz
/usr/share/man/man1/docker-service.1.gz
/usr/share/man/man1/docker-stack-deploy.1.gz
/usr/share/man/man1/docker-stack-ls.1.gz
/usr/share/man/man1/docker-stack-ps.1.gz
/usr/share/man/man1/docker-stack-rm.1.gz
/usr/share/man/man1/docker-stack-services.1.gz
/usr/share/man/man1/docker-stack.1.gz
/usr/share/man/man1/docker-start.1.gz
/usr/share/man/man1/docker-stats.1.gz
/usr/share/man/man1/docker-stop.1.gz
/usr/share/man/man1/docker-swarm-ca.1.gz
/usr/share/man/man1/docker-swarm-init.1.gz
/usr/share/man/man1/docker-swarm-join-token.1.gz
/usr/share/man/man1/docker-swarm-join.1.gz
/usr/share/man/man1/docker-swarm-leave.1.gz
/usr/share/man/man1/docker-swarm-unlock-key.1.gz
/usr/share/man/man1/docker-swarm-unlock.1.gz
/usr/share/man/man1/docker-swarm-update.1.gz
/usr/share/man/man1/docker-swarm.1.gz
/usr/share/man/man1/docker-system-df.1.gz
/usr/share/man/man1/docker-system-events.1.gz
/usr/share/man/man1/docker-system-info.1.gz
/usr/share/man/man1/docker-system-prune.1.gz
/usr/share/man/man1/docker-system.1.gz
/usr/share/man/man1/docker-tag.1.gz
/usr/share/man/man1/docker-top.1.gz
/usr/share/man/man1/docker-trust-inspect.1.gz
/usr/share/man/man1/docker-trust-key-generate.1.gz
/usr/share/man/man1/docker-trust-key-load.1.gz
/usr/share/man/man1/docker-trust-key.1.gz
/usr/share/man/man1/docker-trust-revoke.1.gz
/usr/share/man/man1/docker-trust-sign.1.gz
/usr/share/man/man1/docker-trust-signer-add.1.gz
/usr/share/man/man1/docker-trust-signer-remove.1.gz
/usr/share/man/man1/docker-trust-signer.1.gz
/usr/share/man/man1/docker-trust.1.gz
/usr/share/man/man1/docker-unpause.1.gz
/usr/share/man/man1/docker-update.1.gz
/usr/share/man/man1/docker-version.1.gz
/usr/share/man/man1/docker-volume-create.1.gz
/usr/share/man/man1/docker-volume-inspect.1.gz
/usr/share/man/man1/docker-volume-ls.1.gz
/usr/share/man/man1/docker-volume-prune.1.gz
/usr/share/man/man1/docker-volume-rm.1.gz
/usr/share/man/man1/docker-volume.1.gz
/usr/share/man/man1/docker-wait.1.gz
/usr/share/man/man1/docker.1.gz
/usr/share/man/man5
/usr/share/man/man5/Dockerfile.5.gz
/usr/share/man/man5/docker-config-json.5.gz
/usr/share/man/man8
/usr/share/man/man8/dockerd.8.gz
/usr/share/zsh
/usr/share/zsh/vendor-completions
/usr/share/zsh/vendor-completions/_docker

范例: CentOS7 查看docker相关文件

[root@centos7 ~]#rpm -ql docker-ce
/usr/bin/docker-init
/usr/bin/docker-proxy
/usr/bin/dockerd
/usr/lib/systemd/system/docker.service
/usr/lib/systemd/system/docker.socket
[root@centos7 ~]#rpm -ql docker-ce-cli
/usr/bin/docker
/usr/libexec/docker/cli-plugins/docker-app
/usr/libexec/docker/cli-plugins/docker-buildx
/usr/share/bash-completion/completions/docker
/usr/share/doc/docker-ce-cli-19.03.12
/usr/share/doc/docker-ce-cli-19.03.12/LICENSE
/usr/share/doc/docker-ce-cli-19.03.12/MAINTAINERS
/usr/share/doc/docker-ce-cli-19.03.12/NOTICE
/usr/share/doc/docker-ce-cli-19.03.12/README.md
/usr/share/fish/vendor_completions.d/docker.fish
/usr/share/man/man1/docker-attach.1.gz
/usr/share/man/man1/docker-build.1.gz
/usr/share/man/man1/docker-builder-build.1.gz
/usr/share/man/man1/docker-builder-prune.1.gz
/usr/share/man/man1/docker-builder.1.gz
/usr/share/man/man1/docker-checkpoint-create.1.gz
/usr/share/man/man1/docker-checkpoint-ls.1.gz
/usr/share/man/man1/docker-checkpoint-rm.1.gz
/usr/share/man/man1/docker-checkpoint.1.gz
/usr/share/man/man1/docker-commit.1.gz
/usr/share/man/man1/docker-config-create.1.gz
/usr/share/man/man1/docker-config-inspect.1.gz
/usr/share/man/man1/docker-config-ls.1.gz
/usr/share/man/man1/docker-config-rm.1.gz
/usr/share/man/man1/docker-config.1.gz
/usr/share/man/man1/docker-container-attach.1.gz
/usr/share/man/man1/docker-container-commit.1.gz
/usr/share/man/man1/docker-container-cp.1.gz
/usr/share/man/man1/docker-container-create.1.gz
/usr/share/man/man1/docker-container-diff.1.gz
/usr/share/man/man1/docker-container-exec.1.gz
/usr/share/man/man1/docker-container-export.1.gz
/usr/share/man/man1/docker-container-inspect.1.gz
/usr/share/man/man1/docker-container-kill.1.gz
/usr/share/man/man1/docker-container-logs.1.gz
/usr/share/man/man1/docker-container-ls.1.gz
/usr/share/man/man1/docker-container-pause.1.gz
/usr/share/man/man1/docker-container-port.1.gz
/usr/share/man/man1/docker-container-prune.1.gz
/usr/share/man/man1/docker-container-rename.1.gz
/usr/share/man/man1/docker-container-restart.1.gz
/usr/share/man/man1/docker-container-rm.1.gz
/usr/share/man/man1/docker-container-run.1.gz
/usr/share/man/man1/docker-container-start.1.gz
/usr/share/man/man1/docker-container-stats.1.gz
/usr/share/man/man1/docker-container-stop.1.gz
/usr/share/man/man1/docker-container-top.1.gz
/usr/share/man/man1/docker-container-unpause.1.gz
/usr/share/man/man1/docker-container-update.1.gz
/usr/share/man/man1/docker-container-wait.1.gz
/usr/share/man/man1/docker-container.1.gz
/usr/share/man/man1/docker-context-create.1.gz
/usr/share/man/man1/docker-context-export.1.gz
/usr/share/man/man1/docker-context-import.1.gz
/usr/share/man/man1/docker-context-inspect.1.gz
/usr/share/man/man1/docker-context-ls.1.gz
/usr/share/man/man1/docker-context-rm.1.gz
/usr/share/man/man1/docker-context-update.1.gz
/usr/share/man/man1/docker-context-use.1.gz
/usr/share/man/man1/docker-context.1.gz
/usr/share/man/man1/docker-cp.1.gz
/usr/share/man/man1/docker-create.1.gz
/usr/share/man/man1/docker-deploy.1.gz
/usr/share/man/man1/docker-diff.1.gz
/usr/share/man/man1/docker-engine-activate.1.gz
/usr/share/man/man1/docker-engine-check.1.gz
/usr/share/man/man1/docker-engine-update.1.gz
/usr/share/man/man1/docker-engine.1.gz
/usr/share/man/man1/docker-events.1.gz
/usr/share/man/man1/docker-exec.1.gz
/usr/share/man/man1/docker-export.1.gz
/usr/share/man/man1/docker-history.1.gz
/usr/share/man/man1/docker-image-build.1.gz
/usr/share/man/man1/docker-image-history.1.gz
/usr/share/man/man1/docker-image-import.1.gz
/usr/share/man/man1/docker-image-inspect.1.gz
/usr/share/man/man1/docker-image-load.1.gz
/usr/share/man/man1/docker-image-ls.1.gz
/usr/share/man/man1/docker-image-prune.1.gz
/usr/share/man/man1/docker-image-pull.1.gz
/usr/share/man/man1/docker-image-push.1.gz
/usr/share/man/man1/docker-image-rm.1.gz
/usr/share/man/man1/docker-image-save.1.gz
/usr/share/man/man1/docker-image-tag.1.gz
/usr/share/man/man1/docker-image.1.gz
/usr/share/man/man1/docker-images.1.gz
/usr/share/man/man1/docker-import.1.gz
/usr/share/man/man1/docker-info.1.gz
/usr/share/man/man1/docker-inspect.1.gz
/usr/share/man/man1/docker-kill.1.gz
/usr/share/man/man1/docker-load.1.gz
/usr/share/man/man1/docker-login.1.gz
/usr/share/man/man1/docker-logout.1.gz
/usr/share/man/man1/docker-logs.1.gz
/usr/share/man/man1/docker-manifest-annotate.1.gz
/usr/share/man/man1/docker-manifest-create.1.gz
/usr/share/man/man1/docker-manifest-inspect.1.gz
/usr/share/man/man1/docker-manifest-push.1.gz
/usr/share/man/man1/docker-manifest.1.gz
/usr/share/man/man1/docker-network-connect.1.gz
/usr/share/man/man1/docker-network-create.1.gz
/usr/share/man/man1/docker-network-disconnect.1.gz
/usr/share/man/man1/docker-network-inspect.1.gz
/usr/share/man/man1/docker-network-ls.1.gz
/usr/share/man/man1/docker-network-prune.1.gz
/usr/share/man/man1/docker-network-rm.1.gz
/usr/share/man/man1/docker-network.1.gz
/usr/share/man/man1/docker-node-demote.1.gz
/usr/share/man/man1/docker-node-inspect.1.gz
/usr/share/man/man1/docker-node-ls.1.gz
  • /usr/share/man/man1/docker-node-promote.1.gz

  • /usr/share/man/man1/docker-node-ps.1.gz

/usr/share/man/man1/docker-node-rm.1.gz
/usr/share/man/man1/docker-node-update.1.gz
/usr/share/man/man1/docker-node.1.gz
/usr/share/man/man1/docker-pause.1.gz
/usr/share/man/man1/docker-plugin-create.1.gz
/usr/share/man/man1/docker-plugin-disable.1.gz
/usr/share/man/man1/docker-plugin-enable.1.gz
/usr/share/man/man1/docker-plugin-inspect.1.gz
/usr/share/man/man1/docker-plugin-install.1.gz
/usr/share/man/man1/docker-plugin-ls.1.gz
/usr/share/man/man1/docker-plugin-push.1.gz
/usr/share/man/man1/docker-plugin-rm.1.gz
/usr/share/man/man1/docker-plugin-set.1.gz
/usr/share/man/man1/docker-plugin-upgrade.1.gz
/usr/share/man/man1/docker-plugin.1.gz
/usr/share/man/man1/docker-port.1.gz
/usr/share/man/man1/docker-ps.1.gz
/usr/share/man/man1/docker-pull.1.gz
/usr/share/man/man1/docker-push.1.gz
/usr/share/man/man1/docker-rename.1.gz
/usr/share/man/man1/docker-restart.1.gz
/usr/share/man/man1/docker-rm.1.gz
/usr/share/man/man1/docker-rmi.1.gz
/usr/share/man/man1/docker-run.1.gz
/usr/share/man/man1/docker-save.1.gz
/usr/share/man/man1/docker-search.1.gz
/usr/share/man/man1/docker-secret-create.1.gz
/usr/share/man/man1/docker-secret-inspect.1.gz
/usr/share/man/man1/docker-secret-ls.1.gz
/usr/share/man/man1/docker-secret-rm.1.gz
/usr/share/man/man1/docker-secret.1.gz
/usr/share/man/man1/docker-service-create.1.gz
/usr/share/man/man1/docker-service-inspect.1.gz
/usr/share/man/man1/docker-service-logs.1.gz
/usr/share/man/man1/docker-service-ls.1.gz
/usr/share/man/man1/docker-service-ps.1.gz
/usr/share/man/man1/docker-service-rm.1.gz
/usr/share/man/man1/docker-service-rollback.1.gz
/usr/share/man/man1/docker-service-scale.1.gz
/usr/share/man/man1/docker-service-update.1.gz
/usr/share/man/man1/docker-service.1.gz
/usr/share/man/man1/docker-stack-deploy.1.gz
/usr/share/man/man1/docker-stack-ls.1.gz
/usr/share/man/man1/docker-stack-ps.1.gz
/usr/share/man/man1/docker-stack-rm.1.gz
/usr/share/man/man1/docker-stack-services.1.gz
/usr/share/man/man1/docker-stack.1.gz
/usr/share/man/man1/docker-start.1.gz
/usr/share/man/man1/docker-stats.1.gz
/usr/share/man/man1/docker-stop.1.gz
/usr/share/man/man1/docker-swarm-ca.1.gz
/usr/share/man/man1/docker-swarm-init.1.gz
/usr/share/man/man1/docker-swarm-join-token.1.gz
/usr/share/man/man1/docker-swarm-join.1.gz
/usr/share/man/man1/docker-swarm-leave.1.gz
/usr/share/man/man1/docker-swarm-unlock-key.1.gz
/usr/share/man/man1/docker-swarm-unlock.1.gz
/usr/share/man/man1/docker-swarm-update.1.gz
/usr/share/man/man1/docker-swarm.1.gz
/usr/share/man/man1/docker-system-df.1.gz
/usr/share/man/man1/docker-system-events.1.gz
/usr/share/man/man1/docker-system-info.1.gz
/usr/share/man/man1/docker-system-prune.1.gz
/usr/share/man/man1/docker-system.1.gz
/usr/share/man/man1/docker-tag.1.gz
/usr/share/man/man1/docker-top.1.gz
/usr/share/man/man1/docker-trust-inspect.1.gz
/usr/share/man/man1/docker-trust-key-generate.1.gz
/usr/share/man/man1/docker-trust-key-load.1.gz
/usr/share/man/man1/docker-trust-key.1.gz
/usr/share/man/man1/docker-trust-revoke.1.gz
/usr/share/man/man1/docker-trust-sign.1.gz
/usr/share/man/man1/docker-trust-signer-add.1.gz
/usr/share/man/man1/docker-trust-signer-remove.1.gz
/usr/share/man/man1/docker-trust-signer.1.gz
/usr/share/man/man1/docker-trust.1.gz
/usr/share/man/man1/docker-unpause.1.gz
/usr/share/man/man1/docker-update.1.gz
/usr/share/man/man1/docker-version.1.gz
/usr/share/man/man1/docker-volume-create.1.gz
/usr/share/man/man1/docker-volume-inspect.1.gz
/usr/share/man/man1/docker-volume-ls.1.gz
/usr/share/man/man1/docker-volume-prune.1.gz
/usr/share/man/man1/docker-volume-rm.1.gz
/usr/share/man/man1/docker-volume.1.gz
/usr/share/man/man1/docker-wait.1.gz
/usr/share/man/man1/docker.1.gz
/usr/share/man/man5/Dockerfile.5.gz
/usr/share/man/man5/docker-config-json.5.gz
/usr/share/man/man8/dockerd.8.gz
/usr/share/zsh/vendor-completions/_docker

1.2.4 docker 命令帮助

docker 命令是最常使用的docker 客户端命令,其后面可以加不同的参数以实现不同的功能

docker 命令格式

docker [OPTIONS] COMMAND
COMMAND分为
Management Commands  #指定管理的资源对象类型,较新的命令用法,将命令按资源类型进行分类,方便使
用
Commands             #对不同资源操作的命令不分类,使用容易产生混乱

docker 命令有很多子命令,可以用下面方法查看帮助

#docker 命令帮助
man docker
docker
docker  --help
#docker  子命令帮助
man docker-COMMAND
docker COMMAND --help

官方文档:

https://docs.docker.com/reference/
https://docs.docker.com/engine/reference/commandline/cli/

范例: 查看docker命令帮助

[root@ubuntu1804 ~]#docker --help
Usage:  docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Options:
--config string      Location of client config files (default
"/root/.docker")
-c, --context string     Name of the context to use to connect to the daemon
(overrides DOCKER_HOST env var and default
                           context set with "docker context use")
-D, --debug              Enable debug mode
-H, --host list          Daemon socket(s) to connect to
-l, --log-level string   Set the logging level
("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls                Use TLS; implied by --tlsverify
--tlscacert string   Trust certs signed only by this CA (default
"/root/.docker/ca.pem")
--tlscert string     Path to TLS certificate file (default
"/root/.docker/cert.pem")
--tlskey string      Path to TLS key file (default
"/root/.docker/key.pem")
--tlsverify          Use TLS and verify the remote
-v, --version            Print version information and quit
Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes
Commands:
  attach      Attach local standard input, output, and error streams to a running
container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
diff        Inspect changes to files or directories on a container's
filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
restart     Restart one or more containers
rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by
default)
  search      Search the Docker Hub for images
start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit
codes
Run 'docker COMMAND --help'for more information on a command.

1.2.5 查看 Docker 相关信息

1.2.5.1 查看 Docker 版本
[root@ubuntu1804 ~]#docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 1307:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 1307:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
1.2.5.2 查看 Docker 详解信息
[root@ubuntu1804 ~]#docker info
Client:
 Debug Mode: false#client 端是否开启 debug
Server:
 Containers: 2#当前主机运行的容器总数
  Running: 0#有几个容器是正在运行的
  Paused: 0#有几个容器是暂停的
  Stopped: 2#有几个容器是停止的
 Images: 4#当前服务器的镜像数
 Server Version: 19.03.5   #服务端版本
 Storage Driver: overlay2  #正在使用的存储引擎
  Backing Filesystem: extfs   #后端文件系统,即服务器的磁盘文件系统
  Supports d_type: true#是否支持 d_type
  Native Overlay Diff: true#是否支持差异数据存储
 Logging Driver: json-file   #日志类型
 Cgroup Driver: cgroupfs  #Cgroups 类型
 Plugins:                  #插件
  Volume: local            #卷
  Network: bridge host ipvlan macvlan null overlay # overlay 跨主机通信
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog  # 日志类型
 Swarm: inactive    #是否支持 swarm
 Runtimes: runc     #已安装的容器运行时
 Default Runtime: runc   #默认使用的容器运行时
 Init Binary: docker-init   #初始化容器的守护进程,即 pid 为 1 的进程
 containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339 #版本
 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657  #runc 版本
 init version: fec3683  #init 版本
 Security Options:   #安全选项
  apparmor     #安全模块,https://docs.docker.com/engine/security/apparmor/
  seccomp  #安全计算模块,即制容器操作,
https://docs.docker.com/engine/security/seccomp/
   Profile: default  #默认的配置文件
 Kernel Version: 4.15.0-29-generic  #宿主机内核版本
 Operating System: Ubuntu 18.04.1 LTS  #宿主机操作系统
 OSType: linux    #宿主机操作系统类型
 Architecture: x86_64   #宿主机架构
 CPUs: 1#宿主机 CPU 数量
 Total Memory: 962MiB   #宿主机总内存
 Name: ubuntu1804.wang.org #宿主机 hostname
 ID: IZHJ:WPIN:BRMC:XQUI:VVVR:UVGK:NZBM:YQXT:JDWB:33RS:45V7:SQWJ #宿主机 ID
 Docker Root Dir: /var/lib/docker  #宿主机关于docker数据的保存目录
 Debug Mode: false#server 端是否开启 debug
 Registry: https://index.docker.io/v1/  #仓库路径
 Labels:
 Experimental: false#是否测试版
 Insecure Registries:
127.0.0.0/8  : #非安全的镜像仓库
 Registry Mirrors:
  https://si7y70hh.mirror.aliyuncs.com/   #镜像仓库
 Live Restore Enabled: false#是否开启活动重启 (重启docker-daemon 不关闭容器 )
WARNING: No swap limit support  #系统警告信息 (没有开启 swap 资源限制 )

范例: 解决上述SWAP报警提示

官方文档: https://docs.docker.com/install/linux/linux-postinstall/#your-kernel-does-not-support-c group-swap-limit-capabilities

[root@ubuntu1804 ~]#docker info
......
WARNING: No swap limit support
[root@ubuntu1804 ~]# vim /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`lsb_ release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 swapaccount=1"#修改此行
[root@ubuntu1804 ~]# update-grub
[root@ubuntu1804 ~]# reboot
1.2.5.3 查看 docker0 网卡

在docker安装启动之后,默认会生成一个名称为docker0的网卡并且默认IP地址为172.17.0.1的网卡

#ubuntu18.04安装docker后网卡配置
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:34:df:91 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:df91/64 scope link
       valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
group default
    link/ether 02:42:d3:26:ed:4e brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:d3ff:fe26:ed4e/64 scope link
       valid_lft forever preferred_lft forever
#CentOS 7.6 安装docker后网卡配置
[root@centos7 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
group default qlen 1000
    link/ether 00:0c:29:ca:00:e4 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.7/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:feca:e4/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:d2:81:c2:e0 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
#CentOS 8.1 安装docker后网卡配置
[root@centos8 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:4d:ef:3e brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.18/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe4d:ef3e/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:f5:3e:65:b6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
[root@centos8 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    10000 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     10000 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     000 docker0
1.2.5.4 Docker 存储引擎

官方文档关于存储引擎的相关文档:

https://docs.docker.com/storage/storagedriver/

https://docs.docker.com/storage/storagedriver/select-storage-driver/

  • AUFS: (Advanced Mult-Layered Unification Filesystem,版本2之前旧称AnotherUnionFS)是一种 Union FS ,是文件级的存储驱动。Aufs是之前的UnionFS的重新实现,2006年由Junjiro Okajima开发

  • 所谓 UnionFS就是把不同物理位置的目录合并 mount 到同一个目录中。简单来说就是支持将不同目录挂载到一个虚拟文件系统下的。这种可以层层地叠加修改文件。无论底下有多少都是只读的, 最上系统可写的。当需要修改一个文件时, AUFS 创建该文件的一个副本,使用 CoW 将文件从只读层复制到可写进行修改,结果也保存在Docker 中,底下的只读层就是 image,可写层就是 Container

aufs 被拒绝合并到主线 Linux 。其代码被批评为"dense, unreadable, uncommented 密集、不可读、未注释"。 相反,OverlayFS被合并到 Linux 内核中。在多次尝试将 aufs 合并到主线内核失败后,作者放弃了

AUFS 是 Docker 18.06 及更早版本的首选存储驱动程序,在内核 3.13 上运行 Ubuntu 14.04 时不支持 overlay2

Overlay: 一种 Union FS 文件系统, Linux 内核 3.18 后支持

  • Overlay2: Overlay 的升级版,到目前为止,所有 Linux 发行版推荐使用的存储类型,也是docker 默认使用的存储引擎为overlay2,需要磁盘分区支持d-type功能,因此需要系统磁盘的额外支持,相对AUFS来说Overlay2 有以下优势: 更简单地设计; 从3.18开始就进入了Linux内核主线;资源消耗更少

  • devicemapper: 因为CentOS 7.2和RHEL 7.2 的之前版本内核版本不支持 overlay2,默认使用的存储驱动程序,最大数据容量只支持100GB且性能不佳,当前较新版本的CentOS 已经支持 overlay2, 因此推荐使用 overlay2,另外此存储引擎已在Docker Engine 18.09中弃用

ZFS(Sun -2005)/btrfs(Oracle-2007): 目前没有广泛使用

vfs: 用于测试环境,适用于无法使用 copy-on -writewrite 时的情况。 此存储驱动程序的性能很差,通常不建议用于生产

修改存储引擎参考文档:

https://docs.docker.com/storage/storagedriver/overlayfs-driver/

范例: 在CentOS7.2修改存储引擎

[root@centos7 ~]#vim /lib/systemd/system/docker.service
.....
ExecStart=/usr/bin/dockerd -s overlay2 -H fd:// --
containerd=/run/containerd/containerd.sock
......
#创建新的xfs分区,添加ftype特性,否则默认无法启动docker服务
[root@centos7 ~]#mkfs.xfs  -n ftype=1 /dev/sdb
[root@centos7 ~]#mount /dev/sdb /var/lib/docker
[root@centos7 ~]#systemctl daemon-reload
[root@centos7 ~]#systemctl restart docker

注意:修改存储引擎会导致所有容器丢失,所以先备份再修改

#查看Ubuntu1804的默认存储引擎
[root@ubuntu1804 ~]#docker info |grep Storage
WARNING: No swap limit support
 Storage Driver: overlay2
#查看CentOS7.6的默认存储引擎
[root@centos7 ~]#docker info |grep Storage
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
Storage Driver: overlay2

Docker官方推荐首选存储引擎为overlay2,其次为devicemapper,但是devicemapper存在使用空间方面的一些限制,虽然可以通过后期配置解决,但是官方依然推荐使用overlay2

范例: aufs 实现联合文件系统挂载

[root@ubuntu1804 ~]#cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   ramfs
nodev   bdev
nodev   proc
nodev   cpuset
nodev   cgroup
nodev   cgroup2
nodev   tmpfs
nodev   devtmpfs
nodev   configfs
nodev   debugfs
nodev   tracefs
nodev   securityfs
nodev   sockfs
nodev   dax
nodev   bpf
nodev   pipefs
nodev   hugetlbfs
nodev   devpts
    ext3
    ext2
    ext4
    squashfs
    vfat
nodev   ecryptfs
    fuseblk
nodev   fuse
nodev   fusectl
nodev   pstore
nodev   mqueue
    btrfs
nodev   autofs
nodev   rpc_pipefs
nodev   nfsd
nodev   overlay
nodev   aufs
[root@ubuntu1804 ~]#grep -i aufs /boot/config-4.15.0-29-generic
CONFIG_AUFS_FS=m
CONFIG_AUFS_BRANCH_MAX_127=y
# CONFIG_AUFS_BRANCH_MAX_511 is not set
# CONFIG_AUFS_BRANCH_MAX_1023 is not set
# CONFIG_AUFS_BRANCH_MAX_32767 is not set
CONFIG_AUFS_SBILIST=y
# CONFIG_AUFS_HNOTIFY is not set
CONFIG_AUFS_EXPORT=y
CONFIG_AUFS_INO_T_64=y
CONFIG_AUFS_XATTR=y
# CONFIG_AUFS_FHSM is not set
# CONFIG_AUFS_RDU is not set
CONFIG_AUFS_DIRREN=y
# CONFIG_AUFS_SHWH is not set
# CONFIG_AUFS_BR_RAMFS is not set
# CONFIG_AUFS_BR_FUSE is not set
CONFIG_AUFS_BR_HFSPLUS=y
CONFIG_AUFS_BDEV_LOOP=y
# CONFIG_AUFS_DEBUG is not set
[root@ubuntu1804 ~]#mkdir dir{1,2}
[root@ubuntu1804 ~]#echo here is dir1 > dir1/file1
[root@ubuntu1804 ~]#echo here is dir2 > dir2/file2
[root@ubuntu1804 ~]#mkdir /data/aufs
[root@ubuntu1804 ~]#mount -t aufs -o br=/root/dir1=ro:/root/dir2=rw none
/data/aufs
[root@ubuntu1804 ~]#ll /data/aufs/
total 16
drwxr-xr-x 4 root root 4096 Jan 2516:22 ./
drwxr-xr-x 4 root root 4096 Jan 2516:22 ../
-rw-r--r--1 root root   13 Jan 2516:22 file1
-rw-r--r--1 root root   13 Jan 2516:22 file2
[root@ubuntu1804 ~]#cat /data/aufs/file1
here is dir1
[root@ubuntu1804 ~]#cat /data/aufs/file2
here is dir2
[root@ubuntu1804 ~]#df -T
Filesystem     Type     1K-blocks    Used Available Use% Mounted on
udev           devtmpfs    46256004625600% /dev
tmpfs          tmpfs        98512102968821611% /run
/dev/sda2      ext4      477990202770244425709727% /
tmpfs          tmpfs       49255204925520% /dev/shm
tmpfs          tmpfs         5120051200% /run/lock
tmpfs          tmpfs       49255204925520% /sys/fs/cgroup
/dev/sda3      ext4      1909154045084180535881% /data
/dev/sda1      ext4        944120771128018329% /boot
tmpfs          tmpfs        985080985080% /run/user/0
none           aufs      477990202770244425709727% /data/aufs
[root@ubuntu1804 ~]#echo write to file1 >> /data/aufs/file1
-bash: /data/aufs/file1: Read-only file system
[root@ubuntu1804 ~]#echo write to file2 >> /data/aufs/file2
[root@ubuntu1804 ~]#cat /data/aufs/file1
here is dir1
[root@ubuntu1804 ~]#cat /data/aufs/file2
here is dir2
write to file2
[root@ubuntu1804 ~]#umount /data/aufs
[root@ubuntu1804 ~]#mv dir1/file1 dir1/file2
[root@ubuntu1804 ~]#cat dir1/file2
here is dir1
[root@ubuntu1804 ~]#cat dir2/file2
here is dir2
write to file2
[root@ubuntu1804 ~]#mount -t aufs -o br=/root/dir1=ro:/root/dir2=rw none
/data/aufs
[root@ubuntu1804 ~]#ls /data/aufs -l
total 4
-rw-r--r--1 root root 13 Jan 2516:22 file2
[root@ubuntu1804 ~]#cat /data/aufs/file2
here is dir1
[root@ubuntu1804 ~]#

1.3 镜像管理

1.3.1 镜像结构和原理

镜像即创建容器的模版,含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于方便和快速的创建并启动容器

镜像含里面是一层层的文件系统,叫做 Union FS(联合文件系统),联合文件系统,可以将几层目录挂载到一起(就像千层饼,洋葱头,俄罗斯套娃一样),形成一个虚拟文件系统,虚拟文件系统的目录结构就像普通 linux 的目录结构一样,镜像通过这些文件再加上宿主机的内核共同提供了一个 linux 的虚拟环境,每一层文件系统叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限,只读 (readonly)、读写(readwrite)和写出(whiteout-able),但是镜像中每一层文件系统都是只读的, 构建镜像的时候,从一个最基本的操作系统开始,每个构建提交的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层,实际上也不需要知道里面有几层,结构如下:

一个典型的 Linux文件系统由 bootfs 和 rootfs 两部分组成

bootfs(boot file system) 主要包含bootloader和kernel,bootloader主要用于引导加载 kernel,Linux 刚启动时会加载bootfs文件系统,当boot加载完成后,kernel 被加载到内存中后接管系统的控制权,bootfs 会被 umount 掉

rootfs (root file system) 包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc 等标准目录和文件, 不同的 linux 发行版(如 ubuntu 和 CentOS ) 主要在 rootfs 这一层会有所区别。

一般的镜像通常都比较小,官方提供的Ubuntu镜像只有60MB多点,而 CentOS 基础镜像也只有200MB 左右,一些其他版本的镜像甚至只有几MB,比如: busybox 才1.22MB,alpine镜像也只有5M左右。镜像直接调用宿主机的内核,镜像中只提供 rootfs,也就是只需要包括最基本的命令,配置文件和程序库等相关文件就可以了。

下图就是有两个不同的镜像在一个宿主机内核上实现不同的rootfs。

容器、镜像和父镜像关系:

范例: 查看镜像的分层结构

[root@ubuntu1804 ~]#docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
8ec398bc0356: Pull complete
a53c868fbde7: Pull complete
79daf9dd140d: Pull complete
Digest: sha256:70821e443be75ea38bdf52a974fd2271babd5875b2b1964f05025981c75a6717
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

# 查看镜像分层历史

[root@ubuntu1804 ~]#docker image  history nginx
IMAGE               CREATED             CREATED BY
       SIZE                COMMENT
0901fa9da894        9 days ago          /bin/sh -c#(nop)  CMD ["nginx" "-g"
"daemon…   0B
<missing>           9 days ago          /bin/sh -c#(nop)  STOPSIGNAL SIGTERM
        0B
<missing>           9 days ago          /bin/sh -c#(nop)  EXPOSE 80
       0B
<missing>           9 days ago          /bin/sh -c#(nop)  ENTRYPOINT ["/docker-
entr…   0B
<missing>           9 days ago          /bin/sh -c#(nop) COPY
file:0fd5fca330dcd6a7…   1.04kB
<missing>           9 days ago          /bin/sh -c#(nop) COPY
file:1d0a4127e78a26c1…   1.96kB
<missing>           9 days ago          /bin/sh -c#(nop) COPY
file:e7e183879c35719c…   1.2kB
<missing>           9 days ago          /bin/sh -cset-x     && addgroup --
system-…   63.3MB
<missing>           9 days ago          /bin/sh -c#(nop)  ENV
PKG_RELEASE=1~buster     0B
<missing>           9 days ago          /bin/sh -c#(nop)  ENV NJS_VERSION=0.4.2
       0B
<missing>           9 days ago          /bin/sh -c#(nop)  ENV
NGINX_VERSION=1.19.1     0B
<missing>           5 weeks ago         /bin/sh -c#(nop)  LABEL
maintainer=NGINX Do…   0B
<missing>           5 weeks ago         /bin/sh -c#(nop)  CMD ["bash"]
        0B
<missing>           5 weeks ago         /bin/sh -c#(nop) ADD
file:4d35f6c8bbbe6801c…   69.2MB
[root@ubuntu1804 ~]#docker inspect nginx
[
    {
"Id":
"sha256:0901fa9da894a8e9de5cb26d6749eaffb67b373dc1ff8a26c46b23b1175c913a",
"RepoTags": [
"nginx:latest"
        ],
"RepoDigests": [
"nginx@sha256:a93c8a0b0974c967aebe868a186e5c205f4d3bcb5423a56559f2f9599074bbcd"
        ],
"Parent": "",
"Comment": "",
"Created": "2020-07-10T20:26:44.624785651Z",
"Container":
"348c3ade7f4bdc0366f3f390ea4cfaebfb355ad7d621547eaf73728136d3bd2d",
"ContainerConfig": {
"Hostname": "348c3ade7f4b",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
            },
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.19.1",
"NJS_VERSION=0.4.2",
"PKG_RELEASE=1~buster"
            ],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
            ],
"ArgsEscaped": true,
"Image":
"sha256:8a6dfc8c21a1b3f3679b7755fc7869a22b5f8583778cf7835b5ee5387a73ae5e",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
            ],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-
maint@nginx.com>"
            },
"StopSignal": "SIGTERM"
        },
"DockerVersion": "18.09.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
            },
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.19.1",
"NJS_VERSION=0.4.2",
"PKG_RELEASE=1~buster"
            ],
"Cmd": [
"nginx",
"-g",
"daemon off;"
            ],
"ArgsEscaped": true,
"Image":
"sha256:8a6dfc8c21a1b3f3679b7755fc7869a22b5f8583778cf7835b5ee5387a73ae5e",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
            ],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-
maint@nginx.com>"
            },
"StopSignal": "SIGTERM"
        },
"Architecture": "amd64",
"Os": "linux",
"Size": 132484492,
"VirtualSize": 132484492,
"GraphDriver": {
"Data": {
"LowerDir":
"/var/lib/docker/overlay2/87dfa2bbff4f392e64e8a2fce11e2d9b8c3fffcfd51c6721ef0103
f7d6b525aa/diff:/var/lib/docker/overlay2/925c1a9c01939d111b3f0576608ad02a09bceea
fb6cad8dd616c24a59151bb25/diff:/var/lib/docker/overlay2/b9fd33e18d7bb7bb29b51ee3
99dfe3f21654fa4a9a086e02dcbc23f34f140c09/diff:/var/lib/docker/overlay2/35c6b8c39
68cdc21b78d4bcd6c192683b47db788db612dee04c5110037eed7af/diff",
"MergedDir":
"/var/lib/docker/overlay2/23d3c6ecee136afe7137528b0e6997a488b1f277e86c794fa9a70b
5638a5d3f9/merged",
"UpperDir":
"/var/lib/docker/overlay2/23d3c6ecee136afe7137528b0e6997a488b1f277e86c794fa9a70b
5638a5d3f9/diff",
"WorkDir":
"/var/lib/docker/overlay2/23d3c6ecee136afe7137528b0e6997a488b1f277e86c794fa9a70b
5638a5d3f9/work"
            },
"Name": "overlay2"
        },
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:13cb14c2acd34e45446a50af25cb05095a17624678dbafbcc9e26086547c1d74",
"sha256:0e32546a8af0cd04ad451d6a9d22e650e500e5da3636a32648c9f5aca96a0ff7",
"sha256:7ef35766ef7d5d3d958022405b308d5c105b41190e1b63b2037c4055c6950c9e",
"sha256:4856db5e4f59384c413c20c46cd5403a860e1b07c8fdbad24df1ffd9209d44e7",
"sha256:2808ec4a8ea71c2660284d06cf7e25354b70b58504edb46ac3e705fb7e6ea519"
            ]
        },
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]
[root@ubuntu1804 ~]#docker save nginx -o nginx.tar
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
nginx               latest              0901fa9da894        3 days ago
127MB
alpine              3.11.3              e7d92cdc71fe        7 days ago
5.59MB
centos              centos8.1.1911      470671670cac        7 days ago
237MB
busybox             latest              6d5fcfe5ff17        4 weeks ago
1.22MB
hello-world         latest              fce289e99eb9        12 months ago
1.84kB
[root@ubuntu1804 ~]#ll -h nginx.tar
-rw-------1 root root 131M Jul 2022:33 nginx.tar
[root@ubuntu1804 ~]#tar xf nginx.tar  -C /data
[root@ubuntu1804 ~]#ll /data
total 60
drwxr-xr-x  8 root root  4096 Jul 2022:34 ./
drwxr-xr-x 24 root root  4096 Jul 2016:23 ../
-rw-r--r--1 root root  7510 Jul 1104:26
0901fa9da894a8e9de5cb26d6749eaffb67b373dc1ff8a26c46b23b1175c913a.json
drwxr-xr-x  2 root root  4096 Jul 1104:26
0bb74fcd4b686412f7993916e58c26abd155fa10b10a4dc09a778e7c324c39a2/
drwxr-xr-x  2 root root  4096 Jul 1104:26
517e3239147277447b60191907bc66168963e0ce8707a6a33532f7c63a0d2f12/
drwxr-xr-x  2 root root  4096 Jul 1104:26
68c9e9da52d5a57ee196829ce4a461cc9425b0b920689da9ad547f1da13dbc9d/
drwxr-xr-x  2 root root  4096 Jul 1104:26
d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd/
drwxr-xr-x  2 root root  4096 Jul 1104:26
f4bf863ecdbb8bddb4b3bb271bdd97b067dcb6c95c56f720018abec6af190c6e/
drwx------  2 root root 16384 Mar 1809:49 lost+found/
-rw-r--r--1 root root   509 Jan  11970 manifest.json
-rw-r--r--1 root root    88 Jan  11970 repositories
[root@ubuntu1804 ~]#cat /data/manifest.json
[{"Config":"0901fa9da894a8e9de5cb26d6749eaffb67b373dc1ff8a26c46b23b1175c913a.jso
n","RepoTags":["nginx:latest"],"Layers":
["d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd/layer.tar","f
4bf863ecdbb8bddb4b3bb271bdd97b067dcb6c95c56f720018abec6af190c6e/layer.tar","517e
3239147277447b60191907bc66168963e0ce8707a6a33532f7c63a0d2f12/layer.tar","0bb74fc
d4b686412f7993916e58c26abd155fa10b10a4dc09a778e7c324c39a2/layer.tar","68c9e9da52
d5a57ee196829ce4a461cc9425b0b920689da9ad547f1da13dbc9d/layer.tar"]}]
[root@ubuntu1804 ~]#du -sh /data/*
8.0K
/data/0901fa9da894a8e9de5cb26d6749eaffb67b373dc1ff8a26c46b23b1175c913a.json
16K /data/0bb74fcd4b686412f7993916e58c26abd155fa10b10a4dc09a778e7c324c39a2
16K /data/517e3239147277447b60191907bc66168963e0ce8707a6a33532f7c63a0d2f12
16K /data/68c9e9da52d5a57ee196829ce4a461cc9425b0b920689da9ad547f1da13dbc9d
70M /data/d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd
62M /data/f4bf863ecdbb8bddb4b3bb271bdd97b067dcb6c95c56f720018abec6af190c6e
16K /data/lost+found
4.0K    /data/manifest.json
4.0K    /data/repositories
[root@ubuntu1804 ~]#cd
/data/d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd/
[root@ubuntu1804
d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd]#ls
json  layer.tar  VERSION
[root@ubuntu1804
d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd]#tar xf
layer.tar
[root@ubuntu1804
d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd]#ls
bin   dev  home  layer.tar  lib64  mnt  proc  run   srv  tmp  var
boot  etc  json  lib        media  opt  root  sbin  sys  usr  VERSION
[root@ubuntu1804
d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd]#cat etc/i
init.d/    issue      issue.net
[root@ubuntu1804
d2cf0fc540bb3be33ee7340498c41fd4fc82c6bb02b9955fca2109e599301dbd]#cat etc/issue
Debian GNU/Linux 10 \n \l

1.3.2 搜索镜像

1.3.2.1 搜索镜像 1.3.2.1.1 官方网站进行镜像的搜索

官网: http://hub.docker.com

在官方的docker 仓库中搜索指定名称的docker镜像,也会有很多三方镜像。

1.3.2.2.2 执行docker search命令进行搜索

格式如下:

Usage:  docker search [OPTIONS] TERM
Options:
-f, --filter filter   Filter output based on conditions provided
--format string   Pretty-print search using a Go template
--limit int       Max number of search results (default 25)
--no-trunc        Don't truncate output
说明:
OFFICIAL:  官方
AUTOMATED:  使用第三方docker服务来帮助编译镜像,可以在互联网上面直接拉取到镜像,减少了繁琐的
编译过程

范例:

[root@ubuntu1804 ~]#docker search centos
NAME                               DESCRIPTION
  STARS               OFFICIAL            AUTOMATED
centos
5786 [OK]
The official build of CentOS.

ansible/centos7-ansible
126

Ansible on Centos7
[OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos- …
114 [OK]
consol/centos-xfce-vnc
Centos container with"headless" VNC session…
108 [OK]
centos/mysql-57-centos7
67
MySQL5.7 SQL database server
imagine10255/centos6-lnmp-php56
57
centos6-lnmp-php56
[OK]
tutum/centos Simple CentOS docker image with SSH access
44
centos/postgresql-96-centos7
40
PostgreSQL is an advanced Object-Relational …
centos/httpd-24-centos7
29
Platformfor running Apache httpd2.4 or bui…
kinogmt/centos-ssh CentOS with SSH
29 [OK]
pivotaldata/centos-gpdb-dev
10
CentOS imagefor GPDB development. Tag names…
drecom/centos-ruby centos ruby
6 [OK]
centos/tools Docker image that has systems administration…
5 [OK]
mamohr/centos-java
3
Oracle Java8 Docker image based on Centos7
[OK]
darksheer/centos
Base Centos Image-- Updated hourly
3 [OK]
pivotaldata/centos
Base centos, freshened up a little with a Do…
3
pivotaldata/centos-mingw
2
Using the mingw toolchain to cross-compile t…
miko2u/centos6 CentOS6日本??境
2 [OK]
pivotaldata/centos-gcc-toolchain
2
CentOS with a toolchain, but unaffiliated wi…

indigo/centos-maven
Vanilla CentOS7 with Oracle Java Developmen…
1 [OK]
mcnaughton/centos-base centos base image
1 [OK]
blacklabelops/centos
1
CentOS Base Image! Built and Updates Daily!
[OK]

pivotaldata/centos6.8-dev
0

CentosOS6.8 imagefor GPDB development

pivotaldata/centos7-dev
0
CentosOS7 imagefor GPDB development
smartentry/centos centos with smartentry
0 [OK]

[root@ubuntu1804 ~]#

范例: 选择性的查找镜像

#搜索点赞100个以上的镜像
#旧语法
[root@ubuntu1804 ~]#docker search -s 100  centos
Flag --stars has been deprecated, use --filter=stars=3 instead
#新语法
[root@ubuntu1804 ~]#docker  search --filter=stars=100 centos
NAME                      DESCRIPTION                                     STARS
            OFFICIAL            AUTOMATED
centos                    The official build of CentOS.                   6096
             [OK]
ansible/centos7-ansible   Ansible on Centos7                              132
                                  [OK]
consol/centos-xfce-vnc    Centos container with "headless" VNC session…   117
                                  [OK]
jdeathe/centos-ssh        OpenSSH / Supervisor / EPEL/IUS/SCL Repos - …   115
                                  [OK]
1.3.2.2 alpine 介绍

Alpine 操作系统是一个面向安全的轻型 Linux 发行版。它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐。在保持瘦身的同时,Alpine 还提供了自己的包管理工具 apk,可以通过 ht tps://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种软件。

Alpine 由非商业组织维护的,支持广泛场景的 Linux发行版,它特别为资深/重度Linux用户而优化,关注安全,性能和资源效能。Alpine 镜像可以适用于更多常用场景,并且是一个优秀的可以适用于生产的基础系统/环境。

Alpine Docker 镜像也继承了 Alpine Linux 发行版的这些优势。相比于其他 Docker 镜像,它的容量非常小,仅仅只有 5 MB 左右(对比 Ubuntu 系列镜像接近 200 MB),且拥有非常友好的包管理机制。 官方镜像来自 docker-alpine 项目。

目前 Docker 官方已开始推荐使用 Alpine 替代之前的 Ubuntu 做为基础镜像环境。这样会带来多个好处。包括镜像下载速度加快,镜像安全性提高,主机之间的切换更方便,占用更少磁盘空间等。

下表是官方镜像的大小比较:

REPOSITORY TAG IMAGE ID VIRTUAL SIZE
busybox latest beae173ccac61.24MB
alpine latest 4e38e38c8ce04.799 MB
debian latest 4d6ce913b13084.98 MB
ubuntu latest b39b81afc8ca188.3 MB
centos latest 8efe422e6104210 MB

Alpine 官网: https://www.alpinelinux.org/ Alpine 官方仓库: https://github.com/alpinelinux

Alpine 官方镜像: https://hub.docker.com/_/alpine/

Alpine 官方镜像仓库: https://github.com/gliderlabs/docker-alpine

Alpine 阿里云的镜像仓库: https://mirrors.aliyun.com/alpine/

范例: alpine管理软件

#修改源替换成阿里源,将里面 dl-cdn.alpinelinux.org 的改成 mirrors.aliyun.com
vi /etc/apk/repositories
http://mirrors.aliyun.com/alpine/v3.8/main/
http://mirrors.aliyun.com/alpine/v3.8/community/
#更新源
apk update
#安装软件
apk add vim
apk update && apk --no-cache add gccmake openssl-dev sqlite-dev oniguruma-dev
libxml2-dev bzip2-dev libmcrypt-dev musl-dev
#删除软件
apk del openssh openntp vim

范例:

/ # apk --help
apk-tools 2.10.4, compiled for x86_64.
Installing and removing packages:
  add       Add PACKAGEs to 'world' and install (or upgrade) them, while
ensuring that all dependencies are met
  del       Remove PACKAGEs from 'world' and uninstall them
System maintenance:
  fix       Repair package or upgrade it without modifying main dependencies
  update    Update repository indexes from all remote repositories
  upgrade   Upgrade currently installed packages to match repositories
  cache     Download missing PACKAGEs to cache and/or delete unneeded files from
cache
Querying information about packages:
  info      Give detailed information about PACKAGEs or repositories
  list      List packages by PATTERN and other criteria
  dot       Generate graphviz graphs
  policy    Show repository policy for packages
Repository maintenance:
  index     Create repository index file from FILEs
  fetch     Download PACKAGEs from global repositories to a local directory
  verify    Verify package integrity and signature
  manifest  Show checksums of package contents
Use apk <command> --helpfor command-specific help.
Use apk --help--verbosefor a full command listing.
This apk has coffee making abilities.
/ # apk add  nginx
/ # apk info nginx
nginx-1.16.1-r6 description:
HTTP and reverse proxy server (stable version)
nginx-1.16.1-r6 webpage:
https://www.nginx.org/
nginx-1.16.1-r6 installed size:
1126400
~ # apk manifest nginx
sha1:d21a96358a10b731f8847e6d32799efdc2a7f421  etc/logrotate.d/nginx
sha1:50bd6d3b4f3e6b577d852f12cd6939719d2c2db5  etc/init.d/nginx
sha1:379c1e2a2a5ffb8c91a07328d4c9be2bc58799fd  etc/nginx/scgi_params
sha1:da38e2a0dded838afbe0eade6cb837ac30fd8046  etc/nginx/fastcgi_params
sha1:cc2fcdb4605dcac23d59f667889ccbdfdc6e3668  etc/nginx/uwsgi_params
sha1:cbf596ddb3433a8e0d325f3c188bec9c1bb746b3  etc/nginx/fastcgi.conf
sha1:e39dbc36680b717ec902fadc805a302f1cf62245  etc/nginx/mime.types
sha1:e9dddf20f1196bb67eef28107438b60c4060f4d3  etc/nginx/nginx.conf
sha1:7b2a4da1a14166442c10cbf9e357fa9fb53542ca  etc/nginx/conf.d/default.conf
sha1:cd7f5dc8ccdc838a2d0107511c90adfe318a81e7  etc/conf.d/nginx
sha1:05f050f6ed86c5e6b48c2d2328e81583315431be  usr/sbin/nginx
sha1:c3f02ca81f7f2c6bde3f878b3176f225c7781c7d  var/lib/nginx/modules
sha1:0510312d465b86769136983657df98c1854f0b60  var/lib/nginx/run
sha1:35db17c18ce0b9f84a3cc113c8a9e94e19f632b1  var/lib/nginx/logs
sha1:7dd71afcfb14e105e80b0c0d7fce370a28a41f0a  var/lib/nginx/html/index.html
sha1:95de71d58b37f9f74bede0e91bc381d6059fc2d7  var/lib/nginx/html/50x.html
~ # ls -l /bin
total 824
lrwxrwxrwx    1 root     root            12 Jan 1621:52 arch -> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 ash -> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 base64 -> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 bbconfig ->
/bin/busybox
-rwxr-xr-x1 root     root        841288 Jan 1510:36 busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 cat-> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 chgrp -> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 chmod-> /bin/busybox
lrwxrwxrwx    1 root     root            12 Jan 1621:52 chown-> /bin/busybox
1.3.2.3 Debian(ubuntu)系统建议安装的基础包

在很多软件官方提供的镜像都使用的是Debian(ubuntu)的系统,比如:nginx,tomcat,mysql,httpd 等,但镜像内缺少很多常用的调试工具.当需要进入容器内进行调试管理时,可以安装以下常用工具包

# apt update                #安装软件前需要先更新索引
# apt install procps        #提供top,ps,free等命令
# apt install psmisc        #提供pstree,killall等命令
# apt install iputils-ping  #提供ping命令
# apt install net-tools     #提供netstat网络工具等
# apt install iproute2      #提供ip,ss网络工具等

1.3.3 下载镜像

从 docker 仓库将镜像下载到本地,命令格式如下:

docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Options:
-a, --all-tags                Download all tagged images in the repository
--disable-content-trust   Skip image verification (default true)
--platform string         Set platform if server is multi-platform capable
-q, --quiet                   Suppress verbose output
NAME: 是镜像名,一般的形式仓库服务器:端口/项目名称/镜像名称
:TAG: 即版本号,如果不指定:TAG,则下载最新版镜像

镜像下载说明

[root@ubuntu1804 ~]#docker pull hello-world
Using default tag: latest   #默认下载最新版本
latest: Pulling from library/hello-world
1b930d010525: Pull complete  #分层下载
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
#摘要
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest  #下载的完整地址

镜像下载保存的路径:

/var/lib/docker/overlay2/镜像ID

注意: 镜像下载完成后,会自动解压缩,比官网显示的可能会大很多,如: centos8.1.1911下载时只有 70MB,下载完后显示237MB

范例: 从docker官网下载镜像

docker pull hello-world
docker pull alpine
docker pull busybox
docker pull nginx
docker pull centos
docker pull centos:centos7.7.1908
docker pull docker.io/library/mysql:5.7.30
docker pull mysql:5.6.47

范例: 下载镜像 alpine,busybox等镜像,查看下载的存放目录

[root@ubuntu1804 ~]#ls /var/lib/docker/overlay2/
l
[root@ubuntu1804 ~]#du -sh /var/lib/docker/overlay2
8.0K    /var/lib/docker/overlay2
[root@ubuntu1804 ~]#ls /var/lib/docker/overlay2/l
[root@ubuntu1804 ~]#docker pull hello-world
[root@ubuntu1804 ~]#docker pull alpine:3.11.3
3.11.3: Pulling from library/alpine
c9b1b535fdd9: Pull complete
Digest: sha256:ab00606a42621fb68f2ed6ad3c88be54397f981a7b70a79db3d1172b11c4367d
Status: Downloaded newer image for alpine:3.11.3
docker.io/library/alpine:3.11.3
[root@ubuntu1804 ~]#docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
bdbbaa22dec6: Pull complete
Digest: sha256:6915be4043561d64e0ab0f8f098dc2ac48e077fe23f488ac24b665166898115a
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
[root@ubuntu1804 ~]#docker pull centos:centos8.1.1911
centos8.1.1911: Pulling from library/centos
8a29a15cefae: Pull complete
Digest: sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
Status: Downloaded newer image for centos:centos8.1.1911
docker.io/library/centos:centos8.1.1911
[root@ubuntu1804 ~]#du -sh /var/lib/docker/overlay2/*
5.9M
/var/lib/docker/overlay2/1802616f4c8e0a0b52c839431b6faa8ac21f4bd831548dcbd46943d
3f60061fa
16K
/var/lib/docker/overlay2/5773b92e1351da5e589d0573d9f22d1ec3be1e0e98edbfcddba4b83
0f12c7be2
1.3M
/var/lib/docker/overlay2/de31641b8d2207de7f08eabb5240474a1aaccfef08b6034dcee02b9
623f8d9dc
252M
/var/lib/docker/overlay2/f41df336075611f9e358e5eaf2ebd5089920a90ba68760cdec8da03
edff362f7
20K /var/lib/docker/overlay2/l
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              3.11.3              e7d92cdc71fe        7 days ago
5.59MB
centos              centos8.1.1911      470671670cac        7 days ago
237MB
busybox             latest              6d5fcfe5ff17        4 weeks ago
1.22MB
hello-world         latest              fce289e99eb9        12 months ago
1.84kB
[root@ubuntu1804 ~]#ls -l  /var/lib/docker/overlay2/l
total 16
lrwxrwxrwx 1 root root 72 Jan 2519:51 C5ZTDYHYDTO7BQG6HX36MU6X5K ->
../de31641b8d2207de7f08eabb5240474a1aaccfef08b6034dcee02b9623f8d9dc/diff
lrwxrwxrwx 1 root root 72 Jan 2519:57 DEXHVNUGFLFJCSJAKISOHQG7JY ->
../f41df336075611f9e358e5eaf2ebd5089920a90ba68760cdec8da03edff362f7/diff
lrwxrwxrwx 1 root root 72 Jan 2519:51 KJ5IA5AUHFUEQXFKJA7UDUIA7A ->
../1802616f4c8e0a0b52c839431b6faa8ac21f4bd831548dcbd46943d3f60061fa/diff
lrwxrwxrwx 1 root root 72 Jan 2519:51 ZM3U4WDNHGJJX5DXHA5M4ZWAIW ->
../5773b92e1351da5e589d0573d9f22d1ec3be1e0e98edbfcddba4b830f12c7be2/diff

范例: 指定 TAG下载特定版本的镜像

[root@ubuntu1804 ~]#docker pull docker.io/library/mysql:5.7.30
5.7.29: Pulling from library/mysql
804555ee0376: Pull complete
c53bab458734: Pull complete
ca9d72777f90: Pull complete
2d7aad6cb96e: Pull complete
8d6ca35c7908: Pull complete
6ddae009e760: Pull complete
327ae67bbe7b: Pull complete
9e05241b7707: Pull complete
e822978df8f0: Pull complete
14ca71ed53be: Pull complete
026afe6fd35e: Pull complete
Digest: sha256:2ca675966612f34b4036bbcfa68cb049c03e34b561fba0f88954b03931823d29
Status: Downloaded newer image for mysql:5.7.30
docker.io/library/mysql:5.7.30
[root@ubuntu1804 ~]#docker pull mysql:5.6.47

范例: 指定DIGEST下载特定版本的镜像

先到 hub.docker.com查到指定版本的DIGEST

[root@ubuntu1804 ~]#docker pull
alpine@sha256:156f59dc1cbe233827642e09ed06e259ef6fa1ca9b2e29d52ae14d5e7b79d7f0
sha256:156f59dc1cbe233827642e09ed06e259ef6fa1ca9b2e29d52ae14d5e7b79d7f0: Pulling
from library/alpine
5d2415897100: Pull complete
Digest: sha256:156f59dc1cbe233827642e09ed06e259ef6fa1ca9b2e29d52ae14d5e7b79d7f0
Status: Downloaded newer image for
alpine@sha256:156f59dc1cbe233827642e09ed06e259ef6fa1ca9b2e29d52ae14d5e7b79d7f0
docker.io/library/alpine@sha256:156f59dc1cbe233827642e09ed06e259ef6fa1ca9b2e29d5
2ae14d5e7b79d7f0
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              <none>              3c791e92a856        3 weeks ago
5.57MB

1.3.4 镜像加速配置

docker 镜像官方的下载站点是: https://hub.docker.com/

从国内下载官方的镜像站点有时候会很慢,因此可以更改docker配置文件添加一个加速器,可以通过加速器达到加速下载镜像的目的

国内有许多公司都提供了docker 加速镜像,比如: 阿里云,腾讯云,网易云,以下以阿里云为例

1.3.4.1 阿里云获取加速地址

浏览器打开http://cr.console.aliyun.com,注册或登录阿里云账号,点击左侧的镜像加速器,将会得到一个专属的加速地址,而且下面有使用配置说明:

1.3.4.2 docker 镜像加速配置
1. 安装/升级Docker客户端
推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce
2. 配置镜像加速器
修改daemon配置文件/etc/docker/daemon.json来使用加速器
mkdir-p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","http://hub-
mirror.c.163.com/","https://si7y70hh.mirror.aliyuncs.com"]
}
EOF
#网易云:  http://hub-mirror.c.163.com/
#中科大:  https://docker.mirrors.ustc.edu.cn
#腾讯云:  https://mirror.ccs.tencentyun.com
#七牛云:  https://reg-mirror.qiniu.com
systemctl daemon-reload
systemctl restart docker

范例: 利用阿里云实现镜像加速

[root@ubuntu1804 ~]#docker info |tail
WARNING: the overlay storage-driver is deprecated, and will be removed in a
future release.
 ID: IZHJ:WPIN:BRMC:XQUI:VVVR:UVGK:NZBM:YQXT:JDWB:33RS:45V7:SQWJ
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
127.0.0.0/8
 Live Restore Enabled: false
[root@ubuntu1804 ~]#vim /etc/docker/daemon.json
[root@ubuntu1804 ~]#cat /etc/docker/daemon.json
{
"storage-driver": "overlay",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#docker info |tail
WARNING: the overlay storage-driver is deprecated, and will be removed in a
future release.
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
127.0.0.0/8
 Registry Mirrors:
  https://si7y70hh.mirror.aliyuncs.com/
 Live Restore Enabled: false
[root@ubuntu1804 ~]

范例: 镜像加速器

[root@ubuntu1804 ~]vim /etc/docker/daemon.json
{
"registry-mirrors" : [
"http://registry.docker-cn.com",
"http://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"
  ],
"insecure-registries" : [
"registry.docker-cn.com",
"docker.mirrors.ustc.edu.cn"
  ],
"debug" : true,
"experimental" : true
}

1.3.5 查看本地镜像

docker images 可以查看下载至本地的镜像

格式:

docker images [OPTIONS] [REPOSITORY[:TAG]]
docker image ls [OPTIONS] [REPOSITORY[:TAG]]
#常用选项:
-q, --quiet         Only show numeric IDs
-a, --all           Show all images (default hides intermediate images)
--digests       Show digests
--no-trunc      Don't truncate output
-f, --filter filter   Filter output based on conditions provided
--format string   Pretty-print images using a Go template

执行结果的显示信息说明:

REPOSITORY      #镜像所属的仓库名称
TAG             #镜像版本号(标识符),默认为latest
IMAGE ID        #镜像唯一ID标识,如果ID相同,说明是同一个镜像有多个名称
CREATED         #镜像在仓库中被创建时间
VIRTUAL SIZE    #镜像的大小

Repository仓库

由某特定的docker镜像的所有迭代版本组成的镜像仓库

  • 一个Registry中可以存在多个Repository

  • Repository可分为“顶层仓库”和“用户仓库”

  • Repository用户仓库名称一般格式为“用户名/仓库名”

  • 每个Repository仓库可以包含多个Tag(标签),每个标签对应一个镜像

范例:

[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              3.11.3              e7d92cdc71fe        7 days ago
5.59MB
centos              centos8.1.1911      470671670cac        7 days ago
237MB
busybox             latest              6d5fcfe5ff17        4 weeks ago
1.22MB
hello-world         latest              fce289e99eb9        12 months ago
1.84kB
[root@ubuntu1804 ~]#docker images -q
e7d92cdc71fe
470671670cac
6d5fcfe5ff17
fce289e99eb9
#显示完整的ImageID
[root@ubuntu1804 ~]#docker images --no-trunc
REPOSITORY          TAG                 IMAGE ID
                                 CREATED             SIZE
tomcat              9.0.37-v1
sha256:b8d669ebf99e65d5ed69378d0d53f054e7de4865d335ab7aa0a7a5508e1369f7   47
hours ago        652MB
tomcat              latest
sha256:df72227b40e1985fa5ad529b9ca6582612a41d8f1ddf3a1bea1aa2cfcfa8fb07   5 days
ago          647MB
nginx               latest
sha256:0901fa9da894a8e9de5cb26d6749eaffb67b373dc1ff8a26c46b23b1175c913a   11
days ago         132MB
ubuntu              latest
sha256:adafef2e596ef06ec2112bc5a9663c6a4f59a3dfd4243c9cabe06c8748e7f288   2
weeks ago         73.9MB
busybox             latest
sha256:c7c37e472d31c1685b48f7004fd6a64361c95965587a951692c5f298c6685998   3
weeks ago         1.22MB
alpine              latest
sha256:a24bb4013296f61e89ba57005a7b3e52274d8edd3ae2077d04395f806b63d83e   7
weeks ago         5.57MB
redis               5.0.9-alpine3.11
sha256:3661c84ee9d0f6312a076b69eb2bd112674cadb70ef7e1594c4f00193f8df08e   2
months ago        29.8MB
#只查看指定REPOSITORY的镜像
[root@ubuntu1804 ~]#docker images tomcat
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
tomcat              9.0.37-v1           b8d669ebf99e        47 hours ago
652MB
tomcat              latest              df72227b40e1        5 days ago
647MB

范例: 查看指定镜像的详细信息

[root@centos8 ~]#podman image inspect alpine
[
    {
"Id":
"e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
"Digest":
"sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45",
"RepoTags": [
"docker.io/library/alpine:latest"
        ],
"RepoDigests": [
"docker.io/library/alpine@sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c9
0e6e1297bfa1bc0c45"
        ],
"Parent": "",
"Comment": "",
"Created": "2020-01-18T01:19:37.187497623Z",
"Config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
"Cmd": [
"/bin/sh"
            ]
        },
"Version": "18.06.1-ce",
"Author": "",
"Architecture": "amd64",
"Os": "linux",
"Size": 5859847,
"VirtualSize": 5859847,
"GraphDriver": {
"Name": "overlay",
"Data": {
"MergedDir":
"/var/lib/containers/storage/overlay/5216338b40a7b96416b8b9858974bbe4acc3096ee60
acbc4dfb1ee02aecceb10/merged",
"UpperDir":
"/var/lib/containers/storage/overlay/5216338b40a7b96416b8b9858974bbe4acc3096ee60
acbc4dfb1ee02aecceb10/diff",
"WorkDir":
"/var/lib/containers/storage/overlay/5216338b40a7b96416b8b9858974bbe4acc3096ee60
acbc4dfb1ee02aecceb10/work"
            }
        },
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"
            ]
        },
"Labels": null,
"Annotations": {},
"ManifestType": "application/vnd.docker.distribution.manifest.v2+json",
"User": "",
"History": [
            {
"created": "2020-01-18T01:19:37.02673981Z",
"created_by": "/bin/sh -c #(nop) ADD
file:e69d441d729412d24675dcd33e04580885df99981cec43de8c9b24015313ff8e in / "
            },
            {
"created": "2020-01-18T01:19:37.187497623Z",
"created_by": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
"empty_layer": true
            }
        ]
    }
]

1.3.6 镜像导出

利用docker save命令可以将从本地镜像导出为一个打包 tar文件,然后复制到其他服务器进行导入使用格式:

docker save [OPTIONS] IMAGE [IMAGE...]
选项:
-o, --output string   Write to a file, instead of STDOUT
#说明:
Docker save 使用IMAGE ID导出,在导入后的镜像没有REPOSITORY和TAG,显示为<none>

常见用法:

docker save -o /path/file.tar IMAGE1 IMAGE2 ...
docker save IMAGE1 IMAGE2 ... > /path/file.tar

范例: 导出指定镜像

[root@ubuntu1804 ~]#docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
nginx latest 5ad3bd0e67a93 days ago
127MB
alpine 3.11.3 e7d92cdc71fe7 days ago
5.59MB
centos centos8.1.1911 470671670cac7 days ago
237MB
centos latest 470671670cac7 days ago
237MB
mysql 5.6.47 742f7d5a410410 days ago
302MB
mysql
435MB
5.7.29 b598110d0fff10 days ago
busybox latest 6d5fcfe5ff174 weeks ago
1.22MB
hello-world
1.84kB
latest fce289e99eb912 months ago
[root@ubuntu1804
#或者
~]#docker save mysql:5.7.30 alpine:3.11.3 -o /data/myimages.tar
[root@ubuntu1804 ~]#docker save mysql:5.7.30 alpine:3.11.3 > /data/myimages.tar
[root@ubuntu1804 ~]#scp /data/myimages.tar   10.0.0.7:/data

范例: 导出所有镜像至不同的文件中

[root@centos8 ~]#docker images | awk 'NR!=1{print $1,$2}' | while read repo tag
;do docker save   $repo:$tag -o /opt/$repo-$tag.tar ;done
[root@centos8 ~]#ls /opt/*.tar
/opt/alpine-3.13.5.tar  /opt/busybox-latest.tar  /opt/centos-centos8.3.2011.tar
/opt/centos-latest.tar  /opt/ubuntu-latest.tar
[root@ubuntu2004 ~]#for i in `docker image ls --format "{{.Repository}}:
{{.Tag}}"`;do docker save $i -o `echo $i|cut -d: -f1`.tar ;done

范例:导出所有镜像到一个打包文件

#方法1: 使用image ID导出镜像,在导入后的镜像没有REPOSITORY和TAG,显示为<none>
[root@ubuntu1804 ~]#docker save `docker images -qa` -o all.tar
#方法2:将所有镜像导入到一个文件中,此方法导入后可以看REPOSITORY和TAG
[root@ubuntu1804 ~]#docker save `docker images | awk 'NR!=1{print $1":"$2}'` -o
all.tar
#方法3:将所有镜像导入到一个文件中,此方法导入后可以看REPOSITORY和TAG
[root@centos8 ~]#docker image save `docker image ls --format "{{.Repository}}:
{{.Tag}}"` -o all.tar

1.3.7 镜像导入

利用docker load命令可以将镜像导出的打包或压缩文件再导入

格式:

docker load [OPTIONS]
#选项
-i, --input string   Read from tar archive file, instead of STDIN
-q, --quiet          Suppress the load output

常见用法:

docker load -i /path/file.tar
docker load < /path/file.tar

范例: 镜像导入

[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@centos7 ~]#docker load -i /data/myimages.tar
#或者
[root@centos7 ~]#docker load < /data/myimages.tar
[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              3.11.3              e7d92cdc71fe        7 days ago
5.59MB
mysql               5.7.29              b598110d0fff        10 days ago
435MB

范例: 一次导出多个镜像

[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              latest              e7d92cdc71fe        7 days ago
5.59MB
busybox             latest              6d5fcfe5ff17        4 weeks ago
1.22MB
[root@ubuntu1804 ~]#docker save busybox alpine > /all.tar
[root@ubuntu1804 ~]#ll -h /opt/all.tar
-rw-r--r--1 root root 7.0M Jan 2522:12 /opt/all.tar
[root@ubuntu1804 ~]#docker rmi -f `docker images -q`
Untagged: alpine:latest
Deleted: sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a
Deleted: sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10
Untagged: busybox:latest
Deleted: sha256:6d5fcfe5ff170471fcc3c8b47631d6d71202a1fd44cf3c147e50c8de21cf0648
Deleted: sha256:195be5f8be1df6709dafbba7ce48f2eee785ab7775b88e0c115d8205407265c5
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@ubuntu1804 ~]#docker load -i /opt/all.tar
5216338b40a7: Loading layer
[==================================================>]  5.857MB/5.857MB
Loaded image: alpine:latest
195be5f8be1d: Loading layer
[==================================================>]  1.437MB/1.437MB
Loaded image: busybox:latest
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              latest              e7d92cdc71fe        7 days ago
5.59MB
busybox             latest              6d5fcfe5ff17        4 weeks ago
1.22MB

面试题: 将一台主机的所有镜像传到另一台主机

#方法1: 使用image ID导出镜像,在导入后的镜像没有REPOSITORY和TAG,显示为<none>
[root@ubuntu1804 ~]#docker save `docker images -qa` -o all.tar
[root@ubuntu1804 ~]#scp all.tar 10.0.0.7:
[root@centos7 ~]#docker load -i all.tar
[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
<none>              <none>              a77dce18d0ec        10 days ago
1.24MB
<none>              <none>              389fef711851        3 weeks ago
5.58MB
<none>              <none>              300e315adb2f        4 weeks ago
209MB
<none>              <none>              f643c72bc252        6 weeks ago
72.9MB
#方法2:将所有镜像导入到一个文件中,此方法导入后可以看REPOSITORY和TAG
[root@ubuntu1804 ~]#docker save `docker images | awk 'NR!=1{print $1":"$2}'` -o
backup.tar
[root@ubuntu1804 ~]#scp backup.tar 10.0.0.200:
root@ubuntu2004:~# docker load -i backup.tar
root@ubuntu2004:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox uclibc a77dce18d0ec10 days ago1.24MB
alpine latest 389fef7118513 weeks ago5.58MB
centos latest 300e315adb2f4 weeks ago 209MB
ubuntu latest f643c72bc2526 weeks ago72.9MB
#方法3:将所有镜像导入到一个文件中,此方法导入后可以看REPOSITORY和TAG
[root@centos8 ~]#docker image save `docker image ls --format "{{.Repository}}:
{{.Tag}}"` -o all.tar
[root@centos8 ~]#scp all.tar  10.0.0.100:/data
[root@ubuntu1804 ~]#docker load -i /data/all.tar
[root@ubuntu1804 ~]#docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox uclibc a77dce18d0ec10 days ago1.24MB
alpine latest 389fef7118513 weeks ago5.58MB
centos latest 300e315adb2f4 weeks ago 209MB
ubuntu latest f643c72bc2526 weeks ago72.9MB

1.3.8 删除镜像

docker rmi 命令可以删除本地镜像

格式

docker rmi [OPTIONS] IMAGE [IMAGE...]
docker image rm [OPTIONS] IMAGE [IMAGE...]
#选项:
-f, --force      Force removal of the image,如果有容器正在使用,只是虚拟删除,空间并不释
放,但镜像列表不再显示
--no-prune   Do not delete untagged parents
#默认只清除dangling的镜像,dangling images表示TAG为<none>的镜像,其它不再使用的镜像不清理
docker image prune
#清除dangling以及不再使用的镜像,建议定期清理
docker image prune -a-f

范例: 删除指定镜像

[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              3.11.3              e7d92cdc71fe        7 days ago
5.59MB
mysql               5.7.29              b598110d0fff        10 days ago
435MB
[root@centos7 ~]#docker rmi b59811
Untagged: mysql:5.7.30
Deleted: sha256:b598110d0fffc42862269a25d8767dd95764d0740f318fd6c0a097f8a22de5bf
Deleted: sha256:908aaab4c4b8d0cbbc68c96a0e3820aa74fd1dee5499e2ca326bc8fd7312f689
Deleted: sha256:e2f2e83f295186b00e3c0d119ef3204b509d552972694e34cee7c1675d157b8a
Deleted: sha256:99b4e48b1be76f50741db02a38c783bf698b1b76808cc6bb5e3fdd65ee2897c6
Deleted: sha256:79c1efa7bde3ac754af64779452ca913fa1f281b44c9dbad25cc322a51ac69b1
Deleted: sha256:5f7c68324b959d2c806db18d02f153bc810f9842722415e077351bc834cc8578
Deleted: sha256:338fc0cd3fb4b87a2b83d274e8fbf475fbde19947c4ac5c5eb6e981a6fb0e8f0
Deleted: sha256:f7a4ccab931f1d1e861961eb951a7806d91ccb375e737fe1f84282f6bbafd2be
Deleted: sha256:f388e1092f8fb931a3cd07a7381bd9707d19526ff81f8b624e932f4919c27a3e
Deleted: sha256:e209b7a884b4d2e9d56bbac40ced48f2caa6a19e7ad6eb6dd20ff754f3af2c5d
Deleted: sha256:2401cf11c5455d505ef49657afcc709197ffcdfc9bd732508e9b62578a30b3a5
Deleted: sha256:814c70fdae62bc26c603bfae861f00fb1c77fc0b1ee8d565717846f4df24ae5d
[root@centos7 ~]#docker rmi alpine:3.11.3
Untagged: alpine:3.11.3
Deleted: sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a
Deleted: sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10
[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE

范例: 删除多个镜像

[root@ubuntu1804 ~]#docker rmi nginx tomcat

范例: 强制删除正在使用的镜像,旧版中也会删除对应的容器,新版不允许删除正在占用镜像的容器

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE                   COMMAND                  CREATED
        STATUS                        PORTS                     NAMES
b5a0d2e1e1d0        centos:centos8.1.1911   "bash"41 minutes
ago      Up 41 minutes                                           jolly_burnell
[root@ubuntu1804 ~]#docker rmi centos:centos8.1.1911
Error response from daemon: conflict: unable to remove repository reference
"centos:centos8.1.1911" (must force) - container b5a0d2e1e1d0 is using its
referenced image 470671670cac
[root@ubuntu1804 ~]#docker rmi -f centos:centos8.1.1911
Untagged: centos:centos8.1.1911
Untagged:
centos@sha256:fe8d824220415eed5477b63addf40fb06c3b049404242b31982106ac204f6700
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                        PORTS                     NAMES
[root@ubuntu1804 ~]#

范例: 删除所有镜像

[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
<none>              <none>              470671670cac        7 days ago
237MB
mysql               5.6.47              742f7d5a4104        10 days ago
302MB
[root@ubuntu1804 ~]#docker rmi  -f `docker images -q`
Deleted: sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee
Deleted: sha256:0683de2821778aa9546bf3d3e6944df779daba1582631b7ea3517bb36f9e4007
Untagged: mysql:5.6.47
Untagged:
mysql@sha256:9527bae58991a173ad7d41c8309887a69cb8bd178234386acb28b51169d0b30e
Deleted: sha256:742f7d5a4104969fcac8054cf9201f5656096f0a58d10947a4a41a8e1d7d9f91
Deleted: sha256:62530ddc9fe5f85609da4397d9e0a88b422d15dbc42664d7477d1deccb51a0d9
Deleted: sha256:41309d62590858b6375bd3c4e9d07bd73e4ea5062343a81641453033424e7aba
Deleted: sha256:43cb5cbfcce71f7fdd80b121aa4d0c5eea9ed0bfcf4a2a0e55a8c5ddb78d4368
Deleted: sha256:56806995b55c0e80ee0daec20f32f8293a3d8ccf151895cd1767a1d27eab1977
Deleted: sha256:7dab204c1f667de5090d809019fab7d6e2323e371407b38e8d311ba458009234
Deleted: sha256:1a7c2d06fdee90c4b06a55793f9e45120a82ff476e0fea5618efd8a268f7d303
Deleted: sha256:f7a4ccab931f1d1e861961eb951a7806d91ccb375e737fe1f84282f6bbafd2be
Deleted: sha256:f388e1092f8fb931a3cd07a7381bd9707d19526ff81f8b624e932f4919c27a3e
Deleted: sha256:e209b7a884b4d2e9d56bbac40ced48f2caa6a19e7ad6eb6dd20ff754f3af2c5d
Deleted: sha256:2401cf11c5455d505ef49657afcc709197ffcdfc9bd732508e9b62578a30b3a5
Deleted: sha256:814c70fdae62bc26c603bfae861f00fb1c77fc0b1ee8d565717846f4df24ae5d
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE

范例: 清除dangling和不再使用的镜像

[root@ubuntu1804 ~]#docker image prune -a -f

1.3.9 镜像打标签

docker tag 可以给镜像打标签,类似于起别名,但通常要遵守一定的命名规范,才可以上传到指定的仓库格式

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
#TARGET_IMAGE[:TAG]格式一般形式
仓库主机FQDN或IP[:端口]/项目名(或用户名)/image名字:版本
#阿里云
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/wangxiaochun/nginx:[镜像版
本号]
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/wangxiaochun/ubutnu:[镜像版
本号]

TAG默认为latest

范例:

[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              latest              e7d92cdc71fe        11 days ago
5.59MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
[root@ubuntu1804 ~]#docker tag  alpine alpine:3.11
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              3.11                e7d92cdc71fe        11 days ago
5.59MB
alpine              latest              e7d92cdc71fe        11 days ago
5.59MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB

总结: 企业使用镜像及常见操作: 搜索、下载、导出、导入、删除

命令总结:

docker search centos
docker pull alpine
docker images
docker save > /opt/centos.tar #centos #导出镜像
docker load -i /opt/centos.tar  #导入本地镜像
docker rmi 镜像ID/镜像名称#删除指定ID的镜像,此镜像对应容器正启动镜像不能被删除,除非将容器
全部关闭

1.4 容器操作基础命令

容器生命周期

容器相关命令

[root@ubuntu2004 ~]#docker container --help
Usage:  docker container COMMAND
Manage containers
Commands:
  attach      Attach local standard input, output, and error streams to a running
container
  commit      Create a new image from a container's changes
cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
diff        Inspect changes to files or directories on a container's
filesystem
  exec        Run a command in a running container
export      Export a container's filesystem as a tar archive
  inspect     Display detailed information on one or more containers
kill        Kill one or more running containers
  logs        Fetch the logs of a container
ls          List containers
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  prune       Remove all stopped containers
  rename      Rename a container
restart     Restart one or more containers
rm          Remove one or more containers
  run         Run a command in a new container
start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
stop        Stop one or more running containers
top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit
codes
Run 'docker container COMMAND --help'for more information on a command.
[root@ubuntu1804 ~]#docker container
Usage:  docker container COMMAND
Manage containers
Commands:
  attach      Attach local standard input, output, and error streams to a running
container
  commit      Create a new image from a container's changes
cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
diff        Inspect changes to files or directories on a container's
filesystem
  exec        Run a command in a running container
export      Export a container's filesystem as a tar archive
  inspect     Display detailed information on one or more containers
kill        Kill one or more running containers
  logs        Fetch the logs of a container
ls          List containers
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  prune       Remove all stopped containers
  rename      Rename a container
restart     Restart one or more containers
rm          Remove one or more containers
  run         Run a command in a new container
start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
stop        Stop one or more running containers
top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit
codes
Run 'docker container COMMAND --help'for more information on a command.

1.4.1 启动容器

docker run 可以启动容器,进入到容器,并随机生成容器ID和名称

1.4.1.1 启动第一个容器

范例: 运行docker 的 hello world

[root@centos8 ~]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:

1. The Docker client contacted the Docker daemon.

2. The Docker daemon pulled the "hello-world" image from the Docker Hub.

(amd64)

3. The Docker daemon created a new container from that image which runs the

  • executable that produces the output you are currently reading.

4. The Docker daemon streamed that output to the Docker client, which sent it

to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/
For more examples and ideas, visit:
 https://docs.docker.com/get-started/
[root@centos8 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
hello-world         latest              fce289e99eb9        12 months ago
1.84kB
[root@centos8 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                      PORTS               NAMES
7f53a2a74edc        hello-world         "/hello"21 seconds ago
Exited (0) 19 seconds ago                     nifty_yalow
1.4.1.2 启动容器的流程

1.4.1.3 启动容器用法

帮助: man docker-run

命令格式:

docker run [选项]  [镜像名]  [shell命令] [参数]
#选项:
-i, --interactive    Keep STDIN open even if not attached,通常和-t一起使用
-t, --tty分配pseudo-TTY,通常和-i一起使用,注意对应的容器必须运行shell才支持进
入
-d, --detach         Run container in background and print container ID,台后运行,
默认前台
--name string        Assign a name to the container
--h, --hostname string  Container host name
--rm                 Automatically remove the container when it exits
-p, --publish list   Publish a container's port(s) to the host
-P, --publish-all    Publish all exposed ports to random ports
--dns list           Set custom DNS servers
--entrypoint string  Overwrite the default ENTRYPOINT of the image
--restart policy
--privileged         Give extended privileges to container
-e, --env=[]         Set environment variables
--env-file=[]        Read in a line delimited file of environment variables

--restart 可以指定四种不同的policy

policy 说明
no Default is no,Do not automatically restart the container when it exits.
on-
failure[:max-
retries]
on-failure[:max-retries] Restart only if the container exits with a non-zero
exit status. Optionally, limit the number of restart retries the Docker
daemon attempts.
always Always restart the container regardless of the exit status. When you specify
always, the Docker daemon will try to restart the container indefinitely. The
container will also always start on daemon startup, regardless of the
current state of the container.利用此项可以实现开机自动启动容器,如果用
docker stop或kill容器不会再自动启动
unless-
stopped
Always restart the container regardless of the exit status, but do not start it
on daemon startup if the container has been put to a stopped state before.
和always不同点只是开机不自动启动容器

注意: 容器启动后,如果容器内没有前台运行的进程,将自动退出停止

从容器内退出,并停止容器

 exit

从容器内退出,且容器不停止

同时按三个键,ctrl+p+q

范例: 运行容器

#启动容器时会自动随机字符作为容器名
[root@ubuntu1804 ~]#docker run  alpine
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                     PORTS               NAMES
95967eaefd6a        alpine              "/bin/sh"8 seconds ago
Exited (0) 6 seconds ago                       confident_elion

范例: 一次性运行容器中命令

#启动的容器在执行完shell命令就退出,用于测试
[root@ubuntu1804 ~]#docker run  busybox echo "Hello laowang"
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
91f30d776fb2: Pull complete
Digest: sha256:9ddee63a712cea977267342e8750ecbc60d3aab25f04ceacfa795e6fce341793
Status: Downloaded newer image for busybox:latest
Hello laowang
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                      PORTS               NAMES
7873aed1b5dd        busybox             "echo 'Hello laowang'"19 seconds ago
     Exited (0) 18 seconds ago                       pedantic_varahamihira

范例: 指定容器名称

#注意每个容器的名称要唯一
[root@ubuntu1804 ~]#docker run --name a1 alpine
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                     PORTS               NAMES
dd06368a4f56        alpine              "/bin/sh"2 minutes ago
Exited (0) 8 seconds ago                       a1

范例: 运行交互式容器并退出

[root@ubuntu1804 ~]#docker run -it docker.io/busybox  sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
bdbbaa22dec6: Pull complete
Digest: sha256:6915be4043561d64e0ab0f8f098dc2ac48e077fe23f488ac24b665166898115a
Status: Downloaded newer image for busybox:latest
/ # exit
#用exit退出后容器也停止
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                    PORTS               NAMES
cd8c2a7f39d5        busybox             "sh"8 seconds ago
Exited (0) 1 second ago                       vigorous_leakey
[root@ubuntu1804 ~]#docker run -it docker.io/busybox  sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
bdbbaa22dec6: Pull complete
Digest: sha256:6915be4043561d64e0ab0f8f098dc2ac48e077fe23f488ac24b665166898115a
Status: Downloaded newer image for busybox:latest
/ #同时按三个键:ctrl+p+q
#用同时按三个键ctrl+p+q退出后容器不会停止
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                    PORTS               NAMES
cd8c2a7f39d5        busybox             "sh"8 seconds ago
Up 10 seconds       silly_villani

范例: 设置容器内的主机名

[root@ubuntu1804 ~]#docker run -it --name a1 -h a1.wang.org alpine
/ # hostname
a1.wang.org
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  a1.wang.org a1
/ # cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.
nameserver 180.76.76.76
nameserver 223.6.6.6
search wangxiaochun.com wang.org

范例: 一次性运行容器,退出后立即删除,用于测试

[root@ubuntu1804 ~]#docker run  --rm  alpine cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES

范例: 创建容器后直接进入并退出

退出两种方式:

exit 容器也停止

按ctrl+p+q 容器不停止

#,执行exit退出后容器关闭
[root@ubuntu1804 ~]#docker run -it --name alpine2 alpine
/ # cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
/ # exit  #退出容器,容器也停止运行
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                      PORTS               NAMES
6d64f47a83e6        alpine              "/bin/sh"13 seconds ago
Exited (0) 6 seconds ago                        alpine2
edd2ac2690e6        alpine              "/bin/sh"52 seconds ago
Exited (0) 51 seconds ago                       alpine1
[root@ubuntu1804 ~]#docker run -it --name alpine3 alpine
#同时按ctrl+p+q 三个键退出后,容器不停止
/ # [root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                          PORTS               NAMES
df428caf7128        alpine              "/bin/sh"8 seconds ago
Up 7 seconds                                        alpine3
6d64f47a83e6        alpine              "/bin/sh"26 seconds ago
Exited (0) 20 seconds ago                           alpine2
edd2ac2690e6        alpine              "/bin/sh"           About a minute ago
Exited (0) About a minute ago                       alpine1

什么是守护式容器:

能够长期运行

无需交互式会话

适合运行应用程序和服务

范例: 启动前台守护式容器

[root@ubuntu1804 ~]#docker run nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
6ec8c9369e08: Pull complete
d3cb09a117e5: Pull complete
7ef2f1459687: Pull complete
e4d1bf8c9482: Pull complete
795301d236d7: Pull complete
Digest: sha256:0e188877aa60537d1a1c6484b8c3929cfe09988145327ee47e8e91ddf6f76f5c
Status: Downloaded newer image for nginx:latest
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to
perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-
default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of
/etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in
/etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-
templates.sh
/docker-entrypoint.sh: Configuration complete; ready forstart up
172.17.0.1 -- [28/Jul/2020:13:09:19 +0000] "GET / HTTP/1.1"200612"-"
"curl/7.58.0""-"
172.17.0.4 -- [28/Jul/2020:13:12:49 +0000] "GET / HTTP/1.1"200612"-""Wget"
"-"
[root@ubuntu1804 ~]#docker run --rm --name b1 busybox  wget -qO - 172.17.0.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

范例: 启动后台守护式容器

[root@ubuntu1804 ~]#docker run -d nginx
888685a2487cf8150d264cb3086f78d0c3bddeb07b8ea9786aa3a564157a4cb8
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
888685a2487c        nginx               "/docker-entrypoint.…"8 seconds ago
    Up 6 seconds        80/tcp              busy_goodall
#有些容器后台启动不会持续运行
[root@ubuntu1804 ~]#docker run -d --name alpine4 alpine
3a05bbf66dac8a6ac9829c876bdb5fcb70832bf4a2898d68f6979cd8e8c517cb
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                          PORTS               NAMES
3a05bbf66dac        alpine              "/bin/sh"3 seconds ago
Exited (0) 2 seconds ago                            alpine4
df428caf7128        alpine              "/bin/sh"30 seconds ago
Up 28 seconds                                       alpine3
6d64f47a83e6        alpine              "/bin/sh"48 seconds ago
Exited (0) 41 seconds ago                           alpine2
edd2ac2690e6        alpine              "/bin/sh"           About a minute ago
Exited (0) About a minute ago                       alpine1
[root@ubuntu1804 ~]#docker run -td --name alpine5 alpine
868b33da850cfcc7db8b84150fb9c7686b577889f10425bb4c5e17f28cf68a29
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                          PORTS               NAMES
868b33da850c        alpine              "/bin/sh"2 seconds ago
Up 1 second                                         alpine5
3a05bbf66dac        alpine              "/bin/sh"23 seconds ago
Exited (0) 23 seconds ago                           alpine4
df428caf7128        alpine              "/bin/sh"50 seconds ago
Up 49 seconds                                       alpine3
6d64f47a83e6        alpine              "/bin/sh"           About a minute ago
Exited (0) About a minute ago                       alpine2
edd2ac2690e6        alpine              "/bin/sh"           About a minute ago
Exited (0) About a minute ago                       alpine1
[root@ubuntu1804 ~]#

范例: 开机自动运行容器

# 默认容器不会自动启动

[root@ubuntu1804 ~]#docker run -d --name nginx  -p 80:80  nginx
bce473b8b1d2f728847cdc32b664cca1bd7578bf7bdac850b501e2e5557a718a
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED
      STATUS              PORTS                                            NAMES
bce473b8b1d2        nginx                 "nginx -g 'daemon of…"3 seconds ago
      Up 2 seconds        0.0.0.0:80->80/tcp
[root@ubuntu1804 ~]#reboot
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE       COMMAND     CREATED    STATUS       PORTS
NAMES

# 设置容器总是运行

[root@ubuntu1804 ~]#docker run -d --name nginx --restart=always -p 80:80  nginx
[root@ubuntu1804 ~]#reboot
[root@ubuntu1804 ~]#docker ps
CONTAINER ID   IMAGE        COMMAND     CREATED        STATUS      PORTS
NAMES
dbdba90076e1 nginx"nginx -g 'daemon of…"  About a minute agoUp 49
seconds0.0.0.0:80->80/tcp   nginx

--privileged 选项

大约在0.6版,--privileged 选项被引入docker。使用该参数,container内的root拥有真正的root权限。 否则,container内的root只是外部的一个普通用户权限。privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。甚至允许你在docker容器中启动docker容器。

范例:使用--privileged 让容器获取 root 权限

[root@ubuntu2004 ~]#docker run -it  --rm rockylinux bash
[root@59867b9f0d87 /]#  cat /proc/sys/net/ipv4/ip_forward
1
[root@59867b9f0d87 /]# echo 0 >  /proc/sys/net/ipv4/ip_forward
bash: /proc/sys/net/ipv4/ip_forward: Read-only file system
[root@ubuntu2004 ~]#docker run -it --privileged  --rm rockylinux bash
[root@ee475e79a2be /]#  cat /proc/sys/net/ipv4/ip_forward
1
[root@ee475e79a2be /]# echo 0 > /proc/sys/net/ipv4/ip_forward
[root@ee475e79a2be /]#  cat /proc/sys/net/ipv4/ip_forward
0

范例: 使用--privileged 让容器获取 root 权限

[root@centos8 ~]#podman run -it   centos
[root@382ab09932a7 /]#cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
[root@382ab09932a7 /]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  200G  0 disk
|-sda1   8:1    0    1G  0 part
|-sda2   8:2    0  100G  0 part
|-sda3   8:3    0   50G  0 part
|-sda4   8:4    0    1K  0 part
`-sda5   8:5    0    2G  0 part [SWAP]
sr0     11:0    1    7G  0 rom
[root@382ab09932a7 /]# mount /dev/sda3 /mnt
mount: /mnt: permission denied.
[root@382ab09932a7 /]# exit
exit
#利用--privileged 选项运行容器
[root@centos8 ~]#podman run -it --privileged   centos
echo0 >  /proc/sys/net/ipv4/ip_forward
#可以看到宿主机的设备
[root@a6391a8f82e3 /]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  200G  0 disk
|-sda1   8:1    0    1G  0 part
|-sda2   8:2    0  100G  0 part
|-sda3   8:3    0   50G  0 part
|-sda4   8:4    0    1K  0 part
`-sda5   8:5    0    2G  0 part [SWAP]
sr0     11:0    1    7G  0 rom
[root@a6391a8f82e3 /]# df
Filesystem     1K-blocks    Used Available Use% Mounted on
overlay        10480640027548321020515683% /
tmpfs              655360655360% /dev
tmpfs             40809258924022002% /etc/hosts
shm                640000640000% /dev/shm
tmpfs             40809204080920% /sys/fs/cgroup
[root@a6391a8f82e3 /]# mount /dev/sda3 /mnt
[root@a6391a8f82e3 /]# df
Filesystem     1K-blocks    Used Available Use% Mounted on
overlay        10480640027546321020517683% /
tmpfs              655360655360% /dev
tmpfs             40809258924022002% /etc/hosts
shm                640000640000% /dev/shm
tmpfs             40809204080920% /sys/fs/cgroup
/dev/sda3       52403200619068517841322% /mnt
[root@a6391a8f82e3 /]# touch /mnt/containter.txt
[root@a6391a8f82e3 /]# echo container data > /mnt/containter.txt
[root@a6391a8f82e3 /]# cat  /mnt/containter.txt
container data
[root@a6391a8f82e3 /]#
#在宿主机查看是否生成文件
[root@centos8 ~]#lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  200G  0 disk
├─sda1   8:1    0    1G  0 part /boot
├─sda2   8:2    0  100G  0 part /
├─sda3   8:3    0   50G  0 part /data
├─sda4   8:4    0    1K  0 part
└─sda5   8:5    0    2G  0 part [SWAP]
sr0     11:0    1    7G  0 rom
[root@centos8 ~]#ll /data/containter.txt
-rw-r--r--1 root root 25 Feb 2912:26 /data/containter.txt
[root@centos8 ~]#cat /data/containter.txt
container data
[root@centos8 ~]#echo host data >> /data/containter.txt
[root@centos8 ~]#cat /data/containter.txt
container data
host data
#在容器内可看文件是否发生变化
[root@a6391a8f82e3 /]# cat  /mnt/containter.txt
container data
host data

范例: 运行docker官方文档容器

[root@centos8 ~]#podman run -it -d -p 4000:4000 docs/docker.github.io:latest
[root@centos8 ~]#podman images docs/docker.github.io
REPOSITORY                        TAG      IMAGE ID       CREATED      SIZE
docker.io/docs/docker.github.io   latest   ffd9131eeee7   2 days ago   1.99 GB
#用浏览器访问http://localhost:4000/可以看到下面docker文档资料

1.4.2 查看容器信息

1.4.2.1 显示当前存在容器

格式

docker ps [OPTIONS]
docker container ls [OPTIONS]
选项:
-a, --all             Show all containers (default shows just running)
-q, --quiet           Only display numeric IDs
-s, --size            Display total file sizes
-f, --filter filter   Filter output based on conditions provided
-l, --latest          Show the latest created container (includes all states)
-n, --last int        Show n last created containers (includes all states)
(default -1)

范例:

#显示运行的容器
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
d7ece7f62532        centos              "/bin/bash"23 seconds ago
Up 22 seconds                           ecstatic_franklin
#显示全部容器,包括退出状态的容器
[root@ubuntu1804 ~]#docker ps  -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                     PORTS               NAMES
d7ece7f62532        centos              "/bin/bash"27 seconds ago
     Up 26 seconds                                  ecstatic_franklin
dcdf71d17177        busybox             "/bin/echo 'hello wo…"8 minutes ago
    Exited (0) 8 minutes ago                       cool_jepsen
#只显示容器ID
[root@ubuntu1804 ~]#docker ps  -a -q
d7ece7f62532
dcdf71d17177
#显示容器大小
[root@ubuntu1804 ~]#docker ps  -a -s
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                     PORTS               NAMES               SIZE
d7ece7f62532        centos              "/bin/bash"51 seconds ago
     Up 50 seconds                                  ecstatic_franklin   0B
(virtual 237MB)
dcdf71d17177        busybox             "/bin/echo 'hello wo…"8 minutes ago
    Exited (0) 8 minutes ago                       cool_jepsen         0B
(virtual 1.22MB)
[root@ubuntu1804 ~]
#显示最新创建的容器(停止的容器也能显示)
[root@ubuntu1804 ~]#docker ps  -l

范例: 显示指定状态的容器

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                        PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"19 minutes ago
     Exited (137) 11 minutes ago                       nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"19 minutes ago
     Up 2 minutes                  80/tcp              nginx1
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
1f3f82995e05        nginx               "nginx -g 'daemon of…"19 minutes ago
     Up 2 minutes        80/tcp              nginx1
#查看退出状态的容器
[root@ubuntu1804 ~]#docker ps  -f 'status=exited'
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                        PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"19 minutes ago
     Exited (137) 11 minutes ago                       nginx2
#只显示运行的容器
[root@ubuntu2004 ~]#docker ps  -f 'status=running'
1.4.2.2 查看容器内的进程
docker top CONTAINER [ps OPTIONS]

范例:

[root@ubuntu1804 ~]#docker run -d  httpd
db144f1978148242dc20bd0be951628f1c00371b2c69dee53d84469c52995d8f
[root@ubuntu1804 ~]#docker top db144f19
UID       PID   PPID  C   STIME TTY   TIME     CMD
root      98219797322:02 ?     00:00:00 httpd -DFOREGROUND
daemon    98729821022:02 ?     00:00:00 httpd -DFOREGROUND
daemon    98739821022:02 ?     00:00:00 httpd -DFOREGROUND
daemon    98749821022:02 ?     00:00:00 httpd -DFOREGROUND
[root@ubuntu1804 ~]#docker run -d  alpine /bin/sh -c 'i=1;while true;do echo
hello$i;let i++;sleep 1;done'
9997053f9766d4adf709d46161d7ec6739eacafbe8d4721133874b89112ad1a6
[root@ubuntu1804 ~]#docker top 9997
UID                 PID                 PPID                C
STIME               TTY                 TIME                CMD
root                1002399973
22:03               ?                   00:00:00            /bin/sh -ci=1;while
true;do echo hello$i;let i++;sleep 1;done
root                10074100230
22:03               ?                   00:00:00            sleep1
[root@ubuntu1804 ~]#
1.4.2.3 查看容器资源使用情况
docker stats [OPTIONS] [CONTAINER...]
Display a live stream of container(s) resource usage statistics
Options:
-a, --all             Show all containers (default shows just running)
--format string   Pretty-print images using a Go template
--no-stream       Disable streaming stats and only pull the first result
--no-trunc        Do not truncate output

范例:

[root@ubuntu1804 ~]#docker stats 251c7c7cf2aa
CONTAINER ID  NAME  CPU %  MEM USAGE / LIMIT     MEM %  NET I/O    BLOCK I/O
PIDS
251c7c7cf2aa  busy_l0.00%  3.742MiB / 1.924GiB   0.19%  1.29kB / 0B0B / 8.19kB
2
CONTAINER ID  NAME  CPU %  MEM USAGE / LIMIT     MEM %  NET I/O    BLOCK I/O
PIDS
251c7c7cf2aa  busy_l0.00%  3.742MiB / 1.924GiB   0.19%  1.29kB / 0B0B / 8.19kB
2
#默认启动elasticsearch会使用较多的内存
[root@ubuntu1804 ~]#docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300
-e "discovery.type=single-node" elasticsearch:7.6.2
[root@ubuntu1804 ~]#curl 10.0.0.100:9200
{
"name" : "29282e91d773",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "w5lp_XmITliWa2Yc-XwJFw",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
"tagline" : "You Know, for Search"
}
#查看所有容器
[root@ubuntu1804 ~]#docker stats
CONTAINER ID NAME   CPU %   MEM USAGE / LIMIT MEM % NET I/O  BLOCK I/O      PIDS
5e470e7970f6 suspi  0.00%   3.992MiB / 1.924Gi0.20% 656B / 0B9.2MB / 8.19kB    2
829bcebbc9f6 elast  0.58%   1.24GiB / 1.924GiB64.43%2.97kB / 512kB / 729kB    47
#限制内存使用大小
[root@ubuntu1804 ~]#docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300
-e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx128m"
elasticsearch:7.6.2
[root@ubuntu1804 ~]#docker stats
CONTAINER ID NAME  CPU % MEM USAGE / LIMIT     MEM %  NET I/O   BLOCK     PIDS
29282e91d773 elasti254.23310.5MiB / 1.924GiB   15.76% 766B / 0B 766kB /46kB 22
1.4.2.4 查看容器的详细信息

docker inspect 可以查看docker各种对象的详细信息,包括:镜像,容器,网络等

docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Options:
-f, --format string   Format the output using the given Go template
-s, --size            Display total file sizes if the type is container

范例:

[root@ubuntu1804 ~]#docker inspect 9997
[
    {
"Id":
"9997053f9766d4adf709d46161d7ec6739eacafbe8d4721133874b89112ad1a6",
"Created": "2020-02-25T14:03:00.790597711Z",
"Path": "/bin/sh",
"Args": [
"-c",
"i=1;while true;do echo hello$i;let i++;sleep 1;done"
        ],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 10023,
"ExitCode": 0,
"Error": "",
"StartedAt": "2020-02-25T14:03:01.407282144Z",
"FinishedAt": "0001-01-01T00:00:00Z"
        },
"Image":
"sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
"ResolvConfPath":
"/var/lib/docker/containers/9997053f9766d4adf709d46161d7ec6739eacafbe8d472113387
4b89112ad1a6/resolv.conf",
"HostnamePath":
"/var/lib/docker/containers/9997053f9766d4adf709d46161d7ec6739eacafbe8d472113387
4b89112ad1a6/hostname",
"HostsPath":
"/var/lib/docker/containers/9997053f9766d4adf709d46161d7ec6739eacafbe8d472113387
4b89112ad1a6/hosts",
"LogPath":
"/var/lib/docker/containers/9997053f9766d4adf709d46161d7ec6739eacafbe8d472113387
4b89112ad1a6/9997053f9766d4adf709d46161d7ec6739eacafbe8d4721133874b89112ad1a6-
json.log",
"Name": "/gracious_wescoff",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
            },
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
            },
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
            ],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
            ],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
            ]
        },
"GraphDriver": {
"Data": {
"LowerDir":
"/var/lib/docker/overlay2/27f7bf9c29a0303e2526bd7fa7d61fcc3a2ef400e6948b5d9487b5
b30f506853-
init/diff:/var/lib/docker/overlay2/cb3f60a3d09e0555d06525b70cc30975a3cb70e23c87e
7e46bd44b6cfffbcda0/diff",
"MergedDir":
"/var/lib/docker/overlay2/27f7bf9c29a0303e2526bd7fa7d61fcc3a2ef400e6948b5d9487b5
b30f506853/merged",
"UpperDir":
"/var/lib/docker/overlay2/27f7bf9c29a0303e2526bd7fa7d61fcc3a2ef400e6948b5d9487b5
b30f506853/diff",
"WorkDir":
"/var/lib/docker/overlay2/27f7bf9c29a0303e2526bd7fa7d61fcc3a2ef400e6948b5d9487b5
b30f506853/work"
            },
"Name": "overlay2"
        },
"Mounts": [],
"Config": {
"Hostname": "9997053f9766",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
"Cmd": [
"/bin/sh",
"-c",
"i=1;while true;do echo hello$i;let i++;sleep 1;done"
            ],
"Image": "alpine",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
        },
"NetworkSettings": {
"Bridge": "",
"SandboxID":
"4823297a262eaad3b63778c2fe04a74e38ce401c22404f05f3cf54ab7dc188e2",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/4823297a262e",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID":
"019896bd99c9e158ef9f97b1617f1638fee94c7f92c9250e1ac1bfe58c97c911",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID":
"d407310ec8ff57a6623ae2fa01ba860ab0615135585a00b19f0751561c99ab16",
"EndpointID":
"019896bd99c9e158ef9f97b1617f1638fee94c7f92c9250e1ac1bfe58c97c911",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null
                }
            }
        }
    }
]
#选择性查看
[root@ubuntu1804 ~]#docker inspect -f "{{.Metadata}}" test:v1.0
{2020-07-24 21:56:42.247448035 +0800 CST}
[root@ubuntu1804 ~]#docker inspect -f "{{.Created}}" c1
2020-07-24T13:37:11.006574248Z
[root@ubuntu1804 ~]#docker inspect --format "{{.Created}}" c1
2020-07-24T13:37:11.006574248Z
[root@ubuntu1804 ~]#docker inspect --format="{{.Created}}" c1
2020-07-24T13:37:11.006574248Z
[root@ubuntu2004 ~]#docker inspect  nginx01 -f '{{.Created}}'
2022-10-17T03:22:54.699198665Z
[root@ubuntu2004 ~]#docker inspect  nginx01 -f '{{.Path}}'
/docker-entrypoint.sh
[root@ubuntu2004 ~]#docker inspect  nginx01 -f '{{.Args}}'
[nginx -g daemon off;]
[root@ubuntu2004 ~]#docker inspect  nginx01 -f '{{.State}}'
{running truefalsefalsefalsefalse491002022-10-17T03:22:54.895462684Z
0001-01-01T00:00:00Z <nil>}

1.4.3 删除容器

docker rm 可以删除容器,即使容器正在运行当中,也可以被强制删除掉

格式

docker rm [OPTIONS] CONTAINER [CONTAINER...]
docker container rm [OPTIONS] CONTAINER [CONTAINER...]
#选项:
-f, --force     Force the removal of a running container (uses SIGKILL)
-v, --volumes   Remove the volumes associated with the container
#删除停止的容器
docker container prune [OPTIONS]
Options:
--filter filter   Provide filter values (e.g. 'until=<timestamp>')
-f, --force           Do not prompt for confirmation

范例:

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                     PORTS               NAMES
868b33da850c        alpine              "/bin/sh"2 minutes ago
Up 2 minutes                                   alpine5
3a05bbf66dac        alpine              "/bin/sh"3 minutes ago
Exited (0) 3 minutes ago                       alpine4
df428caf7128        alpine              "/bin/sh"3 minutes ago
Up 3 minutes                                   alpine3
6d64f47a83e6        alpine              "/bin/sh"3 minutes ago
Exited (0) 3 minutes ago                       alpine2
edd2ac2690e6        alpine              "/bin/sh"4 minutes ago
Exited (0) 4 minutes ago                       alpine1
[root@ubuntu1804 ~]#docker rm 3a05bbf66dac
3a05bbf66dac
[root@ubuntu1804 ~]#docker rm alpine5
Error response from daemon: You cannot remove a running container
868b33da850cfcc7db8b84150fb9c7686b577889f10425bb4c5e17f28cf68a29. Stop the
container before attempting removal or force remove
[root@ubuntu1804 ~]#docker rm -f  alpine5
alpine5

范例: 删除所有容器

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                     PORTS               NAMES
df428caf7128        alpine              "/bin/sh"4 minutes ago
Up 4 minutes                                   alpine3
6d64f47a83e6        alpine              "/bin/sh"4 minutes ago
Exited (0) 4 minutes ago                       alpine2
edd2ac2690e6        alpine              "/bin/sh"5 minutes ago
Exited (0) 5 minutes ago                       alpine1
[root@ubuntu1804 ~]#docker rm -f `docker ps -a -q`
df428caf7128
6d64f47a83e6
edd2ac2690e6
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
[root@ubuntu1804 ~]#docker ps -a -q | xargs docker rm -f

范例: 删除指定状态的容器

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                        PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"22 minutes ago
     Exited (137) 14 minutes ago                       nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"22 minutes ago
     Up 4 minutes                  80/tcp              nginx1
[root@ubuntu1804 ~]#docker rm `docker ps -qf status=exited`
dd002f947cbe
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
1f3f82995e05        nginx               "nginx -g 'daemon of…"22 minutes ago
     Up 4 minutes        80/tcp              nginx1
[root@ubuntu1804 ~]#

范例: 删除所有停止的容器

[root@ubuntu1804 ~]#docker container prune  -f
Deleted Containers:
37ba6ef81e33102a9cf4547ed10095d2298e29c8d67991b31390d5db8001dbcf
6c674c7ced422c7c29f218118c8b5da734ccebb9da31cdd3f64e7c658d2882a4
Total reclaimed space: 0B

1.4.4 容器的启动和停止

格式

docker start|stop|restart|pause|unpause 容器ID
#stop 容器的进程退出
#pause 容器的进程进入不可中断的睡眠状态uninterruptable sleeping,ps命令显示为D

批量正常启动或关闭所有容器

docker start $(docker ps -a -q)
docker stop $(docker ps -a -q)

范例:

[root@ubuntu1804 ~]#docker run -d  --name nginx1 nginx
8d9342b35589b72c3f7f01f4d9fe8797e974cda8ba28d2bac69ee578aa592ca2
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
8d9342b35589        nginx               "nginx -g 'daemon of…"5 seconds ago
    Up 4 seconds        80/tcp              nginx1
[root@ubuntu1804 ~]#docker stop nginx1
nginx1
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                     PORTS               NAMES
8d9342b35589        nginx               "nginx -g 'daemon of…"15 seconds ago
     Exited (0) 2 seconds ago                       nginx1
[root@ubuntu1804 ~]#docker start nginx1
nginx1
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
8d9342b35589        nginx               "nginx -g 'daemon of…"21 seconds ago
     Up 1 second         80/tcp              nginx1
[root@ubuntu1804 ~]#docker restart nginx1
nginx1
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
8d9342b35589        nginx               "nginx -g 'daemon of…"30 seconds ago
     Up 1 second         80/tcp              nginx1
[root@ubuntu1804 ~]#

范例: 启动并进入容器

[root@ubuntu1804 ~]#docker run --name=c1 -it ubuntu bash
root@539722b55b76:/# exit
exit
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                    PORTS               NAMES
539722b55b76        ubuntu              "bash"4 seconds ago
Exited (0) 1 second ago                       c1
[root@ubuntu1804 ~]#docker start c1
c1
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                          PORTS               NAMES
539722b55b76        ubuntu              "bash"18 seconds ago
     Up 2 seconds                                        c1
[root@ubuntu1804 ~]#docker stop c1
c1
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                     PORTS               NAMES
539722b55b76        ubuntu              "bash"43 seconds ago
     Exited (0) 1 second ago                        c1
#启动并进入容器
[root@ubuntu1804 ~]#docker start -i c1
root@539722b55b76:/# exit
exit
[root@ubuntu1804 ~]#docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                     PORTS               NAMES
539722b55b76        ubuntu              "bash"4 minutes ago
Exited (0) 5 seconds ago                       c1

范例: 启动和停止所有容器

[root@ubuntu1804 ~]#docker rm -f `docker ps -a -q`
b722c745406c
8d9342b35589
[root@ubuntu1804 ~]#docker run -d  --name nginx1 nginx
1f3f82995e052647678fd27bfa27a5b5615efc129270698cbaac3120544d6609
[root@ubuntu1804 ~]#docker run -d  --name nginx2 nginx
dd002f947cbe786ac0e834e06744337556f82d5850f4b16e01f12b9b3759f83e
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"4 seconds ago
    Up 3 seconds        80/tcp              nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"7 seconds ago
    Up 6 seconds        80/tcp              nginx1
[root@ubuntu1804 ~]#docker stop `docker ps -a -q`
dd002f947cbe
1f3f82995e05
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                     PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"22 seconds ago
     Exited (0) 2 seconds ago                       nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"25 seconds ago
     Exited (0) 2 seconds ago                       nginx1
[root@ubuntu1804 ~]#docker start `docker ps -a -q`
dd002f947cbe
1f3f82995e05
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"2 minutes ago
    Up 1 second         80/tcp              nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"2 minutes ago
    Up 1 second         80/tcp              nginx1

范例: 暂停和恢复容器

[root@ubuntu1804 ~]#docker run -d --name n1 nginx
48a8278f5df1d0b0c2c42c01d4e53d335df7e3e866fc7b68563cc2ac545fc07d
[root@ubuntu1804 ~]#docker top n1
UID                 PID                 PPID                C
STIME               TTY                 TIME                CMD
root                210420760
22:51               ?                   00:00:00            nginx: master
process nginx -g daemon off;
systemd+216821040
22:51               ?                   00:00:00            nginx: worker
process
[root@ubuntu1804 ~]#ps aux|grep nginx
root       21040.3  0.2  106285324 ?        Ss   22:51   0:00 nginx: master
process nginx -g daemon off;
systemd+21680.0  0.1  110562580 ?        S    22:51   0:00 nginx: worker
process
root       21880.0  0.0  144281040 pts/0    S+22:51   0:00 grep--
color=auto nginx
[root@ubuntu1804 ~]#docker pause n1
n1
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                  PORTS               NAMES
48a8278f5df1        nginx               "/docker-entrypoint.…"3 minutes ago
    Up 3 minutes (Paused)   80/tcp              n1
#处于不可中断的睡眠
[root@ubuntu1804 ~]#ps aux|grep nginx
root       21040.0  0.2  106285324 ?        Ds   22:51   0:00 nginx: master
process nginx -g daemon off;
systemd+21680.0  0.1  110562580 ?        D    22:51   0:00 nginx: worker
process
root       24940.0  0.0  144281004 pts/0    R+22:54   0:00 grep--
color=auto nginx
[root@ubuntu1804 ~]#docker unpause n1
n1
[root@ubuntu1804 ~]#ps aux|grep nginx
root       21040.0  0.2  106285324 ?        Ss   22:51   0:00 nginx: master
process nginx -g daemon off;
systemd+21680.0  0.1  110562580 ?        S    22:51   0:00 nginx: worker
process
root       25210.0  0.0  144281028 pts/0    S+22:55   0:00 grep--
color=auto nginx

范例: 容器的暂停和恢复

[root@ubuntu1804 ~]#docker run -itd centos
708bedcbd31be0ecac11aa21a7d15718d440e4bf65e3e6a8670f7391de21f301
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
708bedcbd31b        centos              "/bin/bash"4 seconds ago
Up 1 second                             blissful_payne
[root@ubuntu1804 ~]#docker pause   blissful_payne
blissful_payne
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                   PORTS               NAMES
708bedcbd31b        centos              "/bin/bash"19 seconds ago
Up 17 seconds (Paused)                       blissful_payne
[root@ubuntu1804 ~]#docker unpause  blissful_payne
blissful_payne
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
708bedcbd31b        centos              "/bin/bash"33 seconds ago
Up 31 seconds                           blissful_payne

1.4.5 给正在运行的容器发信号

docker kill 可以给容器发信号,默认号SIGKILL,即9信号

格式

docker kill [OPTIONS] CONTAINER [CONTAINER...]
#选项:
-s, --signal string   Signal to send to the container (default "KILL")
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"2 minutes ago
    Up 1 second         80/tcp              nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"2 minutes ago
    Up 1 second         80/tcp              nginx1
[root@ubuntu1804 ~]#docker  kill nginx1
nginx1
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                       PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"5 minutes ago
    Up 3 minutes                 80/tcp              nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"5 minutes ago
    Exited (137) 2 seconds ago                       nginx1
[root@ubuntu1804 ~]#
#发送19信号
[root@ubuntu2004 ~]#docker kill -s 19  nginx01
nginx01
[root@ubuntu2004 ~]#ps aux|grep nginx
root        66830.0  0.2   89125332 ?        Ts   11:42   0:00 nginx: master
process nginx -g daemon off;
systemd+67410.0  0.1   93322512 ?        S    11:42   0:00 nginx: worker
process
systemd+67420.0  0.1   93322512 ?        S    11:42   0:00 nginx: worker
process
root        69830.0  0.0   9392720 pts/1    R+11:47   0:00 grep--
color=auto nginx
[root@ubuntu2004 ~]#docker kill -s 18  nginx01
nginx01

范例: 关闭所有容器

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS               NAMES
dd002f947cbe        nginx               "nginx -g 'daemon of…"7 minutes ago
    Up 2 seconds        80/tcp              nginx2
1f3f82995e05        nginx               "nginx -g 'daemon of…"7 minutes ago
    Up 3 seconds        80/tcp              nginx1
#强制关闭所有运行中的容器
[root@ubuntu1804 ~]#docker  kill `docker ps -a -q`
dd002f947cbe
1f3f82995e05

1.4.6 进入正在运行的容器

1.4.6.1 使用attach命令

docker attach 容器名,attach 类似于vnc,操作会在同一个容器的多个会话界面同步显示,所有使用此方式进入容器的操作都是同步显示的,且使用exit退出后容器自动关闭, 不推荐使用 ,需要进入到有 shell环境的容器

格式:

docker attach [OPTIONS] CONTAINER

范例:

[root@ubuntu1804 ~]#docker run -it centos
[root@94a5c5c69b14 /]# cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core) #ctrl+p+q 退出
[root@94a5c5c69b14 /]# [root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
94a5c5c69b14        centos              "/bin/bash"14 seconds ago
Up 14 seconds                           unruffled_ellis
[root@ubuntu1804 ~]#docker attach  94a5
[root@94a5c5c69b14 /]#cat /etc/redhat-release
#同时在第二个终端attach到同一个容器,执行命令,可以在前一终端看到显示图面是同步的
[root@ubuntu1804 ~]#docker attach  94a5
[root@94a5c5c69b14 /]#cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
[root@92a8279611a9 /]# exit  #两个终端都同时退出
exit
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                      PORTS               NAMES
92a8279611a9        centos              "/bin/bash"4 minutes ago
Exited (0) 39 seconds ago                       agitated_tesla

1.4.6.2 使用exec命令

在运行中的容器启动新进程,可以执行单次命令,以及进入容器测试环境使用此方式,使用exit退出,但容器还在运行, 此为推荐方式

格式:

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
常用选项:
-d, --detach               Detached mode: run command in the background
-e, --env list             Set environment variables
-i, --interactive          Keep STDIN open even if not attached
-t, --tty                  Allocate a pseudo-TTY
#常见用法
docker exec -it容器ID sh|bash

范例:

[root@ubuntu1804 ~]#docker run -itd centos
24788f69cec65e1f511387c1bae354a66e5b7ae29261e68957bc6dcc4818af6b
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
24788f69cec6        centos              "/bin/bash"3 seconds ago
Up 1 second                             keen_jennings
#执行一次性命令
[root@ubuntu1804 ~]#docker exec 2478 cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
#进入容器,执行命令,exit退出但容器不停止
[root@ubuntu1804 ~]#docker exec  -it 2478  bash
[root@24788f69cec6 /]# cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
[root@24788f69cec6 /]# exit
exit
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
24788f69cec6        centos              "/bin/bash"4 minutes ago
Up 4 minutes                            keen_jennings
[root@ubuntu1804 ~]#

1.4.7 暴露所有容器端口

容器启动后,默认处于预定义的NAT网络中,所以外部网络的主机无法直接访问容器中网络服务

docker run -P 可以将事先容器预定义的所有端口映射宿主机的网卡的随机端口,默认从32768开始使用随机端口时,当停止容器后再启动可能会导致端口发生变化

-P , --publish-all=true | false默认为false
#示例:
docker run -P docker.io/nginx  #映射容器所有暴露端口至随机本地端口

docker port 可以查看容器的端口映射关系

格式

docker port CONTAINER [PRIVATE_PORT[/PROTO]]

范例:

[root@centos7 ~]#docker port nginx-c1
443/tcp -> 0.0.0.0:8443
53/udp -> 0.0.0.0:8053
80/tcp -> 0.0.0.0:8080
[root@centos7 ~]#docker port nginx-c1 53/udp
0.0.0.0:8053

范例:

[root@centos7 ~]#docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
8ec398bc0356: Pull complete
a53c868fbde7: Pull complete
79daf9dd140d: Pull complete
Digest: sha256:70821e443be75ea38bdf52a974fd2271babd5875b2b1964f05025981c75a6717
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@centos7 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
[root@centos7 ~]#ss -ntl
State      Recv-Q Send-Q          Local Address:Port                         Peer
Address:Port
LISTEN     0128                         *:22
       *:*
LISTEN     0100127.0.0.1:25
       *:*
LISTEN     0128                        :::22
      :::*
LISTEN     0100                       ::1:25
      :::*
#前台启动的会话窗口无法进行其他操作,除非退出,但是退出后容器也会退出
[root@centos7 ~]#docker run -P nginx
172.17.0.1 -- [26/Jan/2020:06:44:56 +0000] "GET / HTTP/1.1"200612"-"
"curl/7.29.0""-"
#另开一个窗口执行下面命令
[root@centos7 ~]#ss -ntl
State      Recv-Q Send-Q          Local Address:Port                         Peer
Address:Port
LISTEN     0128                         *:22
       *:*
LISTEN     0100127.0.0.1:25
       *:*
LISTEN     0128                        :::22
      :::*
LISTEN     0100                       ::1:25
      :::*
LISTEN     0128                        :::32768
       :::*
[root@centos7 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                   NAMES
78086069642b        nginx               "nginx -g 'daemon of…"23 seconds ago
     Up 21 seconds       0.0.0.0:32768->80/tcp   gallant_austin
[root@centos7 ~]#curl 127.0.0.1:32768
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@centos7 ~]#
#自动生成Iptables规则
[root@centos7 ~]#iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
191012 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0
         ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 1 packets, 76 bytes)
 pkts bytes target     prot opt in     out     source               destination
00 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8
         ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 1 packets, 76 bytes)
 pkts bytes target     prot opt in     out     source               destination
00 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0
00 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2
          tcp dpt:80
00 MASQUERADE  tcp  --  *      *       172.17.0.4           172.17.0.4
          tcp dpt:80
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination
00 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0
00 DNAT       tcp  --  !docker0 *       0.0.0.0/0            10.0.0.7
          tcp dpt:32768 to:172.17.0.2:80
#回到之前的会话窗口,同时按两个键 ctrl+c 退出容器
[root@centos7 ~]#docker run -P nginx
172.17.0.1 -- [26/Jan/2020:06:44:56 +0000] "GET / HTTP/1.1"200612"-"
"curl/7.29.0""-"
^C[root@centos7 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                     PORTS               NAMES
78086069642b        nginx               "nginx -g 'daemon of…"3 minutes ago
    Exited (0) 5 seconds ago                       gallant_austin
[root@centos7 ~]#

端口映射的本质就是利用NAT技术实现的

范例: 端口映射和iptables

#端口映射前的iptables规则
[root@ubuntu1804 ~]#iptables -S
  • -P INPUT ACCEPT

  • -P FORWARD DROP

  • -P OUTPUT ACCEPT

  • -N DOCKER

  • -N DOCKER-ISOLATION-STAGE-1

  • -N DOCKER-ISOLATION-STAGE-2

  • -N DOCKER-USER

  • -A FORWARD -j DOCKER-USER

-A FORWARD -j DOCKER-ISOLATION-STAGE-1
  • -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -o docker0 -j DOCKER

  • -A FORWARD -i docker0 ! -o docker0 -j ACCEPT

-A FORWARD -i docker0 -o docker0 -j ACCEPT
  • -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2

  • -A DOCKER-ISOLATION-STAGE-1 -j RETURN

  • -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP

  • -A DOCKER-ISOLATION-STAGE-2 -j RETURN -A DOCKER-USER -j RETURN [root@ubuntu1804 ~]#iptables -S -t nat

-P PREROUTING ACCEPT
  • -P INPUT ACCEPT

  • -P OUTPUT ACCEPT

  • -P POSTROUTING ACCEPT

  • -N DOCKER

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
  • -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
[root@ubuntu1804 ~]#iptables -S > pre.filter
[root@ubuntu1804 ~]#iptables -S -t nat > pre.nat
#实现端口映射
[root@ubuntu1804 ~]#docker run -d -P --name nginx1 nginx
286a3dedf159fbf0a4b895741a9d95562c87b44782ea85c8d172474da8860c36
[root@ubuntu1804 ~]#docker exec -it nginx1 hostname -i
172.17.0.2
[root@ubuntu1804 ~]#docker port nginx1
80/tcp -> 0.0.0.0:32769
#端口映射后的iptables规则
[root@ubuntu1804 ~]#iptables -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport80-j
ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
[root@ubuntu1804 ~]#iptables -S -t nat
-P PREROUTING ACCEPT
  • -P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s172.17.0.2/32 -d172.17.0.2/32 -p tcp -m tcp --dport80-j
MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport32769-j DNAT --to-destination
172.17.0.2:80
#对比端口映射前后的变化
[root@ubuntu1804 ~]#iptables -S > post.filter
[root@ubuntu1804 ~]#iptables -S -t nat > post.nat
[root@ubuntu1804 ~]#diff pre.filter post.filter
13a14
> -A DOCKER -d172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport80-j
ACCEPT
[root@ubuntu1804 ~]#diff pre.nat post.nat
8a9
> -A POSTROUTING -s172.17.0.2/32 -d172.17.0.2/32 -p tcp -m tcp --dport80-j
MASQUERADE
9a11
> -A DOCKER ! -i docker0 -p tcp -m tcp --dport32769-j DNAT --to-destination
172.17.0.2:80
#本地和选程都可以访问
[root@ubuntu1804 ~]#curl 127.0.0.1:32769
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@centos8 ~]#curl 10.0.0.100:32769
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#利用iptables 阻止同一个宿主机的其它容器CentOS8的访问
[root@ubuntu1804 ~]#iptables -I DOCKER -s 10.0.0.8 -d 172.17.0.2 -p tcp --dport
80 -j REJECT
[root@ubuntu1804 ~]#iptables -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -s10.0.0.8/32 -d172.17.0.2/32 -p tcp -m tcp --dport80-j REJECT --
reject-with icmp-port-unreachable
-A DOCKER -d172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport80-j
ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
#测试访问
[root@centos8 ~]#curl 10.0.0.100:32769
curl: (7) Failed to connect to 10.0.0.100 port 32769: Connection refused
[root@centos7 ~]#curl -I 10.0.0.100:32769
HTTP/1.1 200 OK
Server: nginx/1.19.1
Date: Thu, 23 Jul 202005:14:01 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 07 Jul 202015:52:25 GMT
Connection: keep-alive
ETag: "5f049a39-264"
Accept-Ranges: bytes

1.4.8 指定端口映射

docker run -p 可以将容器的预定义的指定端口映射到宿主机的相应端口

注意: 多个容器映射到宿主机的端口不能冲突,但容器内使用的端口可以相同

方式1: 容器80端口映射宿主机本地随机端口

docker run  -p80--name nginx-test-port1 nginx

方式2: 容器80端口映射到宿主机本地端口81

docker run  -p81:80 --name nginx-test-port2 nginx

方式3: 宿主机本地IP:宿主机本地端口:容器端口

docker run  -p10.0.0.100:82:80 --name nginx-test-port3 docker.io/nginx

方式4: 宿主机本地IP:宿主机本地随机端口:容器端口,默认从32768开始

docker run -p10.0.0.100::80 --name nginx-test-port4 docker.io/nginx

方式5: 宿主机本机ip:宿主机本地端口:容器端口/协议,默认为tcp协议

docker run  -p10.0.0.100:83:80/udp --name nginx-test-port5 docker.io/nginx

方式6: 一次性映射多个端口+协议

docker run  -p8080:80/tcp -p8443:443/tcp -p53:53/udp --name nginx-test-port6
nginx

范例:

[root@centos7 ~]#docker run -d  -p 8080:80 -p 8443:443 -p 8053:53/udp nginx
a902b177bb7135ad8a8a179dbf8ce02dcc4806a1136475e59c2310833d7434ab
[root@centos7 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS
          NAMES
a902b177bb71        nginx               "nginx -g 'daemon of…"5 seconds ago
    Up 4 seconds        0.0.0.0:8053->53/udp, 0.0.0.0:8080->80/tcp,
0.0.0.0:8443->443/tcp   affectionate_aryabhata
[root@centos7 ~]#ss -ntpul
Netid  State      Recv-Q Send-Q       Local Address:Port
Peer Address:Port
udp    UNCONN     00127.0.0.1:323
         *:*                   users:(("chronyd",pid=6292,fd=1))
udp    UNCONN     00                      ::1:323
        :::*                   users:(("chronyd",pid=6292,fd=2))
udp    UNCONN     00                       :::8053
       :::*                   users:(("docker-proxy",pid=32671,fd=4))
tcp    LISTEN     0128                      *:22
        *:*                   users:(("sshd",pid=6623,fd=3))
tcp    LISTEN     0100127.0.0.1:25
        *:*                   users:(("master",pid=6748,fd=13))
tcp    LISTEN     0128                     :::8080
       :::*                   users:(("docker-proxy",pid=32659,fd=4))
tcp    LISTEN     0128                     :::22
       :::*                   users:(("sshd",pid=6623,fd=4))
tcp    LISTEN     0100                    ::1:25
       :::*                   users:(("master",pid=6748,fd=14))
tcp    LISTEN     0128                     :::8443
       :::*                   users:(("docker-proxy",pid=32646,fd=4))
[root@centos7 ~]#iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
191012 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0
         ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
00 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8
         ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
00 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0
00 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2
          tcp dpt:443
00 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2
          tcp dpt:80
00 MASQUERADE  udp  --  *      *       172.17.0.2           172.17.0.2
          udp dpt:53
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination
00 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0
00 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0
           tcp dpt:8443 to:172.17.0.2:443
00 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0
           tcp dpt:8080 to:172.17.0.2:80
00 DNAT       udp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0
           udp dpt:8053 to:172.17.0.2:53
#杀死nginx进程,nginx将关闭,相应端口也会关闭
[root@centos7 ~]#kill  <NGINXPID>

实战案例: 修改已经创建的容器的端口映射关系

[root@ubuntu1804 ~]#docker run -d -p 80:80 --name nginx01 nginx
dc5d7c1029e582a3e05890fd18565367482232c151bba09ca27e195d39dbcc24
[root@ubuntu1804 ~]#docker port nginx01
80/tcp -> 0.0.0.0:80
[root@ubuntu1804 ~]#lsof -i:80
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 2364 root    4u  IPv6  35929      0t0  TCP *:http (LISTEN)
[root@ubuntu1804 ~]#ls
/var/lib/docker/containers/dc5d7c1029e582a3e05890fd18565367482232c151bba09ca27e1
95d39dbcc24/
checkpoints
hostconfig.json  mounts
config.v2.json
hostname         resolv.conf
dc5d7c1029e582a3e05890fd18565367482232c151bba09ca27e195d39dbcc24-json.log  hosts
           resolv.conf.hash
[root@ubuntu1804 ~]#systemctl stop docker
[root@ubuntu1804 ~]#vim
/var/lib/docker/containers/dc5d7c1029e582a3e05890fd18565367482232c151bba09ca27e1
95d39dbcc24/hostconfig.json
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"80"}]}
#PortBindings后80/tcp对应的是容器内部的80端口,HostPort对应的是映射到宿主机的端口80 修改此
处为8000
"PortBindings":{"80/tcp":[{"HostIp":"","HostPort":"8000"}]}
[root@ubuntu1804 ~]#systemctl start docker
[root@ubuntu1804 ~]#docker start nginx01
[root@ubuntu1804 ~]#docker port nginx01
80/tcp -> 0.0.0.0:8000

范例:实现 wordpress 应用

[root@ubuntu2004 ~]#docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e
MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name
mysql -d  --restart=always mysql:8.0.29-oracle
[root@ubuntu2004 ~]#docker run -d -p 8080:80 --name wordpress -v
/data/wordpess:/var/www/html --restart=always  wordpress:php7.4-apache

1.4.9 查看容器的日志

docker logs 可以查看容器中运行的进程在控制台输出的日志信息

格式

docker logs [OPTIONS] CONTAINER
选项:
--details        Show extra details provided to logs
-f, --follow     Follow log output
--since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or
relative (e.g. 42m for42 minutes)
--tail string    Number of lines to show from the end of the logs (default
"all")
-t, --timestamps     Show timestamps
--until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or
relative (e.g. 42m     for42 minutes)

范例: 查看容器日志

[root@ubuntu1804 ~]#docker run  alpine /bin/sh -c 'i=1;while true;do echo
hello$i;let i++;sleep 2;done'
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
188c0c94c7c5: Pull complete
Digest: sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a
Status: Downloaded newer image for alpine:latest
hello1
hello2
hello3
hello4
hello5
^C[root@ubuntu1804 ~]#
[root@ubuntu1804 ~]#docker run -d  alpine /bin/sh -c 'i=1;while true;do echo
hello$i;let i++;sleep 2;done'
512622b006c05673630eb04f081f8475400b1cda786b0a8a5d1c1c2fd6dc56a7
[root@ubuntu1804 ~]#docker logs  5126
hello1
hello2
hello3
hello4
hello5
hello6
[root@ubuntu1804 ~]#docker logs --tail 3 5126
hello8
hello9
hello10
#显示时间
[root@ubuntu1804 ~]#docker logs --tail 0 -t 5126
2020-02-25T13:30:07.321390731Z hello17
#持续跟踪
[root@ubuntu1804 ~]#docker logs -f 5126
hello1
hello2
hello3
hello4
hello5
hello6
hello7
hello8
hello9
hello10
hello11
hello12
hello13
hello14
hello15
hello16
hello17
hello18
.....

范例: 查看httpd服务日志

[root@ubuntu1804 ~]#docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
bb79b6b2107f: Pull complete
26694ef5449a: Pull complete
7b85101950dd: Pull complete
da919f2696f2: Pull complete
3ae86ea9f1b9: Pull complete
Digest: sha256:b82fb56847fcbcca9f8f162a3232acb4a302af96b1b2af1c4c3ac45ef0c9b968
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
[root@ubuntu1804 ~]#docker run -d -p 80:80 --name web1  httpd
9f55b2216f0d65fe010166a78f07f45a47379bb0efa38c4f81f2034a7401907b
[root@ubuntu1804 ~]#docker logs web1
AH00558: httpd: Could not reliably determine the server's fully qualified domain
name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this
message
AH00558: httpd: Could not reliably determine the server's fully qualified domain
name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this
message
[Mon Nov 1601:07:53.780025 2020] [mpm_event:notice] [pid 1:tid 140363582039168]
AH00489: Apache/2.4.46 (Unix) configured -- resuming normal operations
[Mon Nov 1601:07:53.780218 2020] [core:notice] [pid 1:tid 140363582039168]
AH00094: Command line: 'httpd -D FOREGROUND'
[root@ubuntu1804 ~]#docker logs -f web1
AH00558: httpd: Could not reliably determine the server's fully qualified domain
name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this
message
AH00558: httpd: Could not reliably determine the server's fully qualified domain
name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this
message
[Mon Nov 1601:07:53.780025 2020] [mpm_event:notice] [pid 1:tid 140363582039168]
AH00489: Apache/2.4.46 (Unix) configured -- resuming normal operations
[Mon Nov 1601:07:53.780218 2020] [core:notice] [pid 1:tid 140363582039168]
AH00094: Command line: 'httpd -D FOREGROUND'
10.0.0.8 -- [16/Nov/2020:01:08:23 +0000] "GET / HTTP/1.1"20045

范例: 查看nginx服务访问日志

# 查看一次

[root@centos7 ~]#docker logs nginx-test-port1
10.0.0.1 -- [26/Jan/2020:07:17:16 +0000] "GET /favicon.ico HTTP/1.1"404555"-
""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/63.0.3239.132 Safari/537.36""-"
2020/01/26 07:17:16 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico"
failed (2: No such file or directory), client: 10.0.0.1, server: localhost,
request: "GET /favicon.ico HTTP/1.1", host: "10.0.0.7:32769"
10.0.0.1 -- [26/Jan/2020:07:17:17 +0000] "GET / HTTP/1.1"200612"-"
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko""-"

# 持续查看

[root@centos7 ~]#docker logs -f nginx-test-port1
10.0.0.1 -- [26/Jan/2020:07:17:16 +0000] "GET /favicon.ico HTTP/1.1"404555"-
""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/63.0.3239.132 Safari/537.36""-"
2020/01/26 07:17:16 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico"
failed (2: No such file or directory), client: 10.0.0.1, server: localhost,
request: "GET /favicon.ico HTTP/1.1", host: "10.0.0.7:32769"
10.0.0.1 -- [26/Jan/2020:07:17:17 +0000] "GET / HTTP/1.1"200612"-"
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko""-"

1.4.10 传递运行命令

容器需要有一个前台运行的进程才能保持容器的运行,通过传递运行参数是一种方式,另外也可以在构建镜像的时候指定容器启动时运行的前台命令

容器里的PID为1的守护进程的实现方式

服务类: 如: Nginx,Tomcat,Apache ,但服务不能停

命令类: 如: tail -f /etc/hosts ,主要用于测试环境,注意: 不要tail -f <服务访问日志> 会产生不必要的磁盘IO

范例:

[root@ubuntu1804 ~]#docker run -d alpine
6ec8989f572a41d2d0c7d2cb12ac31de14de38af0a01af405f81dbfcf534b716
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS                     PORTS               NAMES
6ec8989f572a        alpine              "/bin/sh"3 seconds ago
Exited (0) 2 seconds ago                       gallant_albattani
[root@ubuntu1804 ~]#docker run -d alpine tail -f /etc/hosts
2bc9fa486769a2335f7e9aa67c7d3e7f091ba9b76d38dff868b8fd648251b576
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED
  STATUS                      PORTS               NAMES
2bc9fa486769        alpine              "tail -f /etc/hosts"3 seconds ago
  Up 2 seconds                                    stupefied_keldysh
6ec8989f572a        alpine              "/bin/sh"23 seconds ago
   Exited (0) 22 seconds ago                       gallant_albattani
[root@ubuntu1804 ~]#docker exec -it 2bc9fa486769 sh
/ # ps aux
PID   USER     TIME  COMMAND
1 root      0:00 tail -f /etc/hosts
11 root      0:00 sh
17 root      0:00 ps aux
/ # exit
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED
   STATUS              PORTS               NAMES
1e30dfc283da        alpine              "tail -f /etc/hosts"   About a minute
ago   Up About a minute                       kind_mcclintock

1.4.11 容器内部的hosts文件

容器会自动将容器的ID加入自已的/etc/hosts文件中,并解析成容器的IP

[root@ubuntu1804 ~]#docker run -it centos /bin/bash
[root@598262a87c46 /]# cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  598262a87c46  #默认会将实例的ID 添加到自己的hosts文件
[root@598262a87c46 /]# hostname
598262a87c46
[root@598262a87c46 /]# ping 598262a87c46
PING 598262a87c46 (172.17.0.2) 56(84) bytes of data.
64 bytes from 598262a87c46 (172.17.0.2): icmp_seq=1ttl=64time=0.118 ms
64 bytes from 598262a87c46 (172.17.0.2): icmp_seq=2ttl=64time=0.085 ms
^C
--- 598262a87c46 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev =0.085/0.101/0.118/0.019 ms
#在另一个会话执行
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
598262a87c46        centos              "/bin/bash"14 seconds ago
Up 12 seconds                           optimistic_wiles

范例: 修改容器的 hosts文件

[root@ubuntu1804 ~]#docker run -it --rm --add-host www.wangxiaochun.com:6.6.6.6
--add-host www.wang.org:8.8.8.8   busybox
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
6.6.6.6 www.wangxiaochun.com
8.8.8.8 www.wang.org
172.17.0.2  449bf0468efd

1.4.12 指定容器DNS

容器的dns服务器,默认采用宿主机的dns 地址,可以用下面方式指定其它的DNS地址

将dns地址配置在宿主机

在容器启动时加选项 -- dns=x.x.x.x

在/etc/docker/daemon.json 文件中指定

范例: 容器的DNS默认从宿主机的DNS获取

[root@ubuntu1804 ~]#systemd-resolve --status|grep -A1 -i "DNS Servers"
         DNS Servers: 180.76.76.76
223.6.6.6
[root@ubuntu1804 ~]#docker run -it --rm   centos bash
[root@1364f98c4227 /]# cat /etc/resolv.conf
nameserver 180.76.76.76
nameserver 223.6.6.6
search wangxiaochun.com wang.org
[root@1364f98c4227 /]# exit
exit
[root@ubuntu1804 ~]#

范例: 指定DNS地址

[root@ubuntu1804 ~]#docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8  centos bash
[root@ef9cacc74b58 /]# cat /etc/resolv.conf
search wangxiaochun.com wang.org
nameserver 1.1.1.1
nameserver 8.8.8.8
[root@ef9cacc74b58 /]# exit
exit
[root@ubuntu1804 ~]#

范例: 指定domain名

[root@ubuntu1804 ~]#docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8 --dns-search
a.com --dns-search b.com  busybox
/ # cat /etc/resolv.conf
search a.com b.com
nameserver 1.1.1.1
nameserver 8.8.8.8
/ #

范例: 配置文件指定DNS和搜索domain名

[root@ubuntu1804 ~]#vim /etc/docker/daemon.json
[root@ubuntu1804 ~]#cat /etc/docker/daemon.json
{
"storage-driver": "overlay2",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"dns" : [  "114.114.114.114", "119.29.29.29"],
"dns-search": [ "wangxiaochun.com", "wang.org"]

}

[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#docker run -it --rm   centos bash
[root@7a2d8fac6f6b /]# cat /etc/resolv.conf
search wangxiaochun.com wang.org
nameserver 114.114.114.114
nameserver 119.29.29.29
[root@7a2d8fac6f6b /]# exit
exit
#用--dns指定优先级更高
[root@ubuntu1804 ~]#docker run -it --rm  --dns 8.8.8.8 --dns 8.8.4.4 centos bash
[root@80ffe3547b87 /]# cat /etc/resolv.conf
search wangxiaochun.com wang.org
nameserver 8.8.8.8
nameserver 8.8.4.4
[root@80ffe3547b87 /]# exit
exit

1.4.13 容器内和宿主机之间复制文件

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Options:
-a, --archive       Archive mode (copy all uid/gid information)
-L, --follow-link   Always follow symbol link in SRC_PATH

范例: 复制容器的文件至宿主机

[root@ubuntu2004 ~]#docker run -it --name b1  busybox sh
[root@ubuntu2004 ~]#docker cp  b1:/bin/busybox /usr/local/bin/
[root@ubuntu2004 ~]#busybox ls

范例:

[root@ubuntu1804 ~]#docker run -itd centos
1311fe67e6708dac71c01f7d1752a6dcb5e85c2f1fa4ac2efcef9edfe4fb6bb5
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
1311fe67e670        centos              "/bin/bash"2 seconds ago
Up 2 seconds                            elegant_khorana
#将容器内文件复制到宿主机
[root@ubuntu1804 ~]#docker cp -a 1311:/etc/centos-release .
[root@ubuntu1804 ~]#cat centos-release
CentOS Linux release 8.1.1911 (Core)
#将宿主机文件复制到容器内
[root@ubuntu1804 ~]#docker cp /etc/issue  1311:/root/
[root@ubuntu1804 ~]#docker exec 1311 cat /root/issue
Ubuntu 18.04.1 LTS \n \l
[root@ubuntu1804 ~]#
#复制目录
[root@ubuntu2004 ~]#docker cp busybox1:/  /srv/
[root@ubuntu2004 ~]#ls /srv
bin  dev  etc  home  proc  root  sys  tmp  usr  var
[root@ubuntu2004 ~]#du -sh /srv
1.4M    /srv

1.4.14 使用 systemd 控制容器运行

[root@ubuntu1804 ~]#cat  /lib/systemd/system/hello.service
[Unit]
Description=Hello World
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox-hello
ExecStartPre=-/usr/bin/docker rm busybox-hello
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox-hello busybox /bin/sh -c"while
true; do echo Hello World; sleep 1; done"
ExecStop=/usr/bin/docker kill busybox-hello
[Install]
WantedBy=multi-user.target
[root@ubuntu1804 ~]#systemctl  daemon-reload
[root@ubuntu1804 ~]#systemctl  enable --now hello.service

1.4.15 传递环境变量

有些容器运行时,需要传递变量,可以使用 -e <参数> 或 --env-file <参数文件> 实现范例: 传递变量创建MySQL

变量参考链接: https://hub.docker.com/_/mysql

#MySQL容器运行时需要指定root的口令
[root@ubuntu1804 ~]#docker run  --name mysql01 mysql:5.7.32
2020-11-1601:43:13+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL
Server 5.7.32-1debian10 started.
2020-11-1601:43:13+00:00 [Note] [Entrypoint]: Switching to dedicated user
'mysql'
2020-11-1601:43:13+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL
Server 5.7.32-1debian10 started.
2020-11-1601:43:13+00:00 [ERROR] [Entrypoint]: Database is uninitialized and
password option is not specified
    You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD
and MYSQL_RANDOM_ROOT_PASSWORD
[root@ubuntu1804 ~]#docker run --name mysql-test1 -v /data/mysql:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wpuser -e
MYSQL_PASSWORD=123456 -d -p 3306:3306 mysql:5.7.30
[root@ubuntu1804 ~]#docker run --name mysql-test2 -v
/root/mysql/:/etc/mysql/conf.d -v /data/mysql2:/var/lib/mysql --env-file=env.list
-d -p 3307:3306 mysql:5.7.30
[root@ubuntu1804 ~]#cat mysql/mysql-test.cnf
[mysqld]
server-id=100
log-bin=mysql-bin
[root@ubuntu1804 ~]#cat env.list
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=wppass

1.4.16 清除不再使用的数据

#dangling images表示TAG为<none>的镜像
[root@ubuntu1804 ~]#docker system  prune
WARNING! This will remove:
  • all stopped containers

  • all networks not used by at least one container

  • all dangling images

  • all dangling build cache

Are you sure you want to continue? [y/N] y
Deleted Containers:
408ee2891b50221c5ee6b70fcaa3053c95468d046e472212bca63a99d1e04bb2
547d1c1a43e4a72fe50f3905a96f8e47e0cea13c3f23c77f3b9bd0a2b05f3181
f0c2cb6901bfe6c1c3333a34c933a7383a13461c866874b1b7b24d00b95e1afa
74b66bf6fb5f1849f4f8200b428b84a600c32ed7539148bdc7c478fe77aad531
89b047c9b0985167401094dbbc506cfc3e0af48f03b8f420adb236fc55ee6973
9e6872b80a1feb8888622f28154b8bdc58a73afb9c4dde5e74510fa44c78234b
e9027e6be037ee05ca2b9e3210b1d4b3383941903a6357cf05cbb1462fccaf48
81c453b64200eb97390f700b2fb6eab9a27c6044b517e312bf029c3050ae9f4b
ae690adb63f916a3f06ee59fe9b9c736145a0d5cd8007d06253b5cfa00df0c78
83c9ca684d2c61cba8d89526e8dc06cedd954842262513d0042f30f925694dee
4f8892f079660d74e15107e59b3a8698cf75a023cd4c28e0ecde0a32ca30e2f8
679c17d943fec9c3a46ad9e25cdb1c2dfc5e4e1b1816c558c5cbb8bb99c64b8d
e4e76c0c2ddf86e9741e4564845acefe3887d1773226dfa9cffcb5bcebca9c79
09f0c6a59c417e753a1021340cf80ab3ef3369a7809e7da3d3789549490c1b9f
Total reclaimed space: 336B
#清除不再使用的镜像
[root@ubuntu1804 ~]#docker system  prune -f -a

1.5 实战案例: 利用 Docker 快速部署自动化运维平台

1.5.1 项目说明

Spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台,整合了主机管理、主机批量执行、主机在线终端、文件在线上传下载、应用发布部署、在线任务计划、配置中心、监控、报警等一系列功能

特性

  • 批量执行: 主机命令在线批量执行在线终端: 主机支持浏览器在线终端登录文件管理: 主机文件在线上传下载

  • 任务计划: 灵活的在线任务计划

  • 发布部署: 支持自定义发布部署流程

  • 配置中心: 支持 KV、文本、json 等格式的配置

  • 监控中心: 支持站点、端口、进程、自定义等监控

  • 报警中心: 支持短信、邮件、钉钉、微信等报警方式

  • 优雅美观: 基于 Ant Design 的 UI 界面

  • 开源免费: 前后端代码完全开源

官网地址: https://www.spug.dev/

使用文档:https://www.spug.dev/docs/about-spug/

gitee链接: https://gitee.com/openspug/spug

1.5.2 部署过程

官方说明:

https://www.spug.dev/docs/install-docker/
1.5.2.1 安装docker
[root@ubuntu2004 ~]#apt -y install docker.io

1.5.2.2 拉取镜像

[root@ubuntu1804 ~]#docker pull registry.aliyuncs.com/openspug/spug
1.5.2.3 启动容器
[root@ubuntu1804 ~]#docker run -d --restart=always --name=spug -p 80:80
registry.aliyuncs.com/openspug/spug
# 持久化存储启动命令:
# mydata指的是本地磁盘路径,也可以是其他目录,但需要保证映射的本地磁盘路径已经存在,/data是容
器内代码和数据初始化存储的路径
$ docker run -d--restart=always --name=spug -p80:80 -v /mydata/:/data
registry.aliyuncs.com/openspug/spug
1.5.2.4 初始化

以下操作会创建一个用户名为 admin 密码为 123456 的管理员账户,可自行替换管理员账户。

[root@ubuntu1804 ~]#docker exec spug init_spug admin 123456
Migrations for'account':
  data/spug/spug_api/apps/account/migrations/0001_initial.py
- Create model Role
- Create model User
- Add field created_by to role
- Create model History
Migrations for'alarm':
  data/spug/spug_api/apps/alarm/migrations/0001_initial.py
- Create model Alarm
- Create model Group
- Create model Contact
Migrations for'config':
  data/spug/spug_api/apps/config/migrations/0001_initial.py
- Create model Service
- Create model Environment
- Create model ConfigHistory
- Create model Config
Migrations for'exec':
  data/spug/spug_api/apps/exec/migrations/0001_initial.py
- Create model ExecTemplate
Migrations for'host':
  data/spug/spug_api/apps/host/migrations/0001_initial.py
- Create model Host
Migrations for'monitor':
  data/spug/spug_api/apps/monitor/migrations/0001_initial.py
- Create model Detection
Migrations for'notify':
  data/spug/spug_api/apps/notify/migrations/0001_initial.py
- Create model Notify
Migrations for'schedule':
  data/spug/spug_api/apps/schedule/migrations/0001_initial.py
- Create model History
- Create model Task
Migrations for'setting':
  data/spug/spug_api/apps/setting/migrations/0001_initial.py
- Create model Setting
Migrations for'app':
  data/spug/spug_api/apps/app/migrations/0001_initial.py
- Create model App
- Create model Deploy
- Create model DeployExtend1
- Create model DeployExtend2
Migrations for'deploy':
  data/spug/spug_api/apps/deploy/migrations/0001_initial.py
- Create model DeployRequest
Operations to perform:
  Apply all migrations: account, alarm, app, config, deploy, exec, host, monitor,
notify, schedule, setting
Running migrations:
  Applying account.0001_initial... OK
  Applying alarm.0001_initial... OK
  Applying config.0001_initial... OK
  Applying app.0001_initial... OK
  Applying deploy.0001_initial... OK
  Applying exec.0001_initial... OK
  Applying host.0001_initial... OK
  Applying monitor.0001_initial... OK
  Applying notify.0001_initial... OK
  Applying schedule.0001_initial... OK
  Applying setting.0001_initial... OK
初始化/更新成功
创建用户成功
[root@ubuntu1804 ~]#
1.5.2.5 访问测试

在浏览器中输入 http://localhost:80 访问。

用户名: admin  密码: 123456

2 Docker 镜像制作和管理

2.1 Docker 镜像说明

2.1.1 Docker 镜像中有没有内核

从镜像大小上面来说,一个比较小的镜像只有1MB多点或几MB,而内核文件需要几十MB, 因此镜像里面是没有内核的,镜像在被启动为容器后将直接使用宿主机的内核,而镜像本身则只提供相应的 rootfs,即系统正常运行所必须的用户空间的文件系统,比如: /dev/,/proc,/bin,/etc等目录,容器当中/boot目录是空的,而/boot当中保存的就是与内核相关的文件和目录。

2.1.2 为什么没有内核

由于容器启动和运行过程中是直接使用了宿主机的内核,不会直接调用物理硬件,所以也不会涉及到硬件驱动,因此也无需容器内拥有自已的内核和驱动。而如果使用虚拟机技术,对应每个虚拟机都有自已独立的内核

2.1.3 容器中的程序后台运行会导致此容器启动后立即退出

Docker容器如果希望启动后能持续运行,就必须有一个能前台持续运行的进程,如果在容器中启动传统的服务,如:httpd,php-fpm等均为后台进程模式运行,就导致 docker 在前台没有运行的应用,这样的容器启动后会立即退出。所以一般会将服务程序以前台方式运行,对于有一些可能不知道怎么实现前台运行的程序,只需要在你启动的该程序之后添加类似于 tail ,top 这种可以前台运行的程序即可. 比较常用的方法,如 tail - f /etc/hosts 。

范例:

#httpd
ENTRYPOINT [ "/usr/sbin/apache2" ]
CMD ["-D", "FOREGROUND"]
#nginx
ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]
#用脚本运行容器
cat run_haproxy.sh
#!/bin/bash
haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts
tail -n1 Dockerfile
CMD ["run_haproxy.sh"]

2.1.4 docker 镜像生命周期

2.1.5 制作镜像方式

Docker 镜像制作类似于虚拟机的镜像(模版)制作,即按照公司的实际业务需求将需要安装的软件、相关配置等基础环境配置完成,然后将其做成镜像,最后再批量从镜像批量生成容器实例,这样可以极大的简化相同环境的部署工作.

Docker的镜像制作分为手动制作(基于容器)和自动制作(基于DockerFile),企业通常都是基于 Dockerfile制作镜像

docker commit #通过修改现有容器,将之手动构建为镜像
docker build  #通过Dockerfile文件,批量构建为镜像

2.2 将现有容器通过 docker commit 手动构建镜像

2.2.1 基于容器手动制作镜像步骤

docker commit 格式

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
#选项
-a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-
team.com>")
-c, --change list      Apply Dockerfile instruction to the created image
-m, --message string   Commit message
-p, --pause            Pause container during commit (default true)
#说明:
制作镜像和CONTAINER状态无关,停止状态也可以制作镜像
如果没有指定[REPOSITORY[:TAG]],REPOSITORY和TAG都为<none>
提交的时候标记TAG号:  生产当中常用,后期可以根据TAG标记创建不同版本的镜像以及创建不同版本的容器

基于容器手动制作镜像步骤具体如下:

  1. 下载一个系统的官方基础镜像,如: CentOS 或 Ubuntu

  2. 基于基础镜像启动一个容器,并进入到容器

  3. 在容器里面做配置操作

安装基础命令

配置运行环境安装服务和配置服务

放业务程序代码

  1. 提交为一个新镜像 docker commit

  2. 基于自己的的镜像创建容器并测试访问

2.2.2 实战案例: 基于 busybox 制作 httpd 镜像

[root@ubuntu1804 ~]#docker run -it --name b1 busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # mkdir /data/html -p
/ # echo httpd website in busybox > /data/html/index.html
/ # httpd --help
BusyBox v1.32.0 (2020-06-27 00:20:57 UTC) multi-call binary
Usage: httpd [-ifv[v]] [-c CONFFILE] [-p [IP:]PORT] [-u USER[:GRP]] [-r REALM] [-
h HOME]
or httpd -d/-e/-m STRING
Listen for incoming HTTP requests
-i      Inetd mode
-f      Don't daemonize
-v[v]       Verbose 显示访问日志
-p [IP:]PORT    Bind to IP:PORT (default *:80)
-u USER[:GRP]   Set uid/gid after binding to port
-r REALM    Authentication Realm for Basic Authentication
-h HOME     Home directory (default .)
-c FILE     Configuration file (default {/etc,HOME}/httpd.conf)
-m STRING   MD5 crypt STRING
-e STRING   HTML encode STRING
-d STRING   URL decode STRING
/ # exit
#格式1
[root@ubuntu1804 ~]#docker commit -a "wang<root@wangxiaochun.com>" -c 'CMD
/bin/httpd -fv -h /data/html' -c "EXPOSE 80" b1 httpd-busybox:v1.0
#格式2
[root@ubuntu1804 ~]#docker commit -a "wang<root@wangxiaochun.com>" -c 'CMD
["/bin/httpd", "-f", "-v","-h", "/data/html"]' -c "EXPOSE 80" b1 httpd-
busybox:v1.0
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
httpd-busybox       v1.0                e7883146c119        6 minutes ago
1.22MB
[root@ubuntu1804 ~]#docker run  -d -P --name httpd01 httpd-busybox:v1.0
ce95174c6385392b9699d12d1a86d7f81bc4dde1400a071ce17d9c78d905cb12
[root@ubuntu1804 ~]#docker port httpd01
80/tcp -> 0.0.0.0:32783
[root@ubuntu1804 ~]#docker inspect -f "
{{.NetworkSettings.Networks.bridge.IPAddress}}" httpd01
172.17.0.2
#对应格式1
[root@ubuntu1804 ~]#docker inspect -f "{{.Config.Cmd}}" httpd01
[/bin/sh -c /bin/httpd -f-h /data/html]
#对应格式2
[root@ubuntu1804 ~]#docker inspect -f "{{.Config.Cmd}}" httpd01
[/bin/httpd -f-h /data/html]
[root@ubuntu1804 ~]#docker exec -it httpd01 sh
/ # pstree -p
httpd(1)
/ # ps aux
PID   USER     TIME  COMMAND
1 root      0:00 /bin/httpd -fv-h /data/html
7 root      0:00 sh
13 root      0:00 ps aux
/ #
[root@ubuntu1804 ~]#curl 172.17.0.2
httpd website in busybox
[root@ubuntu1804 ~]#curl 127.0.0.1:32783
httpd website in busybox
#再次制作镜像v2.0版
[root@ubuntu1804 ~]#docker commit -a "wang<root@wangxiaochun.com>" b1  httpd-
busybox:v2.0
[root@ubuntu1804 ~]#docker run -d --name web2 -p 81:80   httpd-busybox:v2.0
/bin/httpd -fv -h /data/html
c47bce0de75dcdf88266467accbe0a119190999c23cec32d6af8b8500aed96d4

2.2.3 实战案例: 基于官方镜像生成的容器制作 tomcat 镜像

2.2.3.1 下载官方的tomcat镜像并运行
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@ubuntu1804 ~]#docker run -d -p 8080:8080 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
e9afc4f90ab0: Pull complete
989e6b19a265: Pull complete
af14b6c2f878: Pull complete
5573c4b30949: Pull complete
fb1a405f128d: Pull complete
612a9f566fdc: Pull complete
4226f9b63dac: Pull complete
cb8bfe875d7f: Pull complete
5aa366608b6d: Pull complete
4b7c9018ca5f: Pull complete
Digest: sha256:46456ccf216f2fde198844d5c7d511f60e3ffc2ea3828e0cce9a2eed566e48e2
Status: Downloaded newer image for tomcat:latest
6fcc5f7c1c7ce7be0b12007e310fc044e1077d489e1292b22621de55e302c455
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS                    NAMES
6fcc5f7c1c7c        tomcat              "catalina.sh run"42 seconds ago
Up 40 seconds       0.0.0.0:8080->8080/tcp   focused_wilbur
[root@ubuntu1804 ~]#curl -I 127.0.0.1:8080
HTTP/1.1 404
Content-Type: text/html;charset=utf-8
Content-Language: en
Transfer-Encoding: chunked
Date: Mon, 20 Jul 202015:33:21 GMT
2.2.3.2 修改容器
[root@ubuntu1804 ~]#docker exec -it 6fcc5f7c1c7c bash
root@6fcc5f7c1c7c:/usr/local/tomcat# ls
BUILDING.txt     LICENSE  README.md  RUNNING.txt  conf  logs        temp
webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          lib   native-jni-lib
webapps  work
root@6fcc5f7c1c7c:/usr/local/tomcat# ls webapps
root@6fcc5f7c1c7c:/usr/local/tomcat# ls webapps.dist/
ROOT  docs  examples  host-manager  manager
root@6fcc5f7c1c7c:/usr/local/tomcat# cp -a webapps.dist/* webapps/
root@6fcc5f7c1c7c:/usr/local/tomcat# ls webapps/
ROOT  docs  examples  host-manager  manager
root@6fcc5f7c1c7c:/usr/local/tomcat# exit
exit
[root@ubuntu1804 ~]#curl -I 127.0.0.1:8080
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 20 Jul 202015:34:24 GMT
2.2.3.3 提交新镜像
[root@ubuntu1804 ~]#docker commit -m "add webapps app" -a "wangxiaochun"
6fcc5f7c1c7c tomcat:9.0.37-v1
sha256:b8d669ebf99e65d5ed69378d0d53f054e7de4865d335ab7aa0a7a5508e1369f7
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
tomcat              9.0.37-v1           b8d669ebf99e        4 seconds ago
652MB
tomcat              latest              df72227b40e1        3 days ago
647MB
[root@ubuntu1804 ~]#docker history tomc
at:9.0.37-v1
IMAGE CREATED CREATED BY
SIZE COMMENT
b8d669ebf99e14 minutes ago catalina.sh run
4.84MB add webapps app
df72227b40e13 days ago /bin/sh-c #(nop) CMD ["catalina.sh"
"run"] 0B
<missing>3 days ago
/bin/sh-c #(nop) EXPOSE 8080
0B
<missing>3 days ago /bin/sh-c set -e &&
nativeLines="$(catalin… 0B
<missing> 3 days ago /bin/sh -c set -eux;
savedAptMark="$(apt-m… 20MB
<missing>3 days ago /bin/sh-c #(nop) ENV
TOMCAT_SHA512=077c3e6… 0B
<missing>3 days ago /bin/sh-c #(nop) ENV
TOMCAT_VERSION=9.0.37 0B
<missing>3 days ago
0B
/bin/sh-c #(nop) ENV TOMCAT_MAJOR=9
<missing>3 days ago /bin/sh-c #(nop) ENV
GPG_KEYS=05AB33110949… 0B
<missing>3 days ago /bin/sh-c #(nop) ENV
LD_LIBRARY_PATH=/usr/… 0B
<missing>3 days ago /bin/sh-c #(nop) ENV
TOMCAT_NATIVE_LIBDIR=… 0B
<missing>3 days ago /bin/sh-c #(nop) WORKDIR
/usr/local/tomcat 0B
<missing>3 days ago
/bin/sh-c mkdir -p "$CATALINA_HOME"
0B
<missing>3 days ago /bin/sh-c #(nop) ENV
PATH=/usr/local/tomca… 0B
<missing>3 days ago /bin/sh-c #(nop) ENV
CATALINA_HOME=/usr/lo… 0B
<missing>3 days ago
/bin/sh-c #(nop) CMD ["jshell"]
0B
<missing>3 days ago /bin/sh-c set -eux;dpkgArch="$(dpkg
--pr… 323MB
<missing> 3 days ago /bin/sh -c #(nop) ENV
JAVA_URL_VERSION=11.0… 0B
<missing>3 days ago /bin/sh-c #(nop) ENV
JAVA_BASE_URL=https:/… 0B
<missing>3 days ago /bin/sh-c #(nop) ENV
JAVA_VERSION=11.0.8 0B
<missing>5 weeks ago /bin/sh-c {echo '#/bin/sh'; echo 'echo
"$J… 27B
<missing>5 weeks ago /bin/sh-c #(nop) ENV
PATH=/usr/local/openj… 0B
<missing>5 weeks ago /bin/sh-c #(nop) ENV
JAVA_HOME=/usr/local/… 0B
<missing>5 weeks ago
/bin/sh-c #(nop) ENV LANG=C.UTF-8
0B
<missing>5 weeks ago /bin/sh-c set -eux; apt-get update;

apt-g…11.1MB
<missing>           5 weeks ago         /bin/sh -c apt-get update && apt-get
install…   146MB
<missing>           5 weeks ago         /bin/sh -cset-ex;  if ! command -v gpg
> /…   17.5MB
<missing>           5 weeks ago         /bin/sh -c apt-get update && apt-get
install…   16.5MB
<missing>           5 weeks ago         /bin/sh -c#(nop)  CMD ["bash"]
        0B
<missing>           5 weeks ago         /bin/sh -c#(nop) ADD
file:1ab357efe422cfed5…   114MB
[root@ubuntu1804 ~]#docker inspect tomcat:9.0.37-v1 |tail -n20
"Type": "layers",
"Layers": [
"sha256:8803ef42039dcbe936755e9baae4bb7b19cb0fb6a438eb3992950cd0afef8e4f",
"sha256:c2c789d2d3c5fc15428921b5316a63907d8c312c5508cbac9a704bd30bcc740d",
"sha256:527ade4639e08d1b2ba9d0d46f3b43433310a2e8674ae808aeef5502b099ff3c",
"sha256:2e5b4ca91984c19a75bad687aedebf02609511a033aa0d3d15ac915593279718",
"sha256:f5181c7ef9028578eb0040a0051ce940c3f9ba62a51d3eb02ad52c3724db3e9b",
"sha256:f73b2345c404b2a65abc66ab68af6b112aafb9d2583416d2eb84a47139e4626e",
"sha256:afa12e842ed4e07340351e64318d3149b3ec8430f631d9bbe8e0d3ac24046cff",
"sha256:31d7eb4c72a987dd8742add724562e0e800998cb7a57f7ed0c6dffa0587b5af4",
"sha256:4b1785e8102bdcc4f7bb759d084e1f03b2b26c19fa42aa91c879ce26f36381d7",
"sha256:aca03caac7b1c380545a00f970a42079bbc8928c9785492e9e289f60206b01e1",
"sha256:860b0f130267d185ed8328a5fcd3ecd040a7afec64b63f7551c5f3af80709db5"
            ]
        },
"Metadata": {
"LastTagTime": "2020-07-20T23:42:00.403415564+08:00"
        }
    }
]
#删除当前的容器
[root@ubuntu1804 ~]#docker rm -f 6fcc5f7c1c7c
6fcc5f7c1c7c
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES

2.2.3.4 利用新镜像启动容器

[root@ubuntu1804 ~]#docker run  -d -p 8080:8080 --name tomcat tomcat:9.0.37-v1
97688b4c835da4b222f3ca15af36b8c27d4e60ff33480c314daf3f123b1cb50c
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS                    NAMES
97688b4c835d        tomcat:9.0.37-v1    "catalina.sh run"6 seconds ago
Up 5 seconds        0.0.0.0:8080->8080/tcp   tomcat
2.2.3.5 测试新镜像启动的容器

浏览器访问 http://10.0.0.100:8080/ 可以看到下面显示

2.2.4 实战案例: 基于Ubuntu的基础镜像利用 apt 安装手动制作 nginx 的镜像

2.2.4.1 启动Ubuntu基础镜像并实现相关的配置
[root@ubuntu1804 ~]#docker run -it -p 80 --name nginx_ubuntu ubuntu bash
root@705148273eac:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-
policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
root@705148273eac:/# ll /etc/apt/sources.list
-rw-r--r--1 root root 2743 Jul  302:00 /etc/apt/sources.list
root@705148273eac:/# cat > /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted
universe multiverse
^C
root@705148273eac:/# apt update
Get:1 http://mirrors.aliyun.com/ubuntu focal InRelease [265 kB]
Get:2 http://mirrors.aliyun.com/ubuntu focal-security InRelease [107 kB]
Get:3 http://mirrors.aliyun.com/ubuntu focal-updates InRelease [111 kB]
Get:4 http://mirrors.aliyun.com/ubuntu focal-proposed InRelease [265 kB]
Get:5 http://mirrors.aliyun.com/ubuntu focal-backports InRelease [98.3 kB]
Get:6 http://mirrors.aliyun.com/ubuntu focal/restricted Sources [7198 B]
Get:7 http://mirrors.aliyun.com/ubuntu focal/multiverse Sources [208 kB]
......
Fetched 28.7 MB in 6s (4651 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@705148273eac:/# apt -y install nginx
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
........
Configuring tzdata
------------------
Please select the geographic area in which you live. Subsequent configuration
questions will narrow this down
by presenting a list of cities, representing the time zones in which they are
located.
1. Africa   3. Antarctica  5. Arctic  7. Atlantic  9. Indian    11. SystemV
13. Etc
2. America  4. Australia   6. Asia    8. Europe    10. Pacific  12. US
Geographic area: 6
Please select the city or region corresponding to your time zone.
1. Aden      16. Brunei       31. Hong_Kong    46. Kuala_Lumpur  61. Pyongyang
76. Tehran
2. Almaty    17. Chita        32. Hovd         47. Kuching       62. Qatar
77. Tel_Aviv
3. Amman     18. Choibalsan   33. Irkutsk      48. Kuwait        63. Qostanay
78. Thimphu
4. Anadyr    19. Chongqing    34. Istanbul     49. Macau         64. Qyzylorda
79. Tokyo
5. Aqtau     20. Colombo      35. Jakarta      50. Magadan       65. Rangoon
80. Tomsk
6. Aqtobe    21. Damascus     36. Jayapura     51. Makassar      66. Riyadh
81. Ujung_Pandang
7. Ashgabat  22. Dhaka        37. Jerusalem    52. Manila        67. Sakhalin
82. Ulaanbaatar
8. Atyrau    23. Dili         38. Kabul        53. Muscat        68. Samarkand
83. Urumqi
9. Baghdad   24. Dubai        39. Kamchatka    54. Nicosia       69. Seoul
84. Ust-Nera
10. Bahrain  25. Dushanbe     40. Karachi      55. Novokuznetsk  70. Shanghai
85. Vientiane
11. Baku     26. Famagusta    41. Kashgar      56. Novosibirsk   71. Singapore
86. Vladivostok
12. Bangkok  27. Gaza         42. Kathmandu    57. Omsk          72.
Srednekolymsk  87. Yakutsk
13. Barnaul  28. Harbin       43. Khandyga     58. Oral          73. Taipei
88. Yangon
14. Beirut   29. Hebron       44. Kolkata      59. Phnom_Penh    74. Tashkent
89. Yekaterinburg
15. Bishkek  30. Ho_Chi_Minh  45. Krasnoyarsk  60. Pontianak     75. Tbilisi
90. Yerevan
Time zone: 70#配置时区
......
Setting up nginx-core (1.18.0-0ubuntu1) ...
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.
Setting up nginx (1.18.0-0ubuntu1) ...
Processing triggers for libc-bin (2.31-0ubuntu9) ...
root@705148273eac:/# nginx -v
nginx version: nginx/1.18.0 (Ubuntu)
root@705148273eac:~# grep include /etc/nginx/nginx.conf
include /etc/nginx/modules-enabled/*.conf;
    include /etc/nginx/mime.types;
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
root@705148273eac:~# grep root /etc/nginx/sites-enabled/default
    root /var/www/html;
# deny access to .htaccess files, if Apache's document root
#   root /var/www/example.com;
root@705148273eac:/# echo Nginx Website in Docker >  /var/www/html/index.html
root@705148273eac:/# exit
exit

2.2.4.2 提交为镜像

[root@ubuntu1804 ~]#docker commit -a 'wangxiaochun' -m 'nginx-ubuntu:20.04'
nginx_ubuntu nginx_ubuntu20.04:v1.18.0
sha256:2c789ec21d2545c9bfc4af6d4380878153d52fcc03890aac755d09112631742a
[root@ubuntu1804 ~]#docker images
REPOSITORY             TAG                 IMAGE ID            CREATED
  SIZE
nginx_ubuntu20.04      v1.18.0             2c789ec21d25        22 seconds ago
   179MB
2.2.4.3 从制作的新镜像启动容器并测试访问
[root@ubuntu1804 ~]#docker run -d -p 80 --name nginx-web
nginx_ubuntu20.04:v1.18.0 nginx -g 'daemon off;'
b0c8496a497ba60f7b5bc430b075b00d40c7ace24068e71decac625e84df40de
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED
            STATUS              PORTS                   NAMES
b0c8496a497b        nginx_ubuntu20.04:v1.18.0   "nginx -g 'daemon of…"7
seconds ago       Up 5 seconds        0.0.0.0:32771->80/tcp   nginx-web
[root@ubuntu1804 ~]#docker port nginx-web
80/tcp -> 0.0.0.0:32771
[root@ubuntu1804 ~]#curl http://127.0.0.1:32771
Nginx Website in Docker

2.2.5 实战案例: 基于CentOS的基础镜像利用 yum 安装手动制作 nginx 的镜像

2.2.5.1下载基础镜像并初始化系统

基于某个基础镜像之上重新制作,因此需要先有一个基础镜像,本次使用官方提供的centos镜像为基础

[root@ubuntu1804 ~]#docker pull centos:centos7.7.1908
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
[root@ubuntu1804 ~]#docker run -it centos:centos7.7.1908 bash

# 修改时区

[root@9caa8742e6ce /]#rm -f /etc/localtime
[root@9caa8742e6ce /]#ln -s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[root@9caa8742e6ce /]# yum -y install wget
[root@9caa8742e6ce /]# rm -rf /etc/yum.repos.d/*

# 更改 yum 源

[root@9caa8742e6ce /]# wget -P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/Centos-7.repo
[root@9caa8742e6ce /]# wget -P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/epel-7.repo
2.2.5.2 安装相关软件和工具
#yum安装nginx
[root@9caa8742e6ce /]# yum install nginx –y
#安装常用命令
[root@9caa8742e6ce /]# yum install -y vim curl iproute net-tools
#清理yum缓存
[root@9caa8742e6ce /]# rm -rf /var/cache/yum/*
2.2.5.3 修改服务的配置信息关闭服务后台运行
#关闭nginx后台运行
[root@9caa8742e6ce /]# vim /etc/nginx/nginx.conf
user nginx;
daemon off; #关闭后台运行
2.2.5.4 准备程序和数据
#自定义web界面
[root@9caa8742e6ce ~]# rm -f /usr/share/nginx/html/index.html
[root@9caa8742e6ce ~]# echo "Nginx Page in Docker" >
/usr/share/nginx/html/index.html
2.2.5.5 提交为镜像

docker commit 命令在宿主机基于容器ID 提交为镜像

#不关闭容器的情况,将容器提交为镜像
[root@ubuntu1804 ~]#docker commit -a "root@wangxiaochun.com" -m "nginx yum v1" -
c "EXPOSE 80 443" 9caa8742e6ce wang/centos7-nginx:1.16.1.v1
sha256:e9d09cc585ed8ee1544b1e68de326ea6dcbe99577fc9b2edad9ab481b7a7e7ec
[root@ubuntu1804 ~]#docker images
REPOSITORY           TAG                 IMAGE ID            CREATED
SIZE
wang/centos7-nginx   1.16.1.v1           e9d09cc585ed        4 seconds ago
442MB
centos               centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.2.5.6 从制作的镜像启动容器
[root@ubuntu1804 ~]#docker run -d -p 8080:80 --name my-centos-nginx
wang/centos7-nginx:1.16.1.v1 /usr/sbin/nginx
c60f8373a14210bb3aa06ce03c2258a4b912033b0650ef690f9245fc3afc5bf1
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                          COMMAND             CREATED
          STATUS              PORTS                           NAMES
c60f8373a142        wang/centos7-nginx:1.16.1.v1   "/usr/sbin/nginx"6 seconds
ago       Up 5 seconds        443/tcp, 0.0.0.0:8080->80/tcp   my-centos-nginx
9caa8742e6ce        centos:centos7.7.1908          "bash"35
minutes ago      Up 35 minutes
thirsty_hypatia
[root@ubuntu1804 ~]#
2.2.5.7 访问测试镜像
[root@ubuntu1804 ~]#curl 127.0.0.1:8080
Nginx Page in Docker
[root@ubuntu1804 ~]#

2.2.6 实战案例: 基于CentOS 基础镜像手动制作编译版本 nginx 镜像

在CentOS 基础镜像的容器之上手动编译安装nginx,然后再将此容器提交为镜像

2.2.6.1 下载镜像并初始化系统
[root@ubuntu1804 ~]#docker pull centos:centos7.7.1908
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
[root@ubuntu1804 ~]#docker run -it centos:centos7.7.1908 /bin/bash
#生成yum源配置
[root@86a48908bb97 /]# yum -y install wget
[root@64944257fa88 /]# rm -rf /etc/yum.repos.d/*
[root@64944257fa88 /]# wget -P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/Centos-7.repo http://mirrors.aliyun.com/repo/epel-
7.repo
2.2.6.2 编译安装 nginx
[root@64944257fa88 /]# useradd -r -s /sbin/nologin nginx
#安装基础包
[root@64944257fa88 /]# yum -y install gcc gcc-c++ automake pcre pcre-devel zlib
zlib-devel openssl openssl-devel
[root@64944257fa88 /]# cd /usr/local/src
[root@64944257fa88 src]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@64944257fa88 src]# tar xf nginx-1.16.1.tar.gz
[root@64944257fa88 src]# cd nginx-1.16.1
[root@64944257fa88 nginx-1.16.1]# ./configure  --prefix=/apps/nginx
[root@64944257fa88 nginx-1.16.1]# make && make install
[root@64944257fa88 nginx-1.16.1]# rm -rf nginx*
[root@64944257fa88 nginx-1.16.1]# rm -rf /var/cache/yum/*
2.2.6.3 关闭 nginx 后台运行
[root@64944257fa88 nginx-1.16.1]# cd /apps/nginx/
[root@64944257fa88 nginx]# ls
conf  html  logs  sbin
[root@64944257fa88 nginx]# vi conf/nginx.conf
user nginx;
daemon off;
[root@64944257fa88 nginx]# ln -s /apps/nginx/sbin/nginx  /usr/sbin/
[root@64944257fa88 nginx]# ll /usr/sbin/nginx
lrwxrwxrwx 1 root root 22 Jan 2805:29 /usr/sbin/nginx -> /apps/nginx/sbin/nginx
2.2.6.4 准备相关数据自定义web界面
[root@64944257fa88 nginx]# echo "Nginx Test Page in Docker" >
/apps/nginx/html/index.html
2.2.6.5 提交为镜像
#不要退出容器,在另一个终端窗口执行以下命令
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                   COMMAND             CREATED
  STATUS              PORTS               NAMES
64944257fa88        centos:centos7.7.1908   "/bin/bash"18 seconds ago
   Up 17 seconds                           stupefied_albattani
[root@ubuntu1804 ~]#docker commit -m "nginx1.6.1" 64944257fa88 -c "CMD nginx"
centos7-nginx:1.6.1
sha256:d86d957bb00f35fe09ae38230e1e2d12916f4406e997146c68e34dae7526c079
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos7-nginx       1.6.1               d86d957bb00f        2 minutes ago
486MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.2.6.6 从自己的镜像启动容器
[root@ubuntu1804 ~]#docker run -d -p 80:80 centos7-nginx:1.6.1 nginx
ae90b1abf374138a21f7ed104d14c88f1af23c0b2027c3fe099722fd7fbad3a4
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED
STATUS              PORTS                NAMES
ae90b1abf374        centos7-nginx:1.6.1   "nginx"             About a minute ago
  Up About a minute   0.0.0.0:80->80/tcp   naughty_thompson

备注: 最后面的nginx是运行的命令,即镜像里面要运行一个nginx命令,所以前面软链接到/usr/sbin/nginx,目的为了让系统不需要指定路径就可以执行此命令

2.2.6.7 访问测试
[root@ubuntu1804 ~]#curl 127.0.0.1
Nginx Test Page in Docker
2.2.6.8 查看Nginx访问日志和进程
[root@ubuntu1804 ~]#docker exec -it ae90b1abf374 bash
[root@ae90b1abf374 /]# cat /apps/nginx/logs/access.log
172.17.0.1 -- [28/Jan/2020:05:40:51 +0000] "GET / HTTP/1.1"20026"-"
"curl/7.58.0"
[root@ae90b1abf374 /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          10.0  0.2  205722468 ?        Ss   05:40   0:00 nginx: master
process nginx
nginx         60.0  0.3  210243104 ?        S    05:40   0:00 nginx: worker
process
root          70.3  0.2  118402928 pts/0    Ss   05:45   0:00 bash
root         210.0  0.3  517643344 pts/0    R+05:46   0:00 ps aux

2.3 利用 DockerFile 文件执行 docker build 自动构建镜像

2.3.1 Dockfile 使用详解

2.3.1.1 Dockerfile 介绍

DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile 更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的 DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似与shell脚本一样,可以方便高效的制作镜像

Docker守护程序 Dockerfile 逐一运行指令,如有必要,将每个指令的结果提交到新镜像,然后最终输出新镜像的ID。Docker守护程序将自动清理之前发送的上下文

请注意,每条指令都是独立运行的,并会导致创建新镜像,比如 RUN cd /tmp 对下一条指令不会有任何影响。

Docker将尽可能重用中间镜像层(缓存),以显著加速 docker build 命令的执行过程,这由 Using cache 控制台输出中的消息指示

2.3.1.2 Dockerfile 镜像制作和使用流程

2.3.1.3 Dockerfile文件的制作镜像的分层结构

范例:

#按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
  • [root@ubuntu1804 ~]#mkdir
/data/dockerfile/{web/{nginx,apache,tomcat,jdk},system/{centos,ubuntu,alpine,deb
ian}} -p
  • [root@ubuntu1804 ~]#tree /data/dockerfile/
/data/dockerfile/
├── system
  • │ ├── alpine
│   ├── centos
│   ├── debian
│   └── ubuntu
└── web
    ├── apache
    ├── jdk
    ├── nginx
    └── tomcat
10 directories, 0 files
[root@ubuntu1804 ~]#
2.3.1.4 Dockerfile 文件格式

Dockerfile 是一个有特定语法格式的文本文件

dockerfile 官方说明: https://docs.docker.com/engine/reference/builder/

帮助: man 5 dockerfile

Dockerfile 文件说明

  • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写

  • 使用 # 开始作为注释

  • 每一行只支持一条指令,每条指令可以携带多个参数

  • 指令按文件的顺序从上至下进行执行

  • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令

  • 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面

2.3.1.5 Dockerfile 相关指令

dockerfile 文件中的常见指令:

ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR

2.3.1.5.1 FROM: 指定基础镜像

定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。

FROM 就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境

基础镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件.如果找不到指定的镜像文件, docker build会返回一个错误信息

如何选择合适的镜像呢?

对于不同的软件官方都提供了相关的docker镜像,比如: nginx、redis、mysql、httpd、tomcat等服务类的镜像,也有操作系统类,如: centos、ubuntu、debian等。建议使用官方镜像,比较安全。

格式:

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
#说明:
--platform 指定镜像的平台,比如:  linux/amd64, linux/arm64, or windows/amd64
tag 和 digest是可选项,如果不指定,默认为latest

说明: 关于scratch 镜像

FROM scratch
参考链接:
https://hub.docker.com/_/scratch?tab=description
https://docs.docker.com/develop/develop-images/baseimages/
该镜像是一个空的镜像,可以用于构建busybox等超小镜像,可以说是真正的从零开始构建属于自己的镜像
该镜像在构建基础镜像(例如debian和busybox)或超最小镜像(仅包含一个二进制文件及其所需内容,例
如:hello-world)的上下文中最有用。

范例:

FROM scratch #所有镜像的起源镜像,相当于JAVA语言中的Object类
FROM ubuntu
FROM ubuntu:bionic
FROM debian:buster-slim
2.3.1.5.2 LABEL: 指定镜像元数据

可以指定镜像元数据,如: 镜像作者等

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

范例:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."

一个镜像可以有多个label ,还可以写在一行中,即多标签写法,可以减少镜像的的大小

范例: 多标签写法

#一行格式
LABEL multi.label1="value1" multi.label2="value2"other="value3"
#多行格式
LABEL multi.label1="value1" \
      multi.label2="value2" \
other="value3"

docker inspect 命令可以查看LABEL

范例:

"Labels": {
"com.example.vendor": "ACME Incorporated"
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple
lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
},

MAINTAINER: 指定维护者信息

此指令已过时,用LABEL代替

MAINTAINER <name>

范例:

MAINTAINER wangxiaochun <root@wangxiaochun.com>
#用LABEL代替
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
2.3.1.5.3 RUN: 执行 shell命令

RUN 指令用来在 构建镜像阶段 需要执行 FROM 指定镜像所支持的Shell命令。

通常各种基础镜像一般都支持丰富的shell命令

注意: RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个 shell命令通过 && 连接一起成为在一条指令

每个RUN都是独立运行的,和前一个RUN无关

#shell 格式: 相当于 /bin/sh -c  <命令>  此种形式支持环境变量
RUN <命令>
#exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN ["executable","param1","param2"...]
#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]

说明:

shell格式中,<command>通常是一个shell命令,且以"/bin/sh -c”来运行它,这意味着此进程在容器中
的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收
不到SIGTERM信号
exec格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递
给命令的选项或参数;然而,此种格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变
量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换
为类似下面的格式。
RUN ["/bin/bash", "-c", "<executable>", "<param1>"]

范例:

RUN echo'<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
RUN ["/bin/bash", "-c", "echo hello world"]
RUN yum -y install epel-release \
      && yum -y install nginx \
      && rm-rf /usr/share/nginx/html/*
      && echo"<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html

范例: 多个前后RUN 命令独立无关和shell命令不同

#world.txt并不存放在/app内
RUN cd /app
RUN echo"hello" > world.txt
2.3.1.5.4 ENV: 设置环境变量

ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY或${KEY}进行引用, 并在容器运行时保持

#变量赋值格式1
ENV <key> <value>   #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成
部分
#变量赋值格式2
ENV <key1>=<value1> <key2>=<value2> \  #此格式可以支持多个key赋值,定义多个变量建议使用,
减少镜像层
    <key3>=<value3> ...
#如果<value>中包含空格,可以以反斜线\进行转义,也可通过对<value>加引号进行标识;另外,反斜线也
可用于续行
#只使用一次变量
RUN <key>=<value> <command>
#引用变量
RUN $key .....
#变量支持高级赋值格式
${key:-word}
${kye:+word}

如果运行容器时如果需要修改变量,可以执行下面通过基于 exec 机制实现

注意: 下面方式只影响容器运行时环境,而不影响构建镜像的过程,即只能覆盖docker run时的环境变量,而不会影响docker build时环境变量的值

docker run -e|--env <key>=<value>
#说明
-e, --env list          #Set environment variables
--env-file filename     #Read in a file of environment variables

示例: 两种格式功能相同

#格式1
ENV myName="John Doe"myDog=Rex\ The\ Dog \
myCat=fluffy
#格式2
ENV myName John Doe
ENV myDog Rex The  Dog
ENV myCat fluffy

范例:

ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl-SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC
/usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

范例:

[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV NAME wang xiao chun
RUN touch$NAME.txt
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#./build.sh v5.0
[root@ubuntu1804 dockerfile]#docker run  --rm  --name c1 test:v5.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d4e1f89aca71
NAME=wang xiao chun
HOME=/root
[root@ubuntu1804 dockerfile]#docker run  --rm -e NAME=mage --name c1 test:v5.0
env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=b23500aa100d
NAME=mage
HOME=/root
[root@ubuntu1804 dockerfile]#docker run  --rm -e NAME=mage --name c1 test:v5.0
ls -l
total 36
drwxr-xr-x    2 root     root         12288 Jun 2700:21 bin
-rw-r--r--1 root     root             0 Jul 2410:05 chun.txt
drwxr-xr-x    5 root     root           340 Jul 2410:05 dev
drwxr-xr-x    1 root     root          4096 Jul 2410:05 etc
drwxr-xr-x    2 nobody   nogroup       4096 Jun 2700:21 home
dr-xr-xr-x  222 root     root             0 Jul 2410:05 proc
drwx------    2 root     root          4096 Jun 2700:21 root
dr-xr-xr-x   13 root     root             0 Jul 2410:05 sys
drwxrwxrwt    2 root     root          4096 Jun 2700:21 tmp
drwxr-xr-x    3 root     root          4096 Jun 2700:21 usr
drwxr-xr-x    4 root     root          4096 Jun 2700:21 var
-rw-r--r--1 root     root             0 Jul 2410:05 wang
-rw-r--r--1 root     root             0 Jul 2410:05 xiao
[root@ubuntu1804 dockerfile]#cat  env.txt
NAME=wang
TITLE=cto
[root@ubuntu1804 dockerfile]#docker run  --rm --env-file env.txt --name c1
test:v5.0 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=88ddf5b73a6b
NAME=wang
TITLE=cto
HOME=/root
2.3.1.5.5 COPY: 复制文本

复制本地宿主机的到容器中的 。

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,建议使用此格
式
#Optionally COPY accepts a flag --from=<name> that can be used to set the source
location to a previous build stage (created with FROM .. AS <name>) that will be
used instead of a build context sent by the user. In case a build stage with a
specified name can’t be found an image with the same name is attempted to be used
instead.

说明:

可以是多个,可以使用通配符,通配符规则满足Go的filepath.Match 规则

filepath.Match 参考链接: https://golang.org/pkg/path/filepath/#Match

  • 必须是build上下文中的路径(为 Dockerfile 所在目录的相对路径), 不能是其父目录中的文件

  • 如果是目录,则其内部文件或子目录会被递归复制, 但目录自身不会被复制

  • 如果指定了多个, 或在中使用了通配符,则必须是一个目录, 且必须以 / 结尾

  • 可以是绝对路径或者是 WORKDIR 指定的相对路径

  • 使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等

  • 如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录

范例:

COPY hom* /mydir/
COPY hom?.txt /mydir/

范例: 多阶段构建

FROM alpine:latest
......
FROM alpine:latest
COPY --from=0 /etc/apk/repositories /etc/apk/repositories
2.3.1.5.6 ADD: 复制和解包文件

该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解包解压缩。可以将复制指定的到容器中的

注意: ADD不支持gz格式,但支持tar.gz

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

说明:

  • 可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压) 可以是绝对路径或者是 WORKDIR 指定的相对路径

  • 如果是目录,只复制目录中的内容,而非目录本身

  • 如果是一个 URL ,下载后的文件权限自动设置为 600

  • 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>

  • 如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于"tar -x"命令, 但是通过URL获取到的tar文件将不会自动展开

  • 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到

范例:

ADD test relativeDir/          # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/         # adds "test" to /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
2.3.1.5.7 CMD: 容器启动命令

一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令.

  • 如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT命令,那么开启容器时就会使用执行CMD指定的默认的命令

  • 前面介绍过的 RUN 命令是在构建镜像时执行的命令,注意二者的不同之处

  • 每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行

  • 如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令

# 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","param1","param2"]
# 在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量
CMD command param1 param2
# 提供给 ENTRYPOINT 命令的默认参数
CMD ["param1","param2"]

范例:

CMD ["nginx", "-g", "daemon off;"]

范例:

[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM ubuntu:18.04
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN apt update \
&& apt -y install  curl \
&& rm-rf /var/lib/apt/lists/*
CMD [ "curl", "-s","https://ip.cn"]
[root@centos8 ubuntu]#podman  run  9b
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
#cat /etc/etc/issue覆盖了curl命令
[root@centos8 ubuntu]#podman  run  9b cat /etc/issue
Ubuntu 18.04.4 LTS \n \l

范例:

[root@ubuntu1804 dockerfile]#pwd
/data/dockerfile
[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV ROOT /data/website
COPY index.html ${ROOT}/index.html
CMD /bin/httpd -f-h${ROOT}
EXPOSE 80
[root@ubuntu1804 dockerfile]#cat index.html
Website in Dockerfile
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#./build.sh v1.0
[root@ubuntu1804 dockerfile]#docker run  -d  --rm -P  --name c1  test:v1.0
[root@ubuntu1804 ~]#docker port c1
80/tcp -> 0.0.0.0:32781
[root@ubuntu1804 ~]#curl 127.0.0.1:32781
Website in Dockerfile
[root@ubuntu1804 ~]#

范例:

[root@ubuntu1804 dockerfile]#pwd
/data/dockerfile
[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV ROOT /data/website
RUN mkdir-p${ROOT} && echo'<h1> Busybox httpd server in Dockerfile</h1>' >
${ROOT}/index.html
#COPY index.html ${ROOT}/index.html
CMD ["/bin/sh","-c","/bin/httpd -f -h ${ROOT}"]
#CMD /bin/httpd -f -h ${ROOT}
EXPOSE 80
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#ls
build.sh  Dockerfile
[root@ubuntu1804 dockerfile]#./build.sh v2.0
Sending build context to Docker daemon  4.096kB
Step 1/5 : FROM busybox
---> c7c37e472d31
Step 2/5 : ENV ROOT /data/website
---> Using cache
---> ad654b3213c7
Step 3/5 : RUN mkdir-p${ROOT} && echo'<h1> Busybox httpd server in
Dockerfile</h1>' > ${ROOT}/index.html
---> Running in c7c2b920ccb0
Removing intermediate container c7c2b920ccb0
---> d40ce17d4e85
Step 4/5 : CMD ["/bin/sh","-c","/bin/httpd -f -h ${ROOT}"]
---> Running in 52be24840eee
Removing intermediate container 52be24840eee
---> d22731d921df
Step 5/5 : EXPOSE 80
---> Running in 4a50d8d9aa83
Removing intermediate container 4a50d8d9aa83
---> 85d6547a3168
Successfully built 85d6547a3168
Successfully tagged test:v2.0
[root@ubuntu1804 dockerfile]#docker run  -d  --rm -P  --name c2  test:v2.0
cf5fea09ce1362f18a90f4fcdffa3000de26b4919927e1cdce0cce6243f5dd24
[root@ubuntu1804 dockerfile]#docker port c2
80/tcp -> 0.0.0.0:32785
[root@ubuntu1804 dockerfile]#curl 127.0.0.1:32785
<h1> Busybox httpd server in Dockerfile</h1>
[root@ubuntu1804 dockerfile]#docker inspect -f "{{.Config}}" test:v2.0
{   falsefalsefalse map[80/tcp:{}] falsefalsefalse
[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ROOT=/data/website] [/bin/sh -c /bin/httpd -f-h${ROOT}] <nil> false
sha256:d22731d921df65f9da7452e714cf35ef345529ffa1bd5b92c0024d1d1bd8e714 map[]  []
false  [] map[]  <nil> []}
#查看进程关系
[root@ubuntu1804 ~]#docker exec -it c2 sh
/ # ps
PID   USER     TIME  COMMAND
1 root      0:00 /bin/httpd -f-h /data/website
8 root      0:00 sh
13 root      0:00 ps
2.3.1.5.8 ENTRYPOINT: 入口点

功能类似于CMD,配置容器启动后执行的命令及参数

# 使用 exec 执行
ENTRYPOINT ["executable", "param1", "param2"...]
# shell中执行
ENTRYPOINT command param1 param2
  • ENTRYPOINT 不能被 docker run 提供的参数覆盖,而是追加,即如果docker run 命令有参数,那么参数全部都会作为ENTRYPOINT的参数

  • 如果docker run 后面没有额外参数,但是dockerfile中有CMD命令(即上面CMD的第三种用

  • 法),即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINT的参数

  • 如果docker run 后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run 后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数

  • 可以通过docker run --entrypoint string 参数在运行时替换,注意string不要加空格

  • 使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数

  • 每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效通常会利用ENTRYPOINT指令配合脚本,可以为CMD指令提供环境配置

范例:

[root@centos8 ~]#cat /data/dockerfile/web/nginx/nginx-1.18/Dockerfile
FROM centos:centos7.9-v10.0
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV version=1.18.0
ADD nginx-$version.tar.gz /usr/local/
RUN cd /usr/local/nginx-$version && ./configure --prefix=/apps/nginx && make &&
make install && rm-rf /usr/local/nginx* && sed-i's/.*nobody.*/user nginx;/'
/apps/nginx/conf/nginx.conf && useradd -r nginx
COPY index.html /apps/nginx/html
VOLUME ["/apps/nginx/html"]
EXPOSE 80443
CMD ["-g","daemon off;"]
ENTRYPOINT ["/apps/nginx/sbin/nginx"]
#上面两条指令相当于ENTRYPOINT ["/apps/nginx/sbin/nginx","-g","daemon off;"]
HEALTHCHECK --interval=5s --timeout=3s CMD curl-fs http://127.0.0.1/

范例:

[root@ubuntu1804 ~]#docker run -it  --entrypoint cat alpine /etc/issue
Welcome to Alpine Linux 3.12
Kernel \r on an \m (\l)

范例:

[root@ubuntu1804 dockerfile]#cat Dockerfile
FROM ubuntu:18.04
RUN apt update \
&& apt -y install  curl \
&& rm-rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s","https://ip.cn"]
[root@centos8 dockerfile]#podman run -it --rm f68e006
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
#追加-i参数
[root@centos8 dockerfile]#podman run -it --rm f68e006  -i
HTTP/2 200
date: Sun, 23 Feb 202008:05:19 GMT
content-type: application/json; charset=UTF-8
set-cookie: __cfduid=d4a22496ea6f3b2861763354f8ca600711582445119; expires=Tue,
24-Mar-2008:05:19 GMT; path=/; domain=.ip.cn; HttpOnly; SameSite=Lax
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-
cgi/beacon/expect-ct"
alt-svc: h3-25=":443"; ma=86400, h3-24=":443"; ma=86400, h3-23=":443"; ma=86400
server: cloudflare
cf-ray: 5697b1ac1862eb41-LAX
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}

范例: 利用脚本实现指定环境变量动态生成配置文件内容

[root@ubuntu1804 ~]#echo 'Nginx Website in Dockerfile' > index.html
[root@ubuntu1804 ~]#cat Dockerfile
FROM nginx:1.16-alpine
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV DOC_ROOT='/data/website/'
ADD index.html ${DOC_ROOT}
ADD entrypoint.sh /bin/
EXPOSE 80/tcp 8080
#HEALTHCHECK --start-period=3s CMD wget -0 - -q http://${IP:-0.0.0.0}:
{PORT:-80}/
CMD ["/usr/sbin/nginx","-g", "daemon off;"]  #CMD指令的内容都成为了ENTRYPOINT的参数
ENTRYPOINT [ "/bin/entrypoint.sh"]
[root@ubuntu1804 ~]#cat entrypoint.sh
#!/bin/sh
cat > /etc/nginx/conf.d/www.conf <<EOF
server {
    server_name ${HOSTNAME};
    listen ${IP:-0.0.0.0}:${PORT:-80};
    root   ${DOC_ROOT:-/usr/share/nginx/html};
}
EOF
exec "$@"
[root@ubuntu1804 ~]#chmod +x entrypoint.sh
[root@ubuntu1804 ~]#docker build -t nginx:v1.0 .
[root@ubuntu1804 ~]#docker run --name n1 --rm -P -e "PORT=8080" -e
"HOSTNAME=www.wang.org" nginx:v1.0
2.3.1.5.9 ARG: 构建参数

ARG指令在builad 阶段指定变量,和ENV不同的是,容器运行时不会存在这些环境变量

ARG<name>[=<defaultvalue>]

如果和ENV同名,ENV覆盖ARG变量

可以用 docker build --build-arg <参数名>=<值> 来覆盖

范例:

[root@ubuntu1804 ~]#cat Dockerfile
FROM busybox
ARG author="wang <root@wangxiaochun.com>"
LABEL maintainer="${author}"
[root@ubuntu1804 ~]#docker build --build-arg author="29308620@qq.com"  -t
busybox:v1.0 .

说明: ARG 和 FROM

#FROM指令支持ARG指令放在第一个FROM之前声明变量
#示例:
ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app
FROM extras:${CODE_VERSION}
CMD  /code/run-extras
#在FROM之前声明的ARG在构建阶段之外,所以它不能在FROM之后的任何指令中使用。要使用在第一个FROM
之前声明的ARG的默认值,请在构建阶段内使用没有值的ARG指令
#示例:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo$VERSION > image_version
2.3.1.5.11 VOLUME: 匿名卷

在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,默认会将宿主机上的目录挂载至VOLUME 指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。

宿主机目录为

#docker
/var/lib/docker/volumes/<volume_id>/_data
#Podman
/var/lib/containers/storage/volumes/<volume_id>/_data

语法:

VOLUME <容器内路径>
VOLUME ["<容器内路径1>", "<容器内路径2>"...]
注意:
<容器内路径>如果在容器内不存在,在创建容器时会自动创建
<容器内路径>如果是存在的,同时目录内有内容,将会把此目录的内容复制到宿主机的实际目录

注意:

Dockerfile中的VOLUME实现的是匿名数据卷,无法指定宿主机路径和容器目录的挂载关系通过docker rm -fv <容器ID> 可以删除容器的同时删除VOLUME指定的卷

范例: 在容器创建两个/data/ ,/data2的挂载点

VOLUME [ "/data1","/data2" ]

范例:

[root@centos8 ~]#cat /data/dockerfile/system/alpine/Dockerfile
FROM alpine:3.11
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY repositories /etc/apk/repositories
VOLUME [ "/testdata","/testdata2" ]
[root@centos8 alpine]#podman run -it --rm 8ef61dd3959da3f sh
/ # df
Filesystem           1K-blocks      Used Available Use% Mounted on
overlay              10480640036563801011500203% /
tmpfs                    655360655360% /dev
/dev/sda2            10480640036563801011500203% /testdata2
/dev/sda2            10480640036563801011500203% /testdata
/ # cp /etc/issue  /testdata/f1.txt
/ # cp /etc/issue  /testdata2/f2.txt
[root@centos8 ~]#tree /var/lib/containers/storage/volumes/
/var/lib/containers/storage/volumes/
├── 725f0f67921bdbffbe0aaf9b015d663a6e3ddd24674990d492025dfcf878529b
│   └── _data
│       └── f1.txt
└── fbd13e5253deb375e0dea917df832d2322e96b04ab43bae061584dcdbe7e89f2
    └── _data
        └── f2.txt
4 directories, 2 files
2.3.1.5.12 EXPOSE: 暴露端口

指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。

EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射

因此,在启动容器时需要通过 -P 或 -p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可使用

注意: 即使 Dockerfile 没有 EXPOSE 端口指令,也可以通过docker run -p 临时暴露容器内程序真正监听的端口 ,所以EXPOSE 相当于指定默认的暴露端口,可以通过docker run -P 进行真正暴露

EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
#说明
<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议

范例:

EXPOSE 80443
EXPOSE 11211/udp 11211/tcp

范例:

[root@ubuntu1804 dockerfile]#pwd
/data/dockerfile
[root@ubuntu1804 dockerfile]#echo Website in Dockerfile > index.html
[root@ubuntu1804 dockerfile]#vim Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY index.html /data/website/
EXPOSE 80
[root@ubuntu1804 dockerfile]#cat build.sh
#!/bin/bash
#
TAG=$1
docker build -t test:$TAG .
[root@ubuntu1804 dockerfile]#chmod +x build.sh
[root@ubuntu1804 dockerfile]#./build.sh v1.0
[root@ubuntu1804 dockerfile]#ls
build.sh  Dockerfile  index.html
[root@ubuntu1804 dockerfile]#docker run  --rm -P --name c1 test:v1.0  /bin/httpd
-f  -h /data/website
[root@ubuntu1804 ~]#docker port c1
80/tcp -> 0.0.0.0:32773
[root@ubuntu1804 ~]#curl 127.0.0.1:32773
Website in Dockerfile
[root@ubuntu1804 ~]#docker kill c1
c1
2.3.1.5.13 WORKDIR: 指定工作目录

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录

WORKDIR 指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会自行创建

注意: 在RUN可以生效,在CMD、ENTRYPOINT可能会有问题

WORKDIR/path/to/workdir

范例:

#两次RUN独立运行,不在同一个目录
RUN cd /app
RUN echo"hello" > world.txt
#如果想实现相同目录可以使用WORKDIR
WORKDIR /app
RUN echo"hello" > world.txt

可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如

WORKDIR/a
WORKDIR b
WORKDIR c
RUN pwd
#则最终路径为 /a/b/c
2.3.1.5.14 ONBUILD: 子镜像引用父镜像的指令

可以用来配置当构建当前镜像的子镜像时,会自动触发执行的指令,但在当前镜像构建时,并不会执行,即延迟到子镜像构建时才执行

ONBUILD[INSTRUCTION]

例如,Dockerfile 使用如下的内容创建了镜像 image-A。

...
ONBUILD ADD http://www.wangxiaochun.com/wp-content/uploads/2017/09/logo.png
/data/
ONBUILD RUN rm-rf /*
ONBUILD RUN /usr/local/bin/python-build --dir /app/src...

如果基于 image-A 创建新的镜像image-B时,新的Dockerfile中使用 FROM image-A指定基础镜像时, 会自动执行ONBUILD 指令内容,等价于在后面添加了两条指令。

FROM image-A
#Automatically run the following
ADD http://www.wangxiaochun.com/wp-content/uploads/2017/09/logo.png /data
RUN /usr/local/bin/python-build --dir /app/src

说明:

尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我能套,且不会触发FROM和 MAINTAINER指令

使用 ONBUILD 指令的镜像,推荐在标签中注明,例如 ruby:1.9 - onbuild

2.3.1.5.15 USER: 指定当前用户

指定运行容器的用户名或 UID,在后续dockerfile中的 RUN ,CMD和ENTRYPOINT指令时使用此用户当服务不需要管理员权限时,可以通过该命令指定运行用户

这个用户必须是事先建立好的,否则无法切换

如果没有指定 USER,默认是 root 身份执行

USER <user>[:<group>]
USER <UID>[:<GID>]

范例:

RUN groupadd -r mysql && useradd -r-g mysql mysql
USER mysql
2.3.1.5.16 HEALTHCHECK: 健康检查

检查容器的健康性

HEALTHCHECK [选项] CMD <命令> #设置检查容器健康状况的命令,如果命令执行失败,则返回1,即
unhealthy
HEALTHCHECK NONE #如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK 支持下列选项:
--interval=<间隔>  #两次健康检查的间隔,默认为 30 秒
--timeout=<时长>    #健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默
认 30 秒
--retries=<次数>    #当连续失败指定次数后,则将容器状态视为 unhealthy,默认3次
--start-period=<FDURATION> #default: 0s
#检查结果返回值:
0#success    the container is healthy and ready for use
1#unhealthy   the container is not working correctly
2#reserved   do not use this exit code

范例

FROM nginx
RUN apt-get update && apt-get install -ycurl && rm-rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl-fs
http://localhost/

范例:

#如果健康性检查成功,STATUS会显示 (healthy)
[root@centos8 nginx-1.18]#docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED
          STATUS                   PORTS                         NAMES
fad976015cad        nginx-centos7.9:v1.18-11   "/apps/nginx/sbin/ng…"6
seconds ago       Up 5 seconds (healthy)   0.0.0.0:80->80/tcp, 443/tcp   n1
#如果健康性检查不通过,STATUS会显示(unhealthy)
[root@centos8 nginx-1.18]#docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED
           STATUS                          PORTS                         NAMES
fad976015cad        nginx-centos7.9:v1.18-11   "/apps/nginx/sbin/ng…"   About a
minute ago   Up About a minute (unhealthy)   0.0.0.0:80->80/tcp, 443/tcp   n1
#查看健康状态
[root@centos8 ~]#docker inspect -f '{{.State.Health.Status}}' n1
unhealthy
#以json格式显示
[root@centos8 ~]#docker inspect -f '{{json .State.Health}}' n1
{"Status":"unhealthy","FailingStreak":120,"Log":[{"Start":"2021-01-
12T23:26:55.897317224+08:00","End":"2021-01-
12T23:26:56.117988749+08:00","ExitCode":22,"Output":""},{"Start":"2021-01-
12T23:27:01.121614252+08:00","End":"2021-01-
12T23:27:01.358263627+08:00","ExitCode":22,"Output":""},{"Start":"2021-01-
12T23:27:06.362034898+08:00","End":"2021-01-
12T23:27:06.596203379+08:00","ExitCode":22,"Output":""},{"Start":"2021-01-
12T23:27:11.597954624+08:00","End":"2021-01-
12T23:27:11.857543947+08:00","ExitCode":22,"Output":""},{"Start":"2021-01-
12T23:27:16.861453605+08:00","End":"2021-01-
12T23:27:17.115885101+08:00","ExitCode":22,"Output":""}]}
[root@centos8 ~]#docker inspect -f '{{json .State.Health}}' n1 | python3 -m
json.tool
{
"Status": "unhealthy",
"FailingStreak": 136,
"Log": [
        {
"Start": "2021-01-12T23:28:19.950974202+08:00",
"End": "2021-01-12T23:28:20.204912349+08:00",
"ExitCode": 22,
"Output": ""
        },
        {
"Start": "2021-01-12T23:28:25.208822104+08:00",
"End": "2021-01-12T23:28:25.491441522+08:00",
"ExitCode": 22,
"Output": ""
        },
        {
"Start": "2021-01-12T23:28:30.495419338+08:00",
"End": "2021-01-12T23:28:30.714133496+08:00",
"ExitCode": 22,
"Output": ""
        },
        {
"Start": "2021-01-12T23:28:35.718450539+08:00",
"End": "2021-01-12T23:28:35.988073766+08:00",
"ExitCode": 22,
"Output": ""
        },
        {
"Start": "2021-01-12T23:28:40.993098183+08:00",
"End": "2021-01-12T23:28:41.260442962+08:00",
"ExitCode": 22,
"Output": ""
        }
    ]
}
2.3.1.5.17 .dockerignore文件

官方文档: https://docs.docker.com/engine/reference/builder/#dockerignore-file 与.gitignore文件类似,生成构建上下文时Docker客户端应忽略的文件和文件夹指定模式 .dockerignore 使用 Go 的文件路径规则 filepath.Match

参考链接: https://golang.org/pkg/path/filepath/#Match

完整的语法

#     #以#开头的行为注释
  • # 匹配任何非分隔符字符序列

  • ? # 匹配任何单个非分隔符

  • \\ # 表示 \

  • ** # 匹配任意数量的目录(包括零)例如, **/*.go 将排除在所有目录中以 .go 结尾的所有文件,包括构建上下文的根。 ! # 表示取反,可用于排除例外情况

Rule Behavior
# comment Ignored.
Exclude files and directories whose names start with
tempin any immediate
*/temp* subdirectory of the root. For example, the plain file
/somedir/temporary.txtis excluded, as is the directory
/somedir/temp.
Exclude files and directories starting with
tempfrom any subdirectory that is
*/*/temp* two levels below the root. For example,
/somedir/subdir/temporary.txtis
excluded.
Exclude files and directories in the root directory whose names are a one-
temp? character extension of
temp. For example,
/tempaand
/tempbare
excluded.

范例:

#排除 test 目录下的所有文件
test/*
#排除 md 目录下的 xttblog.md 文件
md/xttblog.md
#排除 xttblog 目录下的所有 .md 的文件
xttblog/*.md
#排除以 xttblog 为前缀的文件和文件夹
xttblog?
#排除所有目录下的 .sql 文件夹
**/*.sql

范例:

#除了README的md不排外,排除所有md文件,但不排除README-secret.md
*.md
!README*.md
README-secret.md
#除了所有README的md文件以外的md都排除
*.md
README-secret.md
!README*.md
2.3.1.5.18 Dockerfile 构建过程和指令总结

Dockerfile 构建过程

  • 从基础镜像运行一个容器

  • 执行一条指令,对容器做出修改

  • 执行类似docker commit的操作,提交一个新的中间镜像层(可以利用中间层镜像创建容器进行调试和排错)

  • 再基于刚提交的镜像运行一个新容器

  • 执行Dockerfile中的下一条指令,直至所有指令执行完毕

Dockerfile 指令总结

2.3.1.6 构建镜像docker build 命令

docker build命令使用Dockerfile文件创建镜像

docker build [OPTIONS] PATH | URL | -
说明:
PATH | URL | -#可以使是本地路径,也可以是URL路径。若设置为 - ,则从标准输入获取
Dockerfile的内容
-f, --file string  #Dockerfile文件名,默认为 PATH/Dockerfile
--force-rm#总是删除中间层容器,创建镜像失败时,删除临时容器
--no-cache#不使用之前构建中创建的缓存
-q--quiet=false#不显示Dockerfile的RUN运行的输出结果
--rm=true#创建镜像成功时,删除临时容器
-t--tag list      #设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标签
默认为latest)

范例:

docker build .
docker build /usr/local/src/nginx
docker build -f /path/to/a/Dockerfile .
docker build -t shykes/myapp .
docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
docker build -t test/myapp .
docker build -t nginx:v1 /usr/local/src/nginx

查看镜像的构建历史:

docker history 镜像ID

范例:

[root@centos8 ~]#podman history  90201858b1fc
ID             CREATED          CREATED BY
SIZE      COMMENT
90201858b1fc   17 minutes ago   /bin/sh -c#(nop) CMD ["tail" ,"-f","/etc/...
0B
<missing>      2 hours ago      /bin/sh -c apt-get update && apt-get insta...
14.83MB
<missing>      35 hours ago     /bin/sh -c#(nop) CMD ["/bin/bash"]
14.83MB
<missing>      35 hours ago     /bin/sh -cmkdir-p /run/systemd && echo'...
3.072kB
<missing>      35 hours ago     /bin/sh -cset-xe && echo'#!/bin/sh' > /...
15.87kB
<missing>      35 hours ago     /bin/sh -c [ -z"$(apt-get indextargets)" ]
991.2kB
<missing>      35 hours ago     /bin/sh -c#(nop) ADD file:91a750fb184711f...
65.58MB

范例: 利用Dockerfile构建基于CentOS的nginx镜像

[root@ubuntu1804 ~]#vim /data/Dockerfile
[root@ubuntu1804 ~]#cat /data/Dockerfile
FROM centos
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum install -y nginx && echo Nginx Website in Docker >
/usr/share/nginx/html/index.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
#ENTRYPOINT ["nginx", "-g", "daemon off;"]
[root@ubuntu1804 ~]#docker build -t nginx_centos8.2:v1.14.1 /data/
Sending build context to Docker daemon  209.2MB
Step 1/6 : FROM centos
---> 831691599b88
Step 2/6 : LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
---> Running in 3fc4487e80f9
Removing intermediate container 3fc4487e80f9
---> 598318841b8a
Step 3/6 : RUN yum install -y nginx
---> Running in 8a6d9866e4ae
CentOS-8 - AppStream                            2.1 MB/s | 5.8 MB     00:02
CentOS-8 - Base                                 1.8 MB/s | 2.2 MB     00:01
CentOS-8 - Extras                               8.6 kB/s | 7.0 kB     00:00
.......
Complete!
Removing intermediate container 8a6d9866e4ae
---> 8963fb608c33
Step 4/6 : RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
---> Running in 04d4287aac49
Removing intermediate container 04d4287aac49
---> 9a95e56b9bc0
Step 5/6 : EXPOSE 80
---> Running in 8534523d8aa6
Removing intermediate container 8534523d8aa6
---> 23cca5737903
Step 6/6 : CMD ["nginx", "-g", "daemon off;"]
---> Running in d52fcc21444f
Removing intermediate container d52fcc21444f
---> afdaec99eb35
Successfully built afdaec99eb35
Successfully tagged nginx_centos8.2:v1.14.1
[root@ubuntu1804 ~]#docker run -d -P --name nginx-web nginx_centos8.2:v1.14.1
3faba5a49f63ab3a1b031da5e4940303b10ddf349069184597e703c572d257d8
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED
          STATUS              PORTS                   NAMES
3faba5a49f63        nginx_centos8.2:v1.14.1   "nginx -g 'daemon of…"4 seconds
ago       Up 3 seconds        0.0.0.0:32775->80/tcp   nginx-web
[root@ubuntu1804 ~]#curl http://127.0.0.1/32775
curl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused
[root@ubuntu1804 ~]#curl http://127.0.0.1:32775
Nginx Website in Docker
[root@ubuntu1804 ~]#curl -I http://127.0.0.1:32775
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Wed, 22 Jul 202017:09:15 GMT
Content-Type: text/html
Content-Length: 24
Last-Modified: Wed, 22 Jul 202017:04:40 GMT
Connection: keep-alive
ETag: "5f1871a8-18"
Accept-Ranges: bytes

范例: 刷新镜像缓存重新构建新镜像

[root@ubuntu1804 ~]#cat /data/Dockerfile
FROM centos
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum install -y nginx
RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
#修改下面行,从下面行开始不再使用缓存
ENV REFRESH_DATA 2020-01-01
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
[root@ubuntu1804 ~]#docker build   -t nginx_centos8.2:v1.14.1 /data/
Sending build context to Docker daemon  209.2MB
Step 1/7 : FROM centos
---> 831691599b88
Step 2/7 : LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
---> Using cache
---> 598318841b8a
Step 3/7 : RUN yum install -y nginx
---> Using cache
---> 8963fb608c33
Step 4/7 : RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
---> Using cache
---> 9a95e56b9bc0
Step 5/7 : ENV REFRESH_DATA 2020-01-01#从此行开始不再利用缓存
---> Running in 4607ee0d0e77
Removing intermediate container 4607ee0d0e77
---> d6235889f336
Step 6/7 : EXPOSE 80
---> Running in 6924aab5c5c8
Removing intermediate container 6924aab5c5c8
---> 545393760683
Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
---> Running in 345bbc6179d8
Removing intermediate container 345bbc6179d8
---> 4bafc2d0c7e0
Successfully built 4bafc2d0c7e0
Successfully tagged nginx_centos8.2:v1.14.1
#全部不利用缓存重新构建镜像
[root@ubuntu1804 ~]#docker build  --no-cache -t nginx_centos8.2:v1.14.1 /data/
Sending build context to Docker daemon  209.2MB
Step 1/7 : FROM centos
---> 831691599b88
Step 2/7 : LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
---> Running in 41f2aab6657f
Removing intermediate container 41f2aab6657f
---> 091969d0ed9e
Step 3/7 : RUN yum install -y nginx
---> Running in 6e174d492348
CentOS-8 - AppStream                            4.2 MB/s | 5.8 MB     00:01
CentOS-8 - Base                                 1.7 MB/s | 2.2 MB     00:01
CentOS-8 - Extras                               1.2 kB/s | 7.0 kB     00:05
Dependencies resolved.
......
Complete!
Removing intermediate container 6e174d492348
---> ba62ac34b951
Step 4/7 : RUN echo Nginx Website in Docker > /usr/share/nginx/html/index.html
---> Running in d6f785b28ef6
Removing intermediate container d6f785b28ef6
---> 6e15fdc84e21
Step 5/7 : ENV REFRESH_DATA 2020-06-06
---> Running in c6fd87ed95f6
Removing intermediate container c6fd87ed95f6
---> 328b8621ec36
Step 6/7 : EXPOSE 80
---> Running in 1af3d6964d81
Removing intermediate container 1af3d6964d81
---> 7c513643b182
Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
---> Running in fd9216490941
Removing intermediate container fd9216490941
---> 0b2b61dd0445
Successfully built 0b2b61dd0445
Successfully tagged nginx_centos8.2:v1.14.1

2.3.2 实战案例: Dockerfile 制作基于基础镜像的Base镜像

2.3.2.1 准备目录结构,下载镜像并初始化系统
#按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
[root@ubuntu1804 ~]#mkdir
/data/dockerfile/{web/{nginx,apache,tomcat,jdk},system/{centos,ubuntu,alpine,deb
ian}} -p
[root@ubuntu1804 ~]#tree /data/dockerfile/
/data/dockerfile/
├── system
│   ├── alpine
│   ├── centos
│   ├── debian
│   └── ubuntu
└── web
    ├── apache
    ├── jdk
    ├── nginx
    └── tomcat
10 directories, 0 files
[root@ubuntu1804 ~]#
#下载基础镜像
[root@ubuntu1804 ~]#docker pull centos:centos7.7.1908
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.3.2.2 先制作基于基础镜像的系统Base镜像
#先制作基于基础镜像的系统base镜像
[root@ubuntu1804 ~]#cd /data/dockerfile/system/centos/
#创建Dockerfile,注意可以是dockerfile,但无语法着色功能
[root@ubuntu1804 centos]#vim Dockerfile
[root@ubuntu1804 centos]#cat Dockerfile
FROM centos:centos7.7.1908
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum -y install wget && rm-f /etc/yum.repos.d/* && wget-P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/Centos-7.repo \
    && wget-P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo/epel-7.repo \
    && sed-i-e'/mirrors.cloud.aliyuncs.com/d'-e'/mirrors.aliyuncs.com/d'
/etc/yum.repos.d/Centos-7.repo \
    && yum -y install  vim-enhanced tcpdump lrzsz tree telnet bash-completion
net-tools wgetcurl bzip2 lsof  zip unzip nfs-utils gccmake gcc-c++ glibc
glibc-devel pcre pcre-devel openssl  openssl-devel systemd-devel zlib-devel \
    && yum clean all \
    && rm-f /etc/localtime  \
    && ln-s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[root@ubuntu1804 centos]#vim build.sh
[root@ubuntu1804 centos]#cat build.sh
#!/bin/bash
#
docker build -t centos7-base:v1  .
[root@ubuntu1804 centos]#chmod +x build.sh
[root@ubuntu1804 centos]#./build.sh
[root@ubuntu1804 centos]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos7-base        v1                  1ba1317e06dc        23 seconds ago
402MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
[root@ubuntu1804 centos]#docker image history centos7-base:v1
IMAGE               CREATED             CREATED BY
       SIZE                COMMENT
1ba1317e06dc        43 seconds ago      /bin/sh -c yum -y install wget && rm-f
/etc…   198MB
6b87f2843eb9        About an hour ago   /bin/sh -c#(nop)  LABEL
maintainer=wangxiao…   0B
08d05d1d5859        2 months ago        /bin/sh -c#(nop)  CMD ["/bin/bash"]
       0B
<missing>           2 months ago        /bin/sh -c#(nop)  LABEL org.label-
schema.sc…   0B
<missing>           2 months ago        /bin/sh -c#(nop) ADD
file:3e2a127b44ed01afc…   204MB

2.3.3 实战案例: Dockerfile 制作基于Base镜像的 nginx 镜像

2.3.3.1 在Dockerfile目录下准备编译安装的相关文件
[root@ubuntu1804 ~]#mkdir /data/dockerfile/web/nginx/1.16
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16
[root@ubuntu1804 1.16]#wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@ubuntu1804 1.16]#mkdir app/
[root@ubuntu1804 1.16]#echo  "Test Page in app" > app/index.html
[root@ubuntu1804 1.16]#tar zcf app.tar.gz app
[root@ubuntu1804 1.16]#ls
app  app.tar.gz nginx-1.16.1.tar.gz
2.3.3.2 在一台测试机进行编译安装同一版本的nginx 生成模版配置文件
[root@centos7 ~]#yum -y install vim-enhanced tcpdump lrzsz tree telnet bash-
completion net-tools wget bzip2 lsof tmux man-pages zip unzip nfs-utils gcc make
gcc-c++ glibc glibc-devel pcre pcre-devel openssl  openssl-devel systemd-devel
zlib-devel
[root@centos7 ~]#wget -P /usr/local/src http://nginx.org/download/nginx-
1.16.1.tar.gz
[root@centos7 ~]#cd /usr/local/src/
[root@centos7 src]#tar xvf nginx-1.16.1.tar.gz
[root@centos7 src]#cd nginx-1.16.1/
[root@centos7 nginx-1.16.1]#./configure  --prefix=/apps/nginx && make && make
install
#将配置文件复制到nginx镜像的服务器相应目录下
[root@centos7 ~]#scp /apps/nginx/conf/nginx.conf
10.0.0.100:/data/dockerfile/web/nginx/1.16
#准备配置文件
[root@ubuntu1804 1.16]#vim /data/dockerfile/web/nginx/1.16/nginx.conf
worker_processes  1;
user nginx;
daemon off;   #增加此行,前台运行nginx
2.3.3.3 编写Dockerfile文件
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx
[root@ubuntu1804 nginx]#vim  Dockerfile
[root@ubuntu1804 nginx]#cat Dockerfile
FROM centos7-base:v1
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD nginx-1.16.1.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.16.1 && \
    && ./configure --prefix=/apps/nginx \
    && make && make install \
    && rm-f /usr/local/src/nginx* \
    && useradd -r nginx
COPY nginx.conf /apps/nginx/conf/
ADD  app.tar.gz /apps/nginx/html/
EXPOSE 80443
CMD ["/apps/nginx/sbin/nginx"]
[root@ubuntu1804 nginx]#
2.3.3.4 生成nginx镜像
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16
[root@ubuntu1804 1.16]#ls
app  app.tar.gz  build.sh  Dockerfile  nginx-1.16.1.tar.gz  nginx.conf
[root@ubuntu1804 1.16]#vim build.sh
[root@ubuntu1804 1.16]#cat build.sh
#!/bin/bash
#
docker build -t nginx-centos7:1.6.1 .
[root@ubuntu1804 1.16]#chmod +x build.sh
[root@ubuntu1804 1.16]#./build.sh
[root@ubuntu1804 1.16]##docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
nginx-centos7       1.6.1               73e4b4b95bca        10 minutes ago
412MB
centos7-base        v1                  1ba1317e06dc        About an hour ago
402MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB

2.3.3.5 生成的容器测试镜像

[root@ubuntu1804 ~]#docker run  -d -p 80:80  nginx-centos7:1.6.1
e8e733c6dc96bfb212a15dec04cfcfcac72daf400f5d2423c707aeb778a1859d
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED
      STATUS              PORTS                         NAMES
e8e733c6dc96        centos7-nginx:1.6.1   "/apps/nginx/sbin/ng…"4 seconds ago
      Up 2 seconds        0.0.0.0:80->80/tcp, 443/tcp   cool_germain
[root@ubuntu1804 ~]#docker exec -it e8e733c6dc96 bash
[root@e8e733c6dc96 /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          10.2  0.2  205722468 ?        Ss   03:36   0:00 nginx: master
process /apps/nginx/sbin/nginx
nginx        120.0  0.2  210242344 ?        S    03:36   0:00 nginx: worker
process
root         134.0  0.3  123643536 pts/0    Ss   03:37   0:00 bash
root         320.0  0.3  517643460 pts/0    R+03:37   0:00 ps aux
[root@e8e733c6dc96 /]# exit
exit
[root@ubuntu1804 ~]#curl 127.0.0.1/app/
Test Page in app

2.3.4 实战案例: Dockerfile 直接制作 nginx 镜像

2.3.4.1 在Dockerfile目录下准备编译安装的相关文件
[root@ubuntu1804 ~]#mkdir /data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 1.16.1]#vim nginx.conf
user  nginx;
worker_processes  1;
#daemon off;
[root@ubuntu1804 1.16.1]#wget http://nginx.org/download/nginx-1.16.1.tar.gz
2.3.4.2 编写Dockerfile文件
[root@ubuntu1804 1.16.1]#pwd
/data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 1.16.1]#vim Dockerfile
[root@ubuntu1804 1.16.1]#cat Dockerfile
#Nginx Dockerfile
FROM centos:centos7.7.1908
MAINTAINER wangxiaochun <root@wangxiaochun.com>
RUN yum install -ygcc gcc-c++  pcre pcre-devel zlib zlib-devel openssl
openssl-devel \
    && useradd -r-s /sbin/nologin nginx \
    && yum clean all
ADD nginx-1.16.1.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.16.1 \
    && ./configure --prefix=/apps/nginx \
    && make \
    && make install \
    && rm-rf /usr/local/src/nginx*
ADD nginx.conf /apps/nginx/conf/nginx.conf
COPY index.html /apps/nginx/html/
RUN ln-s /apps/nginx/sbin/nginx /usr/sbin/nginx
EXPOSE 80443
CMD ["nginx","-g","daemon off;"]
2.3.4.3 生成nginx镜像
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1
[root@ubuntu1804 1.16.1]#vim build.sh
[root@ubuntu1804 1.16.1]#cat build.sh
#!/bin/bash
#
docker build -t nginx-centos7:1.6.1-v2 .
[root@ubuntu1804 1.16.1]#chmod +x build.sh
[root@ubuntu1804 1.16.1]#ls
build.sh  Dockerfile  index.html  nginx-1.16.1.tar.gz  nginx.conf
[root@ubuntu1804 1.16.1]#./build.sh
[root@ubuntu1804 1.16.1]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
nginx-centos7       1.6.1-v2            1918d29d5f45        17 minutes ago
328MB
nginx-centos7       1.6.1               8c16774437a5        13 hours ago
412MB
centos7-base        v1                  1ba1317e06dc        15 hours ago
402MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.3.4.4 生成容器测试镜像
[root@ubuntu1804 ~]#docker run  -d -p 80:80  nginx-centos7:1.6.1-v2
21c954ad4fb902076832cc9a52dd1502aca43d9bcd2b46a2f164382e4ac7b3f6
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED
        STATUS              PORTS                         NAMES
21c954ad4fb9        centos7-nginx:1.6.1-v2   "nginx -g 'daemon of…"6 seconds
ago       Up 4 seconds        0.0.0.0:80->80/tcp, 443/tcp   inspiring_goldwasser
[root@ubuntu1804 ~]#curl 127.0.0.1
Test Page v2 in Docker
[root@ubuntu1804 ~]#docker exec -it 21c954ad4fb9 bash
[root@21c954ad4fb9 /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          10.5  0.2  205722372 ?        Ss   03:30   0:00 nginx: master
process nginx -g daemon off;
nginx         60.0  0.2  210242316 ?        S    03:30   0:00 nginx: worker
process
root          711.5  0.2  118402880 pts/0    Ss   03:31   0:00 bash
root         200.0  0.3  517643376 pts/0    R+03:31   0:00 ps aux
[root@21c954ad4fb9 /]# exit
exit
[root@ubuntu1804 ~]#

2.3.5 生产案例: 制作自定义tomcat业务镜像

基于官方提供的centos、debian、ubuntu、alpine等基础镜像构建 JDK (Java环境),然后再基于自定义的 JDK 镜像构建出业务需要的tomcat 镜像

2.3.5.1 自定义 CentOS 系统基础镜像

先基于官方提供的基础镜像,制作出安装了常用命令的自定义基础镜像

[root@ubuntu1804 ~]#docker pull centos:centos7.7.1908
[root@ubuntu1804 ~]#mkdir -p
/data/dockerfile/{web/{nginx,tomcat,jdk},system/{centos,ubuntu,alpine,debian}}
[root@ubuntu1804 ~]#cd /data/dockerfile/system/centos/
[root@ubuntu1804 centos]#vim Dockerfile
[root@ubuntu1804 centos]#cat Dockerfile
# Centos Base Image
FROM centos:centos7.7.1908
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN yum -y install wget && rm-f /etc/yum.repos.d/* && wget-P /etc/yum.repos.d/
http://mirrors.aliyun.com/repo/Centos-7.repo \
    && wget-P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo/epel-7.repo \
    && yum -y install  vim-enhanced tcpdump lrzsz tree telnet bash-completion
net-tools wget bzip2 lsof  zip unzip nfs-utils gccmake gcc-c++ glibc glibc-
devel pcre pcre-devel openssl  openssl-devel systemd-devel zlib-devel \
    && yum clean all \
    && rm-f /etc/localtime  \
    && ln-s ../usr/share/zoneinfo/Asia/Shanghai /etc/localtime
#添加系统账户
RUN  groupadd www -g2019 && useradd www -u2019-g www
[root@ubuntu1804 centos]#vim build.sh
#通过脚本构建镜像
[root@ubuntu1804 centos]#cat build.sh
#!/bin/bash
docker build -t centos7-base:v1 .
[root@ubuntu1804 centos]#bash build.sh
[root@ubuntu1804 centos]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos7-base        v1                  34ab3afcd3b3        4 seconds ago
403MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB

2.3.5.2 构建JDK 镜像

2.3.5.2.1 上传JDK压缩包和profile文件上传到Dockerfile当前目录
#将CentOS7主机上的/etc/profile文件传到 Dockerfile 所在目录下
[root@ubuntu1804 ~]#scp centos7:/etc/profile 10.0.0.100:/data/dockerfile/web/jdk
#修改profile文件,加下面四行相关变量
[root@ubuntu1804 ~]#vim /data/dockerfile/web/jdk/profile
[root@ubuntu1804 ~]#tail -n 5 /data/dockerfile/web/jdk/profile
exportJAVA_HOME=/usr/local/jdk
exportTOMCAT_HOME=/apps/tomcat
exportPATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$TOMCAT_HOME/bin:$PATH
export
CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
#下载jdk文件传到Dockfile目录下
#https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-
2133151.html
[root@ubuntu1804 ~]#tree /data/dockerfile/web/jdk
/data/dockerfile/web/jdk
├── jdk-8u212-linux-x64.tar.gz
└── profile
0 directories, 2 files
2.3.5.2.2 准备Dockerfile文件
[root@ubuntu1804 ~]#vim  /data/dockerfile/web/jdk/Dockerfile
[root@ubuntu1804 ~]#cat /data/dockerfile/web/jdk/Dockerfile
#JDK Base Image
FROM centos7-base:v1
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD jdk-8u212-linux-x64.tar.gz /usr/local/src/
RUN ln-s /usr/local/src/jdk1.8.0_212 /usr/local/jdk
ADD profile /etc/profile
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin
2.4.2.3 执行构建脚本制作镜像
[root@ubuntu1804 ~]#vim /data/dockerfile/web/jdk/build.sh
[root@ubuntu1804 ~]#cat /data/dockerfile/web/jdk/build.sh
#!/bin/bash
docker build -t centos7-jdk:8u212 .
[root@ubuntu1804 ~]#tree /data/dockerfile/web/jdk/
/data/dockerfile/web/jdk/
├── build.sh
├── Dockerfile
├── jdk-8u212-linux-x64.tar.gz
└── profile
0 directories, 4 files
[root@ubuntu1804 ~]#cd /data/dockerfile/web/jdk/
[root@ubuntu1804 jdk]#bash build.sh
[root@ubuntu1804 jdk]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
centos7-jdk         8u212               fdbeb8a49ea6        59 seconds ago
809MB
centos7-base        v1                  34ab3afcd3b3        44 minutes ago
403MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.3.4.4 从镜像启动容器测试
[root@ubuntu1804 jdk]#docker run -it --rm centos7-jdk:8u212 bash
[root@25c9c0266bd2 /]# java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)
2.3.5.3 从JDK镜像构建tomcat 8 Base镜像

基于自定义的 JDK 基础镜像,构建出通用的自定义 Tomcat 基础镜像,此镜像后期会被多个业务的多个服务共同引用(相同的JDK 版本和Tomcat 版本)

2.3.5.3.1 上传tomcat 压缩包
[root@ubuntu1804 ~]#mkdir -p /data/dockerfile/web/tomcat/tomcat-base-8.5.50
[root@ubuntu1804 ~]#cd /data/dockerfile/web/tomcat/tomcat-base-8.5.50
[root@ubuntu1804 tomcat-base-8.5.50]#
wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-
8/v8.5.50/bin/apache-tomcat-8.5.50.tar.gz
2.3.5.3.2 编辑Dockerfile
[root@ubuntu1804 ~]#cat /data/dockerfile/web/tomcat/tomcat-base-
8.5.50/Dockerfile
#Tomcat Base Image
FROM centos7-jdk:8u212
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
#env
ENV TZ "Asia/Shanghai"
ENV LANG en_US.UTF-8
ENV TERM xterm
ENV TOMCAT_MAJOR_VERSION 8
ENV TOMCAT_MINOR_VERSION 8.5.50
ENV CATALINA_HOME /apps/tomcat
ENV APP_DIR ${CATALINA_HOME}/webapps
RUN mkdir /apps
ADD apache-tomcat-8.5.50.tar.gz /apps
RUN ln-s /apps/apache-tomcat-8.5.50 /apps/tomcat
2.3.5.3.3 通过脚本构建tomcat 基础镜像
[root@ubuntu1804 tomcat-base-8.5.50]#vim  build.sh
[root@ubuntu1804 tomcat-base-8.5.50]#cat build.sh
#!/bin/bash
docker build -t tomcat-base:v8.5.50 .
[root@ubuntu1804 tomcat-base-8.5.50]#tree
.
├── apache-tomcat-8.5.50.tar.gz
├── build.sh
└── Dockerfile
0 directories, 3 files
[root@ubuntu1804 tomcat-base-8.5.50]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
tomcat-base         v8.5.50             8d5395cb72c4        3 seconds ago
824MB
centos7-jdk         8u212               e0fe770a7ccd        22 minutes ago
809MB
centos7-base        v1                  34ab3afcd3b3        2 hours ago
403MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.3.5.3.4 验证镜像构建完成
[root@ubuntu1804 tomcat-base-8.5.50]#docker run -it --rm -p 8080:8080  tomcat-
base:v8.5.50 bash
[root@d0a387e0ccc9 /]# /apps/tomcat/bin/catalina.sh start
Using CATALINA_BASE:   /apps/tomcat
Using CATALINA_HOME:   /apps/tomcat
Using CATALINA_TMPDIR: /apps/tomcat/temp
Using JRE_HOME:        /usr/local/jdk/jre
Using CLASSPATH:       /apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-
juli.jar
Tomcat started.
[root@d0a387e0ccc9 /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        000.0.0.0:8009            0.0.0.0:*               LISTEN
tcp        000.0.0.0:8080            0.0.0.0:*               LISTEN
[root@d0a387e0ccc9 /]#
2.3.5.4 构建业务镜像1

创建tomcat-app1和tomcat-app2两个目录,代表不同的两个基于tomcat的业务。

2.3.5.4.1 准备tomcat的配置文件
[root@ubuntu1804 ~]#mkdir -p /data/dockerfile/web/tomcat/tomcat-app{1,2}
[root@ubuntu1804 ~]#tree /data/dockerfile/web/tomcat/
/data/dockerfile/web/tomcat/
├── tomcat-app1
├── tomcat-app2
└── tomcat-base-8.5.50
    ├── apache-tomcat-8.5.50.tar.gz
    ├── build.sh
    └── Dockerfile
3 directories, 3 files
#上传和修改server.xml
[root@ubuntu1804 ~]#cd /data/dockerfile/web/tomcat/tomcat-base-8.5.50
[root@ubuntu1804 tomcat-base-8.5.50]#tar xf apache-tomcat-8.5.50.tar.gz
[root@ubuntu1804 tomcat-base-8.5.50]#cp apache-tomcat-8.5.50/conf/server.xml
/data/dockerfile/web/tomcat/tomcat-app1/
[root@ubuntu1804 tomcat-base-8.5.50]#cd /data/dockerfile/web/tomcat/tomcat-app1/
[root@ubuntu1804 tomcat-app1]#vim server.xml
......
 <Host name="localhost"appBase="/data/tomcat/webapps"
unpackWARs="true"autoDeploy="true">
......

2.3.5.4.2 准备自定义页面
[root@ubuntu1804 tomcat-app1]#mkdir app
[root@ubuntu1804 tomcat-app1]#echo "Tomcat Page in app1" > app/index.jsp
[root@ubuntu1804 tomcat-app1]#tar zcf app.tar.gz app
2.3.5.4.3 准备容器启动执行脚本
[root@ubuntu1804 tomcat-app1]#vim run_tomcat.sh
[root@ubuntu1804 tomcat-app1]#cat run_tomcat.sh
#!/bin/bash
echo"nameserver 180.76.76.76" > /etc/resolv.conf
su- www -c"/apps/tomcat/bin/catalina.sh start"
su- www -c"tail -f /etc/hosts"
[root@ubuntu1804 tomcat-app1]#chmod a+x run_tomcat.sh
2.3.5.4.4 准备Dockerfile
[root@ubuntu1804 tomcat-app1]#vim Dockerfile
[root@ubuntu1804 tomcat-app1]#cat Dockerfile
#Tomcat Web Image
FROM tomcat-base:v8.5.50
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD server.xml /apps/tomcat/conf/server.xml
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD app.tar.gz /data/tomcat/webapps/
RUN chown-R www.www /apps/   /data/tomcat/
EXPOSE 80808009
CMD ["/apps/tomcat/bin/run_tomcat.sh"]

2.3.5.4.5 执行构建脚本制作镜像

[root@ubuntu1804 tomcat-app1]#vim build.sh
[root@ubuntu1804 tomcat-app1]#cat build.sh
#!/bin/bash
docker build -t tomcat-web:app1 .
[root@ubuntu1804 tomcat-app1]#pwd
/data/dockerfile/web/tomcat/tomcat-app1
[root@ubuntu1804 tomcat-app1]#tree
.
├── app
│   └── index.jsp
├── app.tar.gz
├── build.sh
├── Dockerfile
├── run_tomcat.sh
└── server.xml
1 directory, 6 files
[root@ubuntu1804 tomcat-app1]#bash build.sh
[root@ubuntu1804 tomcat-app1]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
tomcat-web          app1                3e9eacc5ef86        4 seconds ago
824MB
tomcat-base         v8.5.50             8d5395cb72c4        35 minutes ago
824MB
centos7-jdk         8u212               e0fe770a7ccd        57 minutes ago
809MB
centos7-base        v1                  34ab3afcd3b3        2 hours ago
403MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.3.5.4.6 从镜像启动测试容器
[root@ubuntu1804 tomcat-app1]#docker run -d  -p 8080:8080  tomcat-web:app1
82e6690e36c3a6faf2dae62bd706a89cbba490d567c841c37501f0fba670ea25
2.3.5.4.7 访问测试
[root@ubuntu1804 ~]#curl 127.0.0.1:8080/app/
Tomcat Page in app1
[root@ubuntu1804 ~]#docker exec -it 82e6690e36c3  bash
[root@82e6690e36c3 /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          10.0  0.2  151362248 ?        Ss   22:14   0:00 /bin/bash
/apps/tomcat/bin/run_tomcat.sh
www          250.8  9.7 224165695924 ?       Sl   22:14   0:04
/usr/local/jdk/bin/java -Djava.util.logging.config.file=/apps/tomcat
root         260.0  0.4  854284472 ?        S    22:14   0:00 su- www -c
tail -f /etc/hosts
www          270.0  0.0   4416720 ?        Ss   22:14   0:00 tail -f
/etc/hosts
root         8225.0  0.3  158003820 pts/0    Ss   22:22   0:00 bash
root        1010.0  0.3  551963836 pts/0    R+22:22   0:00 ps aux
[root@82e6690e36c3 /]# vim /data/tomcat/webapps/app/index.jsp
[root@82e6690e36c3 /]# cat /data/tomcat/webapps/app/index.jsp
Tomcat Page in app1 v2
[root@82e6690e36c3 /]# /apps/tomcat/bin/catalina.sh stop
Using CATALINA_BASE:   /apps/tomcat
Using CATALINA_HOME:   /apps/tomcat
Using CATALINA_TMPDIR: /apps/tomcat/temp
Using JRE_HOME:        /usr/local/jdk/jre
Using CLASSPATH:       /apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-
juli.jar
[root@82e6690e36c3 /]# /apps/tomcat/bin/catalina.sh start
Using CATALINA_BASE:   /apps/tomcat
Using CATALINA_HOME:   /apps/tomcat
Using CATALINA_TMPDIR: /apps/tomcat/temp
Using JRE_HOME:        /usr/local/jdk/jre
Using CLASSPATH:       /apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-
juli.jar
Tomcat started.
[root@ubuntu1804 tomcat-app1]#curl 127.0.0.1:8080/app/
Tomcat Page in app1 v2
2.3.5.4 构建业务镜像2
2.3.5.4.1 准备自定义页面和其它数据
[root@ubuntu1804 tomcat]#pwd
/data/dockerfile/web/tomcat
[root@ubuntu1804 tomcat]#cp -a tomcat-app1/* tomcat-app2/
[root@ubuntu1804 tomcat]#tree tomcat-app2/
tomcat-app2/
├── app
│   └── index.jsp
├── app.tar.gz
├── build.sh
├── Dockerfile
├── run_tomcat.sh
└── server.xml
1 directory, 6 files
[root@ubuntu1804 tomcat]#cd tomcat-app2
[root@ubuntu1804 tomcat-app2]#echo "Tomcat Page in app2" > app/index.html
[root@ubuntu1804 tomcat-app2]#rm -f app.tar.gz
[root@ubuntu1804 tomcat-app2]#tar zcf app.tar.gz app
2.3.5.4.2 准备容器启动脚本run_tomcat.sh

和业务1一样不变

2.3.5.4.3 准备Dockerfile

和业务1一样不变

2.3.5.4.4 执行构建脚本制作镜像
[root@ubuntu1804 tomcat-app2]#vim build.sh
[root@ubuntu1804 tomcat-app2]#cat build.sh
#!/bin/bash
docker build -t tomcat-web:app2 .
[root@ubuntu1804 tomcat-app2]#bash build.sh
[root@ubuntu1804 tomcat-app2]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
tomcat-web          app2                0e1760fe79a6        37 seconds ago
838MB
tomcat-web          app1                76016219a0ca        27 minutes ago
838MB
tomcat-base         v8.5.50             8d5395cb72c4        2 hours ago
824MB
centos7-jdk         8u212               e0fe770a7ccd        2 hours ago
809MB
centos7-base        v1                  34ab3afcd3b3        3 hours ago
403MB
centos              centos7.7.1908      08d05d1d5859        2 months ago
204MB
2.3.5.4.5 从镜像启动容器测试
[root@ubuntu1804 tomcat-app2]#docker run  -d -p 8082:8080 tomcat-web:app2
3fc9437e42099e92f88e8e09bac0507f2d837ac8a6dba8cb1e4efc934bcf81ff
2.3.5.4.6 访问测试
[root@ubuntu1804 tomcat-app2]#curl 127.0.0.1:8082/app/
Tomcat Page in app2

2.3.6 生产案例: 构建haproxy镜像

2.3.6.1 准备相关文件
#准备haproxy源码文件
[root@ubuntu1804 ~]#mkdir -p  /data/dockerfile/web/haproxy/2.1.2-centos7
[root@ubuntu1804 ~]#cd /data/dockerfile/web/haproxy/2.1.2-centos7
[root@ubuntu1804 2.1.2-centos7]#wget
http://www.haproxy.org/download/2.1/src/haproxy-2.1.2.tar.gz
#准备haproxy启动脚本
[root@ubuntu1804 2.1.2-centos7]#vim run_haproxy.sh
[root@ubuntu1804 2.1.2-centos7]#cat run_haproxy.sh
#!/bin/bash
haproxy -f /etc/haproxy/haproxy.cfg
tail -f /etc/hosts
2.3.6.2 准备haproxy配置文件
#准备haproxy配置文件
[root@ubuntu1804 2.1.2-centos7]#cat haproxy.cfg
global
chroot /apps/haproxy
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 99
gid 99
daemon
nbproc 1
pidfile /apps/haproxy/run/haproxy.pid
log 127.0.0.1 local3 info
defaults
option http-keep-alive
option forwardfor
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
 mode http
 bind 0.0.0.0:9999
 stats enable
 log global
 stats uri   /haproxy-status
 stats auth  haadmin:123456
listen web_port
 bind 0.0.0.0:80
 mode http
 log global
 balance roundrobin
 server web1 10.0.0.101:8080 check inter 3000 fall 2 rise 5
 server web2 10.0.0.102:8080 check inter 3000 fall 2 rise 5

2.3.6.3 准备Dockerfile

[root@ubuntu1804 2.1.2-centos7]#pwd
/data/dockerfile/web/haproxy/2.1.2-centos7
[root@ubuntu1804 haproxy]# cat Dockerfile
#Haproxy Base Image
FROM centos7-base:v1
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD haproxy-2.1.2.tar.gz /usr/local/src/
RUN cd /usr/local/src/haproxy-2.1.2 \
    && makeARCH=x86_64 TARGET=linux-glibc USE_PCRE=1USE_OPENSSL=1USE_ZLIB=1
USE_SYSTEMD=1USE_CPU_AFFINITY=1PREFIX=/apps/haproxy \
    && make install PREFIX=/apps/haproxy \
    && ln-s /apps/haproxy/sbin/haproxy  /usr/sbin/ \
    && mkdir /apps/haproxy/run \
    && rm-rf /usr/local/src/haproxy*
ADD haproxy.cfg /etc/haproxy/
ADD run_haproxy.sh /usr/bin
EXPOSE 809999
CMD ["run_haproxy.sh"]
2.3.6.4 准备构建脚本构建haproxy镜像
[root@ubuntu1804 2.1.2-centos7]#vim build.sh
[root@ubuntu1804 2.1.2-centos7]#cat  build.sh
#!/bin/bash
docker build -t haproxy-centos7:2.1.2 .
[root@ubuntu1804 2.1.2-centos7]#ls
build.sh  Dockerfile  haproxy-2.1.2.tar.gz  haproxy.cfg  run_haproxy.sh
[root@ubuntu1804 2.1.2-centos7]#bash build.sh
[root@ubuntu1804 2.1.2-centos7]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
haproxy-centos7     2.1.2               5eccdb29a058        26 minutes ago
428MB
nginx-ubuntu1804    1.16.1              19efdd23ac87        15 hours ago
378MB
alpine-nginx        1.16.1              978a43bbb61d        16 hours ago
211MB
nginx-alpine        1.16.1              978a43bbb61d        16 hours ago
211MB
alpine-base         3.11                b162eecf4da9        17 hours ago
182MB
tomcat-web          app2                0e1760fe79a6        37 hours ago
838MB
tomcat-web          app1                76016219a0ca        37 hours ago
838MB
tomcat-base v8.5.50 8d5395cb72c438 hours ago
824MB
centos7-jdk 8u212 e0fe770a7ccd39 hours ago
809MB
centos7-base v1 34ab3afcd3b340 hours ago
403MB
alpine 3.11 e7d92cdc71fe12 days ago
5.59MB
alpine latest e7d92cdc71fe12 days ago
5.59MB
ubuntu 18.04 ccc6e87d482b2 weeks ago
64.2MB
ubuntu bionic ccc6e87d482b2 weeks ago
64.2MB
centos
204MB
centos7.7.1908 08d05d1d58592 months ago
2.3.6.5 从镜像启动容器
[root@ubuntu1804 2.1.2-centos7]#docker run -d -p 80:80 -p 9999:9999 haproxy-
centos7:2.1.2
e0a7c827cb5fdd5a630f7dfe58b1f60822da18929a4dfeccb7490fb78403e3df
2.3.6.6 在另外两台主机启动容器

# 导出本地相关镜像

[root@ubuntu1804 ~]#docker save centos7-base:v1 > /data/centos7-base.tar.gz
[root@ubuntu1804 ~]#docker save centos7-jdk:8u212 > /data/centos7-jdk.tar.gz
[root@ubuntu1804 ~]#docker save tomcat-base:v8.5.50 > /data/tomcat-base.tar.gz
[root@ubuntu1804 ~]#docker save tomcat-web:app1 > /data/tomcat-web-app1.tar.gz
[root@ubuntu1804 ~]#docker save tomcat-web:app2 > /data/tomcat-web-app2.tar.gz
[root@ubuntu1804 ~]#ls /data
centos7-base.tar.gz  centos7-jdk.tar.gz  dockerfile  tomcat-base.tar.gz  tomcat-
web-app1.tar.gz  tomcat-web-app2.tar.gz

# 将镜像复制到另外两台主机

[root@ubuntu1804 ~]#scp /data/*.gz 10.0.0.101:/data/
[root@ubuntu1804 ~]#scp /data/*.gz 10.0.0.102:/data/
#在另外两台主机上执行下面操作导入镜像
[root@ubuntu1804 ~]#ls /data
centos7-base.tar.gz  lost+found          tomcat-web-app1.tar.gz
centos7-jdk.tar.gz   tomcat-base.tar.gz  tomcat-web-app2.tar.gz
[root@ubuntu1804 ~]#for i in /data/*.gz;do docker load -i $i;done

# 在另外两台主机上创建相关容器

[root@ubuntu1804 ~]#docker run -d -p 8080:8080 tomcat-web:app1
781681e73333396b23f404e70d0c781ab464a8e9b578f41c153583d23bd76a46
[root@ubuntu1804 ~]#docker run -d -p 8080:8080 tomcat-web:app2
81fa01a688cb72cf397a5da46acc89a51f2a2f8de3a0072565d701625c43540a
2.3.6.7 web访问验证
[root@ubuntu1804 2.1.2-centos7]#curl http://10.0.0.100/app/
Tomcat Page in app1
[root@ubuntu1804 2.1.2-centos7]#curl http://10.0.0.100/app/
Tomcat Page in app2
[root@ubuntu1804 2.1.2-centos7]#docker exec -it e0a7c827cb5 bash
[root@e0a7c827cb5f /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        000.0.0.0:9999            0.0.0.0:*               LISTEN
tcp        000.0.0.0:80              0.0.0.0:*               LISTEN
[root@e0a7c827cb5f /]# vim /etc/haproxy/haproxy.cfg
[root@e0a7c827cb5f /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          10.0  0.2  117002428 ?        Ss   11:01   0:00 /bin/bash
/usr/bin/run_haproxy.sh
nobody        70.0  7.1 18107670324 ?        Ss   11:01   0:00 haproxy -f
/etc/haproxy/haproxy.cfg
root          80.0  0.0   4416772 ?        S    11:01   0:00 tail -f
/etc/hosts
root          90.1  0.3  124883696 pts/0    Ss   11:02   0:00 bash
root         540.0  0.3  517643448 pts/0    R+11:06   0:00 ps aux

#在第二台主机上停止容器
[root@ubuntu1804 ~]#docker stop 81fa01a688cb
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS                        PORTS               NAMES
81fa01a688cb        tomcat-web:app2     "/apps/tomcat/bin/ru…"28 minutes ago
     Exited (137) 39 seconds ago
#观察状态页,发现后端服务器down

#在第二台主机上恢复启动容器
[root@ubuntu1804 ~]#docker start 81fa01a688cb
81fa01a688cb
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                              NAMES
81fa01a688cb        tomcat-web:app2     "/apps/tomcat/bin/ru…"30 minutes ago
     Up 14 seconds       8009/tcp, 0.0.0.0:8080->8080/tcp   optimistic_shirley
#再次观察状态页,发现后端服务器上线

2.3.7 生产案例: 基于 Alpine 基础镜像制作 Nginx 镜像

2.3.7.1 制作 Alpine 的自定义系统镜像
#下载alpine镜像,打新标签
[root@ubuntu1804 ~]#docker pull alpine
[root@ubuntu1804 ~]#docker tag  alpine alpine:3.11
[root@ubuntu1804 ~]#docker images
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine              3.11                e7d92cdc71fe        11 days ago
5.59MB
alpine              latest              e7d92cdc71fe        11 days ago
5.59MB
#准备相关文件
[root@ubuntu1804 ~]#cd /data/dockerfile/system/alpine
[root@ubuntu1804 alpine]#cat repositories
http://mirrors.aliyun.com/alpine/v3.11/main
http://mirrors.aliyun.com/alpine/v3.11/community
#准备Dockerfile文件
[root@ubuntu1804 alpine]#cat Dockerfile
FROM alpine:3.11
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY repositories /etc/apk/repositories
RUN  apk update && apk --no-cache add  iotop  gcc libgcc libc-dev libcurl libc-
utils pcre-dev zlib-dev  libnfs make  pcre pcre2 zip unzip net-tools pstree wget
libevent libevent-dev iproute2
#准备构建脚本
[root@ubuntu1804 alpine]#cat build.sh
#!/bin/bash
docker build -t alpine-base:3.11 .
[root@ubuntu1804 alpine]#bash build.sh
[root@ubuntu1804 alpine]#docker images  alp*
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
alpine-base         3.11                b162eecf4da9        5 minutes ago
182MB
alpine              3.11                e7d92cdc71fe        11 days ago
5.59MB
alpine              latest              e7d92cdc71fe        11 days ago
5.59MB
2.3.7.2 制作基于 Alpine 自定义镜像的 Nginx 镜像
#准备相关文件
[root@ubuntu1804 ~]#mkdir /data/dockerfile/web/nginx/1.16.1-alpine/
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1-alpine/
[root@ubuntu1804 1.16.1-alpine]#wget http://nginx.org/download/nginx-
1.16.1.tar.gz
[root@ubuntu1804 1.16.1-alpine]#echo Test Page based nginx-alpine > index.html
[root@ubuntu1804 1.16.1-alpine]#cp ../1.16.1-centos7/nginx.conf  .
[root@ubuntu1804 1.16.1-alpine]#cat nginx.conf
user  nginx;
worker_processes  1;
daemon off;
...
location / {
            root   /data/nginx/html;
...
#编写Dockerfile文件
[root@ubuntu1804 1.16.1-alpine]#vim Dockerfile
[root@ubuntu1804 1.16.1-alpine]#cat Dockerfile
FROM alpine-base:3.11
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD nginx-1.16.1.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.16.1 && ./configure  --prefix=/apps/nginx && make
&& make install && ln-s /apps/nginx/sbin/nginx  /usr/bin/
RUN addgroup  -g2019-S nginx && adduser  -s /sbin/nologin -S-D-u2019-G
nginx nginx
COPY nginx.conf /apps/nginx/conf/nginx.conf
ADD index.html /data/nginx/html/index.html
RUN chown-R  nginx.nginx  /data/nginx/ /apps/nginx/
EXPOSE 80443
CMD ["nginx"]
#构建镜像
[root@ubuntu1804 1.16.1-alpine]#vim build.sh
[root@ubuntu1804 1.16.1-alpine]#cat build.sh
#!/bin/bash
#********************************************************************
docker build -t nginx-alpine:1.16.1 .
[root@ubuntu1804 1.16.1-alpine]#ls
build.sh  Dockerfile  index.html  nginx-1.16.1.tar.gz  nginx.conf
[root@ubuntu1804 1.16.1-alpine]#docker images “*alpine*”
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
nginx-alpine        1.16.1              344ff9acf58b        13 seconds ago
211MB
alpine-base         3.11                b162eecf4da9        About an hour ago
182MB
alpine              3.11                e7d92cdc71fe        11 days ago
5.59MB
alpine              latest              e7d92cdc71fe        11 days ago
5.59MB
#生成容器测试镜像
[root@ubuntu1804 1.16.1-alpine]#docker run -d -p  80:80 nginx-alpine:1.16.1
1cb16e9fe6cd8e583a61c2718a92ce3031313bbf3656c2f85ac84d34ccfe7e0d
[root@ubuntu1804 1.16.1-alpine]#curl 127.0.0.1
Test Page based nginx-alpine
[root@ubuntu1804 1.16.1-alpine]#docker exec -it 1cb16e9fe6cd sh
/ # ps aux
PID   USER     TIME  COMMAND
1 root      0:00 nginx: master process nginx
6 nginx     0:00 nginx: worker process
7 root      0:00 sh
12 root      0:00 ps aux
/ # ls /data/nginx/html/ -l
total 4
-rw-r--r--1 nginx    nginx           29 Jan 2911:08 index.html
/ # exit
[root@ubuntu1804 1.16.1-alpine]#

2.3.8 生产案例: 基于 Ubuntu 基础镜像制作 Nginx 镜像

#下载ubuntu1804镜像
[root@ubuntu1804 ~]#docker pull ubuntu:18.04
[root@ubuntu1804 ~]#docker images ubuntu*
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
ubuntu              18.04               ccc6e87d482b        13 days ago
64.2MB
#准备相关文件
[root@ubuntu1804 ~]#mkdir /data/dockerfile/web/nginx/1.16.1-ubuntu1804
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1-ubuntu1804
[root@ubuntu1804 1.16.1-ubuntu1804]#vim sources.list
[root@ubuntu1804 1.16.1-ubuntu1804]#cat sources.list
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted
universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe
multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted
universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe
multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted
universe multiverse
[root@ubuntu1804 1.16.1-ubuntu1804]#wget http://nginx.org/download/nginx-
1.16.1.tar.gz
[root@ubuntu1804 1.16.1-ubuntu1804]#cp ../1.16.1-alpine/nginx.conf .
[root@ubuntu1804 1.16.1-ubuntu1804]#echo Test Page based nginx-ubuntu1804 >
index.html
#编写Dockerfile文件
[root@ubuntu1804 1.16.1-ubuntu1804]#vim Dockerfile
[root@ubuntu1804 1.16.1-ubuntu1804]#cat Dockerfile
FROM ubuntu:18.04
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY sources.list /etc/apt/sources.list
RUN apt update && apt  install -y  nfs-kernel-server nfs-common  gcc openssh-
server lrzsz tree  openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev   unzip
zip make
ADD nginx-1.16.1.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.16.1 && ./configure --prefix=/apps/nginx && make
&& make install && ln-s /apps/nginx/sbin/nginx /usr/bin && rm-rf
/usr/local/src/nginx-1.16.1*
ADD nginx.conf /apps/nginx/conf/nginx.conf
ADD index.html /data/nginx/html/index.html
RUN groupadd  -g2019 nginx && useradd  -g nginx -s /usr/sbin/nologin -u2019
nginx && chown-R nginx.nginx /apps/nginx /data/nginx
EXPOSE 80443
CMD ["nginx"]

# 构建镜像

[root@ubuntu1804 1.16.1-ubuntu1804]#vim build.sh
[root@ubuntu1804 1.16.1-ubuntu1804]#cat build.sh
#!/bin/bash
docker build -t nginx-ubuntu1804:1.16.1 .
[root@ubuntu1804 1.16.1-ubuntu1804]#ls
build.sh  Dockerfile  index.html  nginx-1.16.1.tar.gz  nginx.conf  sources.list
[root@ubuntu1804 1.16.1-ubuntu1804]#docker images "nginx*"
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
nginx-ubuntu1804    1.16.1              19efdd23ac87        4 minutes ago
378MB
nginx-alpine        1.16.1              978a43bbb61d        40 minutes ago
211MB
nginx-centos7       1.6.1-v2            1918d29d5f45        17 minutes ago
328MB
nginx-centos7       1.6.1               8c16774437a5        13 hours ago
412MB

# 启动容器测试镜像

[root@ubuntu1804 1.16.1-ubuntu1804]#docker run -d  -p 80:80 nginx-
ubuntu1804:1.16.1
58f8e9a8fd6eebb19bd2b7c27bd8d52a3a4d42637a942e1e9179ec1b2bcc559d
[root@ubuntu1804 1.16.1-ubuntu1804]#curl 127.0.0.1
Test Page based nginx-ubuntu1804

3 Docker 数据管理

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层

如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW copy on write)"机制

如果将正在运行中的容器修改生成了新的数据,那么新产生的数据将会被复制到读写层,进行持久化保存,这个读写层也就是容器的工作目录,也为写时复制(COW) 机制。

COW机制节约空间,但会导致性低下,虽然关闭重启容器,数据不受影响,但会随着容器的删除,其对应的可写层也会随之而删除,即数据也会丢失.如果容器需要持久保存数据,并不影响性能可以用数据卷技术实现

如下图是将对根的数据写入到了容器的可写层,但是把/data 中的数据写入到了一个另外的volume 中用于数据持久化

3.1 容器的数据管理介绍

Docker镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层中。

3.1.1 Docker容器的分层

容器的数据分层目录

LowerDir: image 镜像层,即镜像本身,只读

UpperDir: 容器的上层,可读写 ,容器变化的数据存放在此处

MergedDir: 容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和 upperdir 合并完成后给容器使用,最终呈现给用户的统一视图

WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见

范例: 查看指定容器数据分层

[root@ubuntu1804 ~]#docker inspect  12959f2c152f
"GraphDriver": {
"Data": {
"LowerDir":
"/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9
ed58751761-
init/diff:/var/lib/docker/overlay2/4a259e4cc9da105d17075e316c3e1f7c29abd6f7a37c5
c7c29251a7e5f0e7eb3/diff",
"MergedDir":
"/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9
ed58751761/merged",
"UpperDir":
"/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9
ed58751761/diff",
"WorkDir":
"/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9
ed58751761/work"
            },
"Name": "overlay2"
[root@ubuntu1804 ~]#ll -i
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761
total 28
920832 drwx------  5 root root 4096 Jan 3119:02 ./
917524 drwx------ 53 root root 4096 Jan 3119:02 ../
920843 drwxr-xr-x  3 root root 4096 Jan 3119:02 diff/
920846-rw-r--r--1 root root   26 Jan 3119:02 link
920851-rw-r--r--1 root root   57 Jan 3119:02 lower
920818 drwxr-xr-x  1 root root 4096 Jan 3119:02 merged/
920847 drwx------  3 root root 4096 Jan 3119:02 work/
[root@ubuntu1804 ~]#tree -d
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/
├── diff
│   └── root
├── merged
│   ├── bin
│   ├── dev
│   │   ├── pts
│   │   └── shm
│   ├── etc
│   │   ├── apk
  • │ │ │ ├── keys

  • │ │ │ └── protected_paths.d

  • │ │ ├── conf.d

  • │ │ ├── crontabs

  • │ │ ├── init.d

  • │ │ ├── logrotate.d

  • │ │ ├── modprobe.d

  • │ │ ├── modules-load.d

  • │ │ ├── network

  • │ │ │ ├── if-down.d

  • │ │ │ ├── if-post-down.d

  • │ │ │ ├── if-post-up.d

  • │ │ │ ├── if-pre-down.d

  • │ │ │ ├── if-pre-up.d

  • │ │ │ └── if-up.d

  • │ │ ├── opt

  • │ │ ├── periodic

  • │ │ │ ├── 15min

  • │ │ │ ├── daily

  • │ │ │ ├── hourly

  • │ │ │ ├── monthly

  • │ │ │ └── weekly

  • │ │ ├── profile.d

  • │ │ ├── ssl

  • │ │ │ ├── certs

  • │ │ │ ├── misc

  • │ │ │ └── private

  • │ │ └── sysctl.d

  • │ ├── home

  • │ ├── lib

  • │ │ ├── apk

  • │ │ │ └── db

│   │   ├── firmware
│   │   └── mdev
│   ├── media
│   │   ├── cdrom
│   │   ├── floppy
│   │   └── usb
│   ├── mnt
│   ├── opt
│   ├── proc
│   ├── root
│   ├── run
│   ├── sbin
│   ├── srv
│   ├── sys
│   ├── tmp
│   ├── usr
│   │   ├── bin
│   │   ├── lib
│   │   │   └── engines-1.1
│   │   ├── local
│   │   │   ├── bin
│   │   │   ├── lib
│   │   │   └── share
│   │   ├── sbin
│   │   └── share
│   │       ├── apk
│   │       │   └── keys
│   │       │       ├── aarch64
│   │       │       ├── armhf
│   │       │       ├── ppc64le
│   │       │       ├── s390x
│   │       │       ├── x86
│   │       │       └── x86_64
│   │       ├── man
│   │       ├── misc
│   │       └── udhcpc
│   └── var
│       ├── cache
│       │   ├── apk
│       │   └── misc
│       ├── empty
│       ├── lib
│       │   ├── apk
│       │   ├── misc
│       │   └── udhcpd
│       ├── local
│       ├── lock
│       │   └── subsys
│       ├── log
│       ├── mail
│       ├── opt
│       ├── run -> /run
│       ├── spool
│       │   ├── cron
│       │   └── mail -> /var/mail
│       └── tmp
└── work
    └── work
99 directories
[root@ubuntu1804 ~]#docker run -it  alpine:3.11  sh
/ #  dd if=/dev/zero of=/root/test.img bs=1M count=10
10+0 records in
10+0 records out
/ #
#每个镜像层目录中包含了一个文件link,文件内容则是当前层对应的短标识符,镜像层的内容则存放在diff
目录
[root@ubuntu1804 ~]#find
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761 -name test.img -ls
92090310240-rw-r--r--1 root     root     10485760 Jan 3119:02
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/merged/root/test.img
92090310240-rw-r--r--1 root     root     10485760 Jan 3119:02
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/diff/root/test.img
[root@ubuntu1804 ~]#mount

overlay on

/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/merged type overlay
(rw,relatime,lowerdir=/var/lib/docker/overlay2/l/OIRNCV35BGPGWKRWEMCJD5SYUZ:/var
/lib/docker/overlay2/l/VZ7N54CVY2JLDASJAZ6AASRQSJ,upperdir=/var/lib/docker/overl
ay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9ed58751761/diff,workdi
r=/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf
9ed58751761/work)
nsfs on /run/docker/netns/6ce1d74bc9af type nsfs (rw)
[root@ubuntu1804 ~]#tree
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/diff/
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/diff/
└── root
    └── test.img
1 directory, 1 file
[root@ubuntu1804 ~]#ls
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/merged/
bin  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp
usr  var
[root@ubuntu1804 ~]#docker run -it  alpine:3.11  sh
/ # echo welcome to magedu >> /etc/issue
/ # cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
welcome to magedu
/ #
[root@ubuntu1804 ~]#tree
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/diff/
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761/diff/
├── etc
│   └── issue
└── root
    └── test.img
2 directories, 2 files
#删除容器后,所有容器数据目录都随之而删除
[root@ubuntu1804 ~]#docker rm -f 12959f2c152f
[root@ubuntu1804 ~]#ls
/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9e
d58751761
ls: cannot access
'/var/lib/docker/overlay2/848d77064091ba3ddd25a10ea6e0065af15ee701fed06f82804cf9
ed58751761': No such file or directory

3.1.2 哪些数据需要持久化

有状态的协议

有状态协议就是就通信双方要记住双方,并且共享一些信息。
无状态协议的通信每次都是独立的,与上一次的通信没什么关系。
"状态”可以理解为“记忆”,有状态对应有记忆,无状态对应无记忆

  • 左侧是无状态的http请求服务,右侧为有状态

  • 下层为不需要存储的服务,上层为需要存储的部分服务

3.1.3 容器数据持久保存方式

如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录

Docker的数据类型分为两种:

  • 数据卷(Data Volume): 直接将宿主机目录挂载至容器的指定的目录 ,推荐使用此种方式,此方式较常用

  • 数据卷容器(Data Volume Container): 间接使用宿主机空间,数据卷容器是将宿主机的目录挂载至一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据 ,此方式不常用

3.2 数据卷

3.2.1 数据卷特点和使用

数据卷实际上就是宿主机上的目录或者是文件,可以被直接mount到容器当中使用

实际生成环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性

3.2.1.1 数据卷使用场景
  • 数据库

  • 日志输出

  • 静态web页面

  • 应用配置文件

  • 多容器间目录或文件共享

3.2.1.2 数据卷的特点
  • 数据卷是目录或者文件,并且可以在多个容器之间共同使用,实现容器之间共享和重用对数据卷更改数据在所有容器里面会立即更新。

  • 数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。

  • 在容器里面的写入数据不会影响到镜像本身,即数据卷的变化不会影响镜像的更新

  • 依赖于宿主机目录,宿主机出问题,上面容器会受影响,当宿主机较多时,不方便统一管理

  • 匿名和命名数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,会拷贝到新初始化的数据卷中

3.2.1.3 数据卷分类

启动容器时,可以指定使用数据卷实现容器数据的持久化,数据卷有三种

  • 指定宿主机目录或文件: 指定宿主机的具体路径和容器路径的挂载关系,此方式不会创建数据卷匿名卷: 不指定数据名称,只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载,此方式会创建匿名数据卷,Dockerfile中VOLUME指定的卷即为此种

  • 命名卷: 指定数据卷的名称和容器路径的挂载关系,此方式会创建命名数据卷

3.2.1.4 数据卷使用方法

docker run 命令的以下格式可以实现数据卷

-v, --volume=[host-src:]container-dest[:<options>]
<options>
ro 从容器内对此数据卷是只读,不写此项默认为可读可写
rw 从容器内对此数据卷可读可写,此为默认值

方式1

#指定宿主机目录或文件格式:
-v   <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro]  #将宿主机目录挂载容器目录,两个目录
都可自动创建

方式2

#匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷
ID>/_data目录,并挂载至容器指定路径
-v <容器内路径>
#示例:
docker run --name nginx -v /etc/nginx nginx

方式3

#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
docker volume  create <卷名>
#示例:
docker volume  create vol1  #也可以事先不创建
docker run -d-p80:80 --name nginx01 -v vol1:/usr/share/nginx/html  nginx

docker rm 的 -v 选项可以删除容器时,同时删除相关联的匿名卷

-v, --volumes   Remove the volumes associated with the container

管理数据卷命令

docker volume COMMAND
Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
ls          List volumes
  prune       Remove all unused local volumes
rm          Remove one or more volumes

查看数据卷的挂载关系

docker inspect --format="{{.Mounts}}"  <容器ID>

范例: 删除所有数据卷

[root@ubuntu1804 ~]#docker volume rm `docker volume ls -q`

范例:创建命名卷并删除

[root@ubuntu1804 ~]#docker volume create mysql-vol
mysql-vol
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME
local               mysql-vol
[root@ubuntu1804 ~]#tree /var/lib/docker/volumes/
/var/lib/docker/volumes/
├── metadata.db
└── mysql-vol
    └── _data
2 directories, 1 file
[root@ubuntu1804 ~]#docker volume rm mysql-vol
mysql-vol
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME

范例:删除不再使用的数据卷

[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME
local
897bd48c5c5e2067627d5c6d10dad17d4793132a638986c16f36820663728ee1
[root@ubuntu1804 ~]#docker volume prune  -f
Deleted Volumes:
897bd48c5c5e2067627d5c6d10dad17d4793132a638986c16f36820663728ee1
Total reclaimed space: 219.5MB
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME

关于匿名数据卷和命名数据卷

命名卷就是有名字的卷,使用 docker volume create <卷名> 形式创建并命名的卷;而匿名卷就是没名
字的卷,一般是 docker run -v /data 这种不指定卷名的时候所产生,或者 Dockerfile 里面的定义
直接使用的。
有名字的卷,在用过一次后,以后挂载容器的时候还可以使用,因为有名字可以指定。所以一般需要保存的数
据使用命名卷保存。
而匿名卷则是随着容器建立而建立,随着容器消亡而淹没于卷列表中(对于 docker run 匿名卷不会被自动
删除)。因此匿名卷只存放无关紧要的临时数据,随着容器消亡,这些数据将失去存在的意义。
Dockerfile中指定VOLUME为匿名数据卷,其目的只是为了将某个路径确定为卷。
按照最佳实践的要求,不应该在容器存储层内进行数据写入操作,所有写入应该使用卷。如果定制镜像的时
候,就可以确定某些目录会发生频繁大量的读写操作,那么为了避免在运行时由于用户疏忽而忘记指定卷,导
致容器发生存储层写入的问题,就可以在 Dockerfile 中使用 VOLUME 来指定某些目录为匿名卷。这样即
使用户忘记了指定卷,也不会产生不良的后果。
这个设置可以在运行时覆盖。通过 docker run 的 -v 参数或者 docker-compose.yml 的 volumes
指定。使用命名卷的好处是可以复用,其它容器可以通过这个命名数据卷的名字来指定挂载,共享其内容(不
过要注意并发访问的竞争问题)。
比如,Dockerfile 中说 VOLUME /data,那么如果直接 docker run,其 /data 就会被挂载为匿名
卷,向 /data 写入的操作不会写入到容器存储层,而是写入到了匿名卷中。但是如果运行时 docker run
-v mydata:/data,这就覆盖了 /data 的挂载设置,要求将 /data 挂载到名为 mydata 的命名卷中。
所以说 Dockerfile 中的 VOLUME 实际上是一层保险,确保镜像运行可以更好的遵循最佳实践,不向容器
存储层内进行写入操作。
数据卷默认可能会保存于 /var/lib/docker/volumes,不过一般不需要、也不应该访问这个位置。

3.2.2 实战案例: 目录数据卷

3.2.2.1 在宿主机创建容器所使用的目录
[root@ubuntu1804 ~]#mkdir /data/testdir
[root@ubuntu1804 ~]#echo  Test page  on host > /data/testdir/index.html
3.2.2.2 查看容器相关目录路径
[root@ubuntu1804 ~]#docker images "*nginx*"
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
nginx-ubuntu1804    1.16.1              19efdd23ac87        2 days ago
378MB
nginx-alpine        1.16.1              978a43bbb61d        2 days ago
211MB
[root@ubuntu1804 ~]#docker run -it  --rm  nginx-alpine:1.16.1 sh
/ # cat /apps/nginx/conf/nginx.conf
...
    server {
...
        location / {
            root   /data/nginx/html;  #nginx存放网页文件的路径
            index  index.html index.htm;
        }
...
/ # cat  /data/nginx/html/index.html
Test Page based nginx-alpine
/ # exit
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
3.2.2.3 引用宿主机的数据卷启动容器

引用同一个数据卷目录,开启多个容器,实现多个容器共享数据

[root@ubuntu1804 ~]#docker run  -d -v /data/testdir:/data/nginx/html/   -p
8001:80 nginx-alpine:1.16.1
56a5460f584bd2de56040c4a1dff86ad8a9723cfd6bf21ed8a538b9629b0874c
[root@ubuntu1804 ~]#docker run  -d -v /data/testdir:/data/nginx/html/   -p
8002:80 nginx-alpine:1.16.1
e7b5bff6ce56fa51ed6411175c9c9f1fb9bf8e7b1b9471080380b01692f89e58
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED
STATUS              PORTS                           NAMES
e7b5bff6ce56        nginx-alpine:1.16.1   "nginx"6 seconds ago
  Up 5 seconds        443/tcp, 0.0.0.0:8002->80/tcp   hungry_robinson
56a5460f584b        nginx-alpine:1.16.1   "nginx"33 seconds ago
Up 31 seconds       443/tcp, 0.0.0.0:8001->80/tcp   stupefied_dubinsky
[root@ubuntu1804 ~]#curl 127.0.0.1:8001
Test page on host
[root@ubuntu1804 ~]#curl 127.0.0.1:8002
Test page on host
3.2.2.3 进入到容器内测试写入数据

进入其中一个容器写入数据,可以其它容器的数据也变化

[root@ubuntu1804 ~]#docker exec -it e7b5bff6ce56 sh
/ # df
Filesystem           1K-blocks      Used Available Use% Mounted on
overlay               4779902052944924004672412% /
tmpfs                    655360655360% /dev
tmpfs                   49255204925520% /sys/fs/cgroup
shm                      655360655360% /dev/shm
/dev/sda2             4779902052944924004672412% /etc/resolv.conf
/dev/sda2             4779902052944924004672412% /etc/hostname
/dev/sda2             4779902052944924004672412% /etc/hosts
/dev/sda3             1909154039587321413994022% /data/nginx/html
tmpfs                   49255204925520% /proc/asound
tmpfs                   49255204925520% /proc/acpi
tmpfs                    655360655360% /proc/kcore
tmpfs                    655360655360% /proc/keys
tmpfs                    655360655360% /proc/timer_list
tmpfs                    655360655360% /proc/sched_debug
tmpfs                   49255204925520% /proc/scsi
tmpfs                   49255204925520% /sys/firmware
/ # cat /data/nginx/html/index.html
Test page on host
/ # echo Test page v2 on host > /data/nginx/html/index.html

# 进入另一个容器看到数据变化

[root@ubuntu1804 ~]#docker exec -it 56a5460f584b  sh
/ # cat /data/nginx/html/index.html
Test page v2 on host

# 访问应用

[root@ubuntu1804 ~]#curl 127.0.0.1:8001
Test page v2 on host
[root@ubuntu1804 ~]#curl 127.0.0.1:8002
Test page v2 on host
3.2.2.4 在宿主机修改数据
[root@ubuntu1804 ~]#echo Test page v3 on host > /data/testdir/index.html
[root@ubuntu1804 ~]#cat /data/testdir/index.html
Test page v3 on host
[root@ubuntu1804 ~]#curl 127.0.0.1:8001
Test page v3 on host
[root@ubuntu1804 ~]#curl 127.0.0.1:8002
Test page v3 on host
[root@ubuntu1804 ~]#docker exec -it e7b5bff6ce56 sh
/ # cat /data/nginx/html/index.html
Test page v3 on host
[root@ubuntu1804 ~]#docker exec -it 56a5460f584b  sh
/ # cat /data/nginx/html/index.html
Test page v3 on host

3.2.2.5 只读方法挂载数据卷

默认数据卷为可读可写,加ro选项,可以实现只读挂载,对于不希望容器修改的数据,比如: 配置文件,脚本等,可以用此方式挂载

[root@ubuntu1804 ~]#docker run  -d -v /data/testdir:/data/nginx/html/:ro   -p
8004:80 nginx-alpine:1.16.1
727d3ecf65c5a79bd9a11033812dc01619c4c45bd25af5155f904016f5f0c45a
[root@ubuntu1804 ~]#docker exec -it 727d3ecf65c5a79bd9 sh
/ # cat /data/nginx/html/index.html
Test page v3 on host
/ # echo Test page v4 on host > /data/nginx/html/index.html
sh: can't create /data/nginx/html/index.html: Read-only file system
/ # cat /data/nginx/html/index.html
3.2.2.6 删除容器

删除容器后,宿主机的数据卷还存在,可继续给新的容器使用

[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED
STATUS              PORTS                           NAMES
e7b5bff6ce56        nginx-alpine:1.16.1   "nginx"9 minutes ago
  Up 9 minutes        443/tcp, 0.0.0.0:8002->80/tcp   hungry_robinson
56a5460f584b        nginx-alpine:1.16.1   "nginx"9 minutes ago
  Up 9 minutes        443/tcp, 0.0.0.0:8001->80/tcp   stupefied_dubinsky
[root@ubuntu1804 ~]#docker rm -f `docker ps -aq`
e7b5bff6ce56
56a5460f584b
[root@ubuntu1804 ~]#cat /data/testdir/index.html
Test page v3 on host
#新建的容器还可以继续使用原有的数据卷
[root@ubuntu1804 ~]#docker run  -d -v /data/testdir:/data/nginx/html/   -p
8003:80 nginx-alpine:1.16.1
ecd016506f6af3f4af61dbd869f8fce5f634ecdc0e3272f9e0402c981acd80a4
[root@ubuntu1804 ~]#curl 127.0.0.1:8003
Test page v3 on host

3.2.3 安战案例: MySQL使用的数据卷

[root@ubuntu1804 ~]#docker pull mysql:5.7.30
5.7.29: Pulling from library/mysql
Status: Downloaded newer image for mysql:5.7.30
docker.io/library/mysql:5.7.30
[root@ubuntu1804 ~]#docker images "mysql*"
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
mysql               5.7.29              b598110d0fff        2 weeks ago
435MB
[root@ubuntu1804 ~]#docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456
mysql:5.7.30
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                               NAMES
c21ca6f8a7fe        mysql:5.7.30        "docker-entrypoint.s…"3 minutes ago
    Up 3 minutes        0.0.0.0:3306->3306/tcp, 33060/tcp   nifty_banach
[root@ubuntu1804 ~]#docker exec -it c21ca6f8a7fe bash
root@c21ca6f8a7fe:/# cat /etc/issue
Debian GNU/Linux 9 \n \l
root@c21ca6f8a7fe:/# cat /etc/mysql/my.cnf
......
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
root@c21ca6f8a7fe:/# cat /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
datadir     = /var/lib/mysql   #数据存放路径
root@c21ca6f8a7fe:/# pstree -p
mysqld(1)-+-{mysqld}(130)
          |-{mysqld}(131)
          |-{mysqld}(132)
          |-{mysqld}(133)
          |-{mysqld}(134)
          |-{mysqld}(135)
          |-{mysqld}(136)
          |-{mysqld}(137)
          |-{mysqld}(138)
          |-{mysqld}(139)
          |-{mysqld}(140)
          |-{mysqld}(141)
          |-{mysqld}(143)
          |-{mysqld}(144)
          |-{mysqld}(145)
          |-{mysqld}(146)
          |-{mysqld}(147)
          |-{mysqld}(148)
          |-{mysqld}(149)
          |-{mysqld}(150)
          |-{mysqld}(151)
          |-{mysqld}(152)
          |-{mysqld}(153)
          |-{mysqld}(154)
          |-{mysqld}(155)
`-{mysqld}(156)
[root@ubuntu1804 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h'for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows inset (0.00 sec)
mysql> create database dockerdb;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| dockerdb           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows inset (0.01 sec)
mysql>
#删除容器后,再创建新的容器,数据库信息丢失
[root@ubuntu1804 ~]#docker rm -f  c21ca6f8a7fe
c21ca6f8a7fe
[root@ubuntu1804 ~]#docker run -d  --name mysql -p 3306:3306 -e
MYSQL_ROOT_PASSWORD=123456  mysql:5.7.30
f52a50c7f80ee39d9a935a762eacb05db72dcfa5f0d02af8b4f23b5538080b67
[root@ubuntu1804 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h'for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows inset (0.00 sec)

# 利用数据卷创建容器

[root@ubuntu1804 ~]#mkdir /data/mysql
[root@ubuntu1804 ~]#docker run -d  --name mysql -p 3306:3306 -v
/data/mysql/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456  mysql:5.7.30
d64ef3f9a64491061132020306fd3e97e1aa361b0fb9f6f644f2a1e3f334119c
[root@ubuntu1804 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql> create database dockerdb;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| dockerdb           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows inset (0.00 sec)
mysql> exit
#删除容器,数据存放在挂载数据卷中,不会删除
[root@ubuntu1804 ~]#docker rm -fv mysql
mysql
[root@ubuntu1804 ~]#ls /data/mysql/
auto.cnf    ca.pem           client-key.pem  ib_buffer_pool  ib_logfile0  ibtmp1
performance_schema  public_key.pem   server-key.pem
ca-key.pem  client-cert.pem  dockerdb        ibdata1         ib_logfile1  mysql
private_key.pem     server-cert.pem  sys
#重新创建新容器,之前数据还在
[root@ubuntu1804 ~]#docker run -d  --name mysql -p 3306:3306 -v
/data/mysql/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456  mysql:5.7.30
8d6cd0822cc61db30c0401992d2dbfa5c33b525f9aead44c165e0e247c37e5df
[root@ubuntu1804 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h'for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| dockerdb           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows inset (0.00 sec)
mysql> exit
#指定多个数据卷,创建MySQL
[root@ubuntu1804 ~]#docker run --name mysql-test1 -v /data/mysql:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wpuser -e
MYSQL_PASSWORD=123456 -d -p 3306:3306 mysql:5.7.30
[root@ubuntu1804 ~]#docker run --name mysql-test2 -v
/root/mysql/:/etc/mysql/conf.d -v /data/mysql2:/var/lib/mysql --env-file=env.list
-d -p 3307:3306 mysql:5.7.30
[root@ubuntu1804 ~]#cat mysql/mysql-test.cnf
[mysqld]
server-id=100
log-bin=mysql-bin
[root@ubuntu1804 ~]#cat env.list
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=wppass

3.2.4 实战案例: 文件数据卷

文件挂载用于很少更改文件内容的场景,比如: nginx 的配置文件、tomcat的配置文件等。

3.2.4.1 准备相关文件
[root@ubuntu1804 ~]#mkdir /data/{bin,testapp,logs}
[root@ubuntu1804 ~]#echo testapp v1  > /data/testapp/index.html
[root@ubuntu1804 ~]#cat /data/testapp/index.html
testapp v1
[root@ubuntu1804 ~]#cp /data/dockerfile/web/tomcat/tomcat-base-8.5.50/apache-
tomcat-8.5.50/bin/catalina.sh  /data/bin/
[root@ubuntu1804 ~]#vim /data/bin/catalina.sh
#加下面tomcat的优化参数行
# -----------------------------------------------------------------------------
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -
XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -
XX:+AggressiveOpts
-XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10-
XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2-XX:Pe
rmSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5-
XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UsePar
NewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -
XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
# OS specific support.  $var _must_ be set to either true or false.
[root@ubuntu1804 ~]#chown 2019:2019 /data/bin/catalina.sh
[root@ubuntu1804 ~]#ll /data/bin/catalina.sh
-rwxr-x---12019201924324 Jan 3121:43 /data/bin/catalina.sh*
[root@ubuntu1804 ~]#chown 2019:2019 /data/logs/
3.2.4.2 引用文件数据卷启动容器

同时挂载可读可写方式的目录数据卷和只读方式的文件数据卷,实现三个数据卷的挂载,数据,日志和启动脚本

[root@ubuntu1804 ~]#docker run -d -v
/data/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v
/data/testapp:/data/tomcat/webapps/testapp   -v /data/logs:/apps/tomcat/logs -p
8080:8080 tomcat-web:app1
55de76261c5e489de9a24d5533fe630d44aa7cce821627f6503a91c041c8f8d3
3.2.4.3 验证容器可以访问
[root@ubuntu1804 ~]#curl 127.0.0.1:8080/testapp/
testapp v1
[root@ubuntu1804 ~]#ls -l /data/logs/
total 36
drwxr-xr-x 2201920194096 Jan 3122:44 ./
drwxr-xr-x 7 root root 4096 Jan 3122:43 ../
-rw-r-----1201920198336 Jan 3122:44 catalina.2020-01-31.log
-rw-r-----1201920198808 Jan 3122:44 catalina.out
-rw-r-----1201920190 Jan 3122:44 host-manager.2020-01-31.log
-rw-r-----1201920190 Jan 3122:44 localhost.2020-01-31.log
-rw-r-----12019201976 Jan 3122:44 localhost_access_log.2020-01-31.txt
-rw-r-----1201920190 Jan 3122:44 manager.2020-01-31.log
3.2.4.4 直接修改宿主机的数据
#宿主机修改目录数据卷
[root@ubuntu1804 ~]#echo testapp v2 > /data/testapp/index.html
[root@ubuntu1804 ~]#curl 127.0.0.1:8080/testapp/
testapp v2
[root@ubuntu1804 ~]#ll /data/bin/catalina.sh
-rwxr-x---12019201924324 Jan 3121:43 /data/bin/catalina.sh*
[root@ubuntu1804 ~]#echo >> /data/bin/catalina.sh
[root@ubuntu1804 ~]#ll /data/bin/catalina.sh
-rwxr-x---12019201924325 Jan 3122:21 /data/bin/catalina.sh*
3.2.4.5 进入容器修改数据
[root@ubuntu1804 ~]#docker exec -it 55de76261c5e bash
[root@55de76261c5e /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        00127.0.0.1:8005          0.0.0.0:*               LISTEN
tcp        000.0.0.0:8009            0.0.0.0:*               LISTEN
tcp        000.0.0.0:8080            0.0.0.0:*               LISTEN
#文件数据卷上的文件为只读
[root@55de76261c5e /]#  echo >> /apps/tomcat/bin/catalina.sh
bash: /apps/tomcat/bin/catalina.sh: Read-only file system
#目录数据卷可读可写
[root@55de76261c5e /]# cat /data/tomcat/webapps/testapp/index.html
testapp v2
[root@55de76261c5e /]# echo testapp v3 > /data/tomcat/webapps/testapp/index.html
[root@55de76261c5e /]# cat /data/tomcat/webapps/testapp/index.html
testapp v3
[root@ubuntu1804 ~]#curl 127.0.0.1:8080/testapp/
testapp v3
3.2.4.6 查看容器中挂载和进程信息
[root@55de76261c5e /]# mount
......
/dev/sda3 on /apps/apache-tomcat-8.5.50/bin/catalina.sh type ext4
(ro,relatime,data=ordered)
/dev/sda3 on /data/tomcat/webapps/testapp type ext4 (rw,relatime,data=ordered)
......
[root@55de76261c5e /]# df
Filesystem     1K-blocks    Used Available Use% Mounted on
overlay         4779902052950324004618412% /
tmpfs              655360655360% /dev
tmpfs             49255204925520% /sys/fs/cgroup
shm                655360655360% /dev/shm
/dev/sda2       4779902052950324004618412% /etc/hosts
/dev/sda3       1909154039749081412376422% /data/tomcat/webapps/testapp
tmpfs             49255204925520% /proc/asound
tmpfs             49255204925520% /proc/acpi
tmpfs             49255204925520% /proc/scsi
tmpfs             49255204925520% /sys/firmware
[root@55de76261c5e /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          10.0  0.3  151363040 ?        Ss   22:09   0:00 /bin/bash
/apps/tomcat/bin/run_tomcat.sh
www          250.5 12.7 6253760125268 ?      Sl   22:09   0:04
/usr/local/jdk/bin/java -Djava.util.logging.config.file=/apps/tomcat
root         260.0  0.4  854284468 ?        S    22:09   0:00 su- www -c
tail -f /etc/hosts
www          280.0  0.0   4416716 ?        Ss   22:09   0:00 tail -f
/etc/hosts
root         850.0  0.4  158003980 pts/0    Ss   22:16   0:00 bash
root        1090.0  0.3  551963696 pts/0    R+22:25   0:00 ps aux
[root@55de76261c5e /]# ps aux|grep java
www          250.5 12.7 6253760125268 ?      Sl   22:09   0:04
/usr/local/jdk/bin/java -
Djava.util.logging.config.file=/apps/tomcat/conf/logging.properties -
Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server-Xms4g
-Xmx4g-Xss512k-Xmn1g-XX:CMSInitiatingOccupancyFraction=65-
XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -
XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10-XX:NewSize=2048M -
XX:MaxNewSize=2048M -XX:NewRatio=2-XX:PermSize=128m -XX:MaxPermSize=512m -
XX:CMSFullGCsBeforeCompaction=5-XX:+ExplicitGCInvokesConcurrent -
XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -
XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -
XX:+UseFastAccessorMethods -Djdk.tls.ephemeralDHKeySize=2048-
Djava.protocol.handler.pkgs=org.apache.catalina.webresources -
Dorg.apache.catalina.security.SecurityListener.UMASK=0027-
Dignore.endorsed.dirs=-classpath
/apps/tomcat/bin/bootstrap.jar:/apps/tomcat/bin/tomcat-juli.jar -
Dcatalina.base=/apps/tomcat -Dcatalina.home=/apps/tomcat -
Djava.io.tmpdir=/apps/tomcat/temp org.apache.catalina.startup.Bootstrap start
root        1110.0  0.2  125362320 pts/0    S+22:25   0:00 grep--
color=auto java

3.2.5 实战案例: 匿名数据卷

[root@ubuntu1804 ~]#docker volume  ls
DRIVER              VOLUME NAME
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
#利用匿名数据卷创建容器
[root@ubuntu1804 ~]#docker run -d -p 80:80 --name nginx01 -v
/usr/share/nginx/html  nginx
914c622af7ebae68aab0b0075da39534fdb118cd5d4d7adf3054da94eb2a4952
[root@ubuntu1804 ~]#curl  127.0.0.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#查看自动生成的匿名数据卷
[root@ubuntu1804 ~]#docker volume  ls
DRIVER              VOLUME NAME
local
2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe
#查看匿名数据卷的详细信息
[root@ubuntu1804 ~]#docker volume inspect
2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe
[
    {
"CreatedAt": "2020-07-21T19:17:07+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint":
"/var/lib/docker/volumes/2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d755
02f8b40fe/_data",
"Name":
"2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe",
"Options": null,
"Scope": "local"
    }
]
[root@ubuntu1804 ~]#docker inspect --format="{{.Mounts}}"  nginx01
[{volume 2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe
/var/lib/docker/volumes/2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d7550
2f8b40fe/_data /usr/share/nginx/html local  true }]
#查看匿名数据卷的文件
[root@ubuntu1804 ~]#ls
/var/lib/docker/volumes/2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d7550
2f8b40fe/_data
50x.html  index.html
#修改宿主机中匿名数据卷的文件
[root@ubuntu1804 ~]#echo Anonymous Volume >
/var/lib/docker/volumes/2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d7550
2f8b40fe/_data/index.html
[root@ubuntu1804 ~]#curl 127.0.0.1
Anonymous Volume
#删除容器不会删除匿名数据卷
[root@ubuntu1804 ~]#docker rm -f  nginx01
nginx01
[root@ubuntu1804 ~]#docker volume  ls
DRIVER              VOLUME NAME
local
2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe
[root@ubuntu1804 ~]#docker run -d -p 80:80 --name nginx01 -v
/usr/share/nginx/html  nginx
40a99ae066cc60aa0ad7d073e46101a15446509acbd7971e677f3cbe6733aa79
[root@ubuntu1804 ~]#cat
/var/lib/docker/volumes/2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d7550
2f8b40fe/_data/index.html
Anonymous Volume
#删除匿名数据卷
[root@ubuntu1804 ~]#docker volume rm
2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe
2a18aff09215e7830c6df56a80e0f8ace9b44f3384d512daf06d75502f8b40fe
[root@ubuntu1804 ~]#docker volume  ls
DRIVER              VOLUME NAME

3.2.6 实战案例: 命名数据卷

3.2.6.1 创建命名数据卷
[root@ubuntu1804 ~]#docker volume  create vol1
vol1
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME
local               vol1
[root@ubuntu1804 ~]#docker inspect vol1
[
    {
"CreatedAt": "2020-07-21T18:36:45+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/vol1/_data",
"Name": "vol1",
"Options": {},
"Scope": "local"
    }
]
3.2.6.2 使用命名数据卷创建容器
[root@ubuntu1804 ~]#docker run -d  -p 8001:80 --name nginx01 -v
vol1:/usr/share/nginx/html  nginx
2a2ad99de2984521cbce777eae8e482c3e6e55e35ab5f398a35c7986fa39cc99
[root@ubuntu1804 ~]#curl 127.0.0.1:8001
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
#显示命名数据卷
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME
local               vol1
#查看命名数据卷详解信息
[root@ubuntu1804 ~]#docker volume inspect vol1
[
    {
"CreatedAt": "2020-07-21T18:44:03+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/vol1/_data",
"Name": "vol1",
"Options": {},
"Scope": "local"
    }
]
[root@ubuntu1804 ~]#docker inspect --format="{{.Mounts}}"  nginx01
[{volume vol1 /var/lib/docker/volumes/vol1/_data /usr/share/nginx/html local z
true }]
#查看命名数据卷的文件
[root@ubuntu1804 ~]#ls /var/lib/docker/volumes/vol1/_data
50x.html  index.html
#修改宿主机命名数据卷的文件
[root@ubuntu1804 ~]#echo nginx vol1 website >
/var/lib/docker/volumes/vol1/_data/index.html
[root@ubuntu1804 ~]#curl 127.0.0.1:8001
nginx vol1 website
#利用现在的命名数据卷再创建新容器,可以和原有容器共享同一个命名数据卷的数据
[root@ubuntu1804 ~]#docker run -d  -p 8002:80 --name nginx02 -v
vol1:/usr/share/nginx/html  nginx
fb8739438992b7797a3f23dc495d2fd43f513fd793114848171f376c4325675e
[root@ubuntu1804 ~]#curl 127.0.0.1:8002
nginx vol1 website
3.2.6.3 创建容器时自动创建命名数据卷
#创建容器自动创建命名数据卷
[root@ubuntu1804 ~]#docker run -d  -p 8003:80 --name nginx03 -v
vol2:/usr/share/nginx/html  nginx
5d7497c04907babcb2084f8f7a16874223e07965410fd4da14bc2fe993277aed
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME
local               portainer_data
local               vol1
local               vol2
3.2.6.4 删除数据卷
#删除指定的命名数据卷
[root@ubuntu1804 ~]#docker volume rm vol1
#清理全部不再使用的卷
[root@ubuntu1804 ~]#docker volume  prune -f

3.2.7 实战案例:实现 wordpress 持久化

[root@ubuntu2004 ~]#docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e
MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name
mysql -d  -v /data/mysql:/var/lib/mysql --restart=always mysql:8.0.29-oracle
[root@ubuntu2004 ~]#docker run -d -p 80:80 --name wordpress -v
/data/wordpess:/var/www/html --restart=always  wordpress:php7.4-apache

注意:数据库主机填写宿主机的IP,而非127.0.0.1

3.3 数据卷容器

3.3.1 数据卷容器介绍

在Dockerfile中创建的是匿名数据卷,无法直接实现多个容器之间共享数据

数据卷容器最大的功能是可以让数据在多个docker容器之间共享

如下图所示: 即可以让B容器访问A容器的内容,而容器C也可以访问A容器的内容,即可以实现A,B,C 三个容器之间的数据读写共享。

相当于先要创建一个后台运行的容器作为 Server,用于提供数据卷,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为client端 ,但此方法并不常使用

缺点: 因为依赖一个 Server 的容器,所以此 Server 容器出了问题,其它 Client容器都会受影响

3.3.2 使用数据卷容器

启动容器时,指定使用数据卷容器

docker run 命令的以下选项可以实现数据卷容器,格式如下:

--volumes-from <数据卷容器>     Mount volumes from the specified container(s)

3.3.3 实战案例: 数据卷容器

3.3.3.1 创建一个数据卷容器 Server

先创建一个挂载宿主机的数据目录的容器,且可以无需启动

范例: 使用之前的镜像创建数据卷容器

#数据卷容器一般无需映射端口
[root@ubuntu1804 ~]#docker run -d --name volume-server -v
/data/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v
/data/testapp:/data/tomcat/webapps/testapp   tomcat-web:app1
109a34c5a83b23bc57b16fc8b1e19104d3d522a8c62e1e98d8e69577b01739b5
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                NAMES
109a34c5a83b        tomcat-web:app1     "/apps/tomcat/bin/ru…"14 seconds ago
     Up 13 seconds       8009/tcp, 8080/tcp   volume-server
3.3.3.2 启动多个数据卷容器 Client
[root@ubuntu1804 ~]#docker run -d --name client1 --volumes-from volume-server -p
8081:8080  tomcat-web:app1
fe6ce0548dfee924cd39a8d86d5ed0e8ce9ea65323742f1336fa3b002c1b4a8c
[root@ubuntu1804 ~]#docker run -d --name client2 --volumes-from volume-server -p
8082:8080  tomcat-web:app1
10397838df9a489d7af2112850d4285bff5c2c262ea05cc9c5fb265af538f2c8
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                              NAMES
10397838df9a        tomcat-web:app1     "/apps/tomcat/bin/ru…"30 seconds ago
     Up 27 seconds       8009/tcp, 0.0.0.0:8082->8080/tcp   client2
fe6ce0548dfe        tomcat-web:app1     "/apps/tomcat/bin/ru…"40 seconds ago
     Up 38 seconds       8009/tcp, 0.0.0.0:8081->8080/tcp   client1
109a34c5a83b        tomcat-web:app1     "/apps/tomcat/bin/ru…"2 minutes ago
    Up 2 minutes        8009/tcp, 8080/tcp                 volume-server
[root@ubuntu1804 ~]#
3.3.3.3 验证访问
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v3
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v3
3.3.3.4 进入容器测试读写

读写权限依赖于源数据卷Server容器

#进入 Server 容器修改数据
[root@ubuntu1804 ~]#docker exec -it volume-server bash
[root@109a34c5a83b /]# cat /data/tomcat/webapps/testapp/index.html
testapp v3
[root@109a34c5a83b /]# echo testapp v4 > /data/tomcat/webapps/testapp/index.html
[root@109a34c5a83b /]#
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v4
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v4
#进入 Client 容器修改数据
[root@ubuntu1804 ~]#docker exec -it client1 bash
[root@fe6ce0548dfe /]# cat /data/tomcat/webapps/testapp/index.html
testapp v4
[root@fe6ce0548dfe /]# echo testapp v4 > /data/tomcat/webapps/testapp/index.html
[root@fe6ce0548dfe /]# cat /data/tomcat/webapps/testapp/index.html
testapp v5
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v5
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v5

3.3.3.5 在宿主机直接修改

[root@ubuntu1804 ~]#cat /data/testapp/index.html
testapp v5
[root@ubuntu1804 ~]#echo testapp v6 > /data/testapp/index.html
[root@ubuntu1804 ~]#cat /data/testapp/index.html
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v6
[root@ubuntu1804 ~]#
[root@ubuntu1804 ~]#docker exec -it volume-server bash
[root@109a34c5a83b /]# cat  /data/tomcat/webapps/testapp/index.html
testapp v6
[root@109a34c5a83b /]#
3.3.3.6 关闭卷容器Server测试能否启动新容器

关闭卷容器Server,仍然可以创建新的client容器及访问旧的client容器

[root@ubuntu1804 ~]#docker stop volume-server
volume-server
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                              NAMES
10397838df9a        tomcat-web:app1     "/apps/tomcat/bin/ru…"9 minutes ago
    Up 9 minutes        8009/tcp, 0.0.0.0:8082->8080/tcp   client2
fe6ce0548dfe        tomcat-web:app1     "/apps/tomcat/bin/ru…"10 minutes ago
     Up 10 minutes       8009/tcp, 0.0.0.0:8081->8080/tcp   client1
[root@ubuntu1804 ~]#docker run -d --name client3 --volumes-from volume-server -p
8083:8080  tomcat-web:app1
458df991688c3dbc69d824f889616e0a7534ce18543c8559162f3609fbb26b53
[root@ubuntu1804 ~]#docker ps  -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
     STATUS                            PORTS                              NAMES
458df991688c        tomcat-web:app1     "/apps/tomcat/bin/ru…"   About a minute
ago   Up About a minute                 8009/tcp, 0.0.0.0:8083->8080/tcp
client3
10397838df9a        tomcat-web:app1     "/apps/tomcat/bin/ru…"11 minutes ago
      Up 11 minutes                     8009/tcp, 0.0.0.0:8082->8080/tcp
client2
fe6ce0548dfe        tomcat-web:app1     "/apps/tomcat/bin/ru…"11 minutes ago
      Up 11 minutes                     8009/tcp, 0.0.0.0:8081->8080/tcp
client1
109a34c5a83b        tomcat-web:app1     "/apps/tomcat/bin/ru…"13 minutes ago
      Exited (137) About a minute ago
volume-server
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8083/testapp/
testapp v6
3.3.3.7 删除源卷容器Server,访问client和创建新的client容器

删除数据卷容器后,旧的client 容器仍能访问,但无法再创建新的client容器

删除数据卷容器后,旧的client 容器仍能访问,但无法再创建基于数据卷容器的新的client容器,但可以创建基于已创建的Client容器的Client容器

[root@ubuntu1804 ~]#docker rm -fv volume-server
volume-server
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED
    STATUS              PORTS                              NAMES
458df991688c        tomcat-web:app1     "/apps/tomcat/bin/ru…"4 minutes ago
    Up 4 minutes        8009/tcp, 0.0.0.0:8083->8080/tcp   client3
10397838df9a        tomcat-web:app1     "/apps/tomcat/bin/ru…"14 minutes ago
     Up 14 minutes       8009/tcp, 0.0.0.0:8082->8080/tcp   client2
fe6ce0548dfe        tomcat-web:app1     "/apps/tomcat/bin/ru…"14 minutes ago
     Up 14 minutes       8009/tcp, 0.0.0.0:8081->8080/tcp   client1
[root@ubuntu1804 ~]#docker run -d --name client4 --volumes-from volume-server -p
8084:8080  tomcat-web:app1
Unable to find image 'tomcat-web:app1' locally
docker: Error response from daemon: pull access denied for tomcat-web,
repository does not exist or may require 'docker login': denied: requested
access to the resource is denied.
See 'docker run --help'.
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8083/testapp/
testapp v6
3.3.3.8 重新创建容器卷 Server

重新创建容器卷容器后,还可继续创建新client 容器

[root@ubuntu1804 ~]#docker run -d --name volume-server -v
/data/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v
/data/testapp:/data/tomcat/webapps/testapp   tomcat-web:app1
ee0dacff6a4531dc8ecc1d416b449e087d8bf27dad2d6a6e515faf10455a1cc0
[root@ubuntu1804 ~]#docker run -d --name client4 --volumes-from volume-server -p
8084:8080  tomcat-web:app1
dcd002fe87887a0c5d1f62b24cd7665e42ee864c975d1a2953c383af0cb65a70
[root@ubuntu1804 ~]#curl 127.0.0.1:8084/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8081/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8082/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8083/testapp/
testapp v6
[root@ubuntu1804 ~]#curl 127.0.0.1:8084/testapp/
testapp v6

3.3.4 利用数据卷容器备份指定容器的数据卷实现

由于匿名数据卷在宿主机中的存储位置不确定,所以为了方便的备份匿名数据卷,可以利用数据卷容器实现数据卷的备份

#先创建匿名卷中数据需要备份的容器
docker run --name [container name] -v [container data volume]  <image>
#创建另一个用于备份的容器,执行备份命令
docker run -it--rm--volumes-from [container name] -v$(pwd):/backup ubuntu
root@ca5bb2c1f877:/#tar cvf /backup/backup.tar [container data volume]
#说明
[container name]            #表示需要备份的容器
[container data volume]     #表示容器内的需要备份的数据卷对应的目录
#还原方式
docker run -it--rm--volumes-from [container name] -V$(pwd):/backup ubuntu
root@ca5bb2c1f877:/#tar xvf /backup/backup.tar -C [container data volume]

范例:

#创建需要备份的匿名数据卷容器
[root@ubuntu1804 ~]#docker run -it -v /datavolume1  --name volume-server centos
bash
[root@88bbc22a3072 /]# ls
bin      dev  home  lib64       media  opt   root  sbin  sys  usr
datavolume1  etc  lib   lost+found  mnt    proc  run   srv   tmp  var
[root@88bbc22a3072 /]# touch /datavolume1/centos.txt
[root@88bbc22a3072 /]# exit
exit
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
#可以看到数据卷对应的宿主机目录
[root@ubuntu1804 ~]#docker inspect --format="{{.Mounts}}" volume-server
[{volume 21199be9bff7ce98926f673d2250d64d75aaa00c5d375a2528b2b47f0ec4cb93
/var/lib/docker/volumes/21199be9bff7ce98926f673d2250d64d75aaa00c5d375a2528b2b47f
0ec4cb93/_data /datavolume1 local  true }]
#基于前面的匿名数据卷容器创建执行备份操作的容器
[root@ubuntu1804 ~]#docker run -it --rm --volumes-from volume-server -v
~/backup:/backup --name backup-server ubuntu
root@9ad8be4b5810:/# ls
backup  boot         dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
bin     datavolume1  etc  lib   lib64  media   opt  root  sbin  sys  usr
root@9ad8be4b5810:/# ls /backup/
root@9ad8be4b5810:/# ls  /datavolume1/
centos.txt
root@9ad8be4b5810:/# cd /datavolume1/
root@9ad8be4b5810:/datavolume1# tar cvf /backup/data.tar .
./
./centos.txt
root@9ad8be4b5810:/datavolume1# exit
exit
[root@ubuntu1804 ~]#ls ~/backup/
data.tar
#删除容器的数据
[root@ubuntu1804 ~]#docker start -i volume-server
[root@88bbc22a3072 /]# rm -rf /datavolume1/*
[root@88bbc22a3072 /]# ls /datavolume1/
[root@88bbc22a3072 /]# exit
exit
#进行还原
[root@ubuntu1804 ~]#docker run --rm --volumes-from volume-server -v
~/backup:/backup --name backup-server ubuntu tar xvf /backup/data.tar -C
/datavolume1/
./
./centos.txt
#验证是否还原
[root@ubuntu1804 ~]#docker start -i volume-server
[root@88bbc22a3072 /]# ls /datavolume1/
centos.txt

范例: 利用数据卷容器备份MySQL数据库

#MySQL容器默认使用了匿名卷
[root@ubuntu1804 ~]#docker run -d  --name mysql -p 3306:3306 -e
MYSQL_ROOT_PASSWORD=123456  mysql:5.7.30
[root@ubuntu1804 ~]#docker volume ls
DRIVER              VOLUME NAME
local
897bd48c5c5e2067627d5c6d10dad17d4793132a638986c16f36820663728ee1
#备份数据库
[root@ubuntu1804 ~]#docker run -it --rm --volumes-from mysql  -v $(pwd):/backup
centos tar xvf  /backup/mysql.tar -C  /var/lib/mysql
#删除数据库文件
[root@ubuntu1804 ~]#rm -rf
/var/lib/docker/volumes/897bd48c5c5e2067627d5c6d10dad17d4793132a638986c16f368206
63728ee1/_data/
#还原数据库
[root@ubuntu1804 ~]#docker run -it --rm --volumes-from mysql  -v $(pwd):/backup
centos tar xvf  /backup/mysql.tar -C  /

3.3.5 数据卷容器总结

将提供卷的容器Server 删除,已经运行的容器Client依然可以使用挂载的卷,因为容器是通过挂载访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器Server创建后即可正常创建卷容器Client, 此方式可以用于线上共享数据目录等环境,因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用

由此可知, 数据卷容器的功能只是将数据挂载信息传递给了其它使用数据卷容器的容器,而数据卷容器本身并不提供数据存储功能

数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于NFS共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性

数据卷容器的 Server 和 Client 可以不使用同一个镜像生成

当创建Client容器时,会复制Server容器的数据卷信息,后续Server容器状态和存在与否,都不会影响Client 容器使用的数据卷

当Server容器删除后,不能再基于Server容器创建新的Client容器,但可以基于已存在的Client容器来创建新的Client容器

最终实现了多个客户端容器共享相同的持久化宿主机的存储方案

4 Docker 网络管理

docker容器创建后,必不可少的要和其它主机或容器进行网络通信

官方文档:

https://docs.docker.com/network/

4.1 Docker的默认的网络通信

4.1.1 Docker安装后默认的网络设置

Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡其IP地址都是 172.17.0.1/16

范例: 安装Docker的默认的网络配置

[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:34:df:91 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:df91/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:02:7f:a8:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:2ff:fe7f:a8c6/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#brctl show
bridge name bridge id       STP enabled interfaces
docker0     8000.0242027fa8c6   no

范例: 安装Harbor的默认网络配置

[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:01:f3:0c brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.102/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe01:f30c/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:f4:23:e8:29 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: br-9af624ecd23e: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP group default
    link/ether 02:42:e9:1c:1a:7b brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-9af624ecd23e
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e9ff:fe1c:1a7b/64 scope link
       valid_lft forever preferred_lft forever
6: veth225895c@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether a6:f3:0f:ae:4b:43 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::a4f3:fff:feae:4b43/64 scope link
       valid_lft forever preferred_lft forever
8: veth244c237@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether 72:12:35:11:e8:14 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::7012:35ff:fe11:e814/64 scope link
       valid_lft forever preferred_lft forever
10: veth81ab8cb@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether 5e:07:f2:eb:43:c2 brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::5c07:f2ff:feeb:43c2/64 scope link
       valid_lft forever preferred_lft forever
12: vethf8499d4@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether 4e:df:12:c5:58:83 brd ff:ff:ff:ff:ff:ff link-netnsid 4
    inet6 fe80::4cdf:12ff:fec5:5883/64 scope link
       valid_lft forever preferred_lft forever
14: vethceabf74@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether 06:c0:58:ea:51:2e brd ff:ff:ff:ff:ff:ff link-netnsid 5
    inet6 fe80::4c0:58ff:feea:512e/64 scope link
       valid_lft forever preferred_lft forever
16: veth47c5069@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether c6:6f:aa:51:be:38 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::c46f:aaff:fe51:be38/64 scope link
       valid_lft forever preferred_lft forever
18: veth83fde4a@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether 32:74:1e:e2:81:50 brd ff:ff:ff:ff:ff:ff link-netnsid 6
    inet6 fe80::3074:1eff:fee2:8150/64 scope link
       valid_lft forever preferred_lft forever
20: veth2c51f87@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether ca:b7:c9:da:87:92 brd ff:ff:ff:ff:ff:ff link-netnsid 7
    inet6 fe80::c8b7:c9ff:feda:8792/64 scope link
       valid_lft forever preferred_lft forever
22: veth0f4a931@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether fa:29:a4:4d:b1:c2 brd ff:ff:ff:ff:ff:ff link-netnsid 8
    inet6 fe80::f829:a4ff:fe4d:b1c2/64 scope link
       valid_lft forever preferred_lft forever
24: veth55b6555@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master br-9af624ecd23e state UP group default
    link/ether aa:87:c4:2c:de:7c brd ff:ff:ff:ff:ff:ff link-netnsid 9
    inet6 fe80::a887:c4ff:fe2c:de7c/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#apt -y install bridge-utils
[root@ubuntu1804 ~]#brctl show
bridge name bridge id       STP enabled interfaces
br-9af624ecd23e     8000.0242e91c1a7b   no      veth0f4a931
                                                veth225895c
                                                veth244c237
                                                veth2c51f87
                                                veth47c5069
                                                veth55b6555
                                                veth81ab8cb
                                                veth83fde4a
                                                vethceabf74
                                                vethf8499d4
docker0     8000.0242f423e829   no

4.1.2 创建容器后的网络配置

每次新建容器后

  • 宿主机多了一个虚拟网卡,和容器的网卡组合成一个网卡,比如: 137: veth8ca6d43@if136,而在容器内的网卡名为136,可以看出和宿主机的网卡之间的关联

  • 容器会自动获取一个172.17.0.0/16网段的随机地址,默认从172.17.0.2开始分配给第1个容器使用,第2个容器为172.17.0.3,以此类推

  • 容器获取的地址并不固定,每次容器重启,可能会发生地址变化

4.1.2.1 创建第一个容器后的网络状态

范例: 创建容器,容器自动获取IP地址

[root@ubuntu1804 ~]#docker run -it --rm  alpine:3.11 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
136: eth0@if137: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  6b8d9f3a653e
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
6b8d9f3a653e        alpine:3.11         "sh"13 seconds ago
Up 12 seconds                           pensive_chandrasekhar

范例: 新建第一个容器,宿主机的网卡多了一个新网卡

[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:34:df:91 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:df91/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
group default
    link/ether 02:42:02:7f:a8:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:2ff:fe7f:a8c6/64 scope link
       valid_lft forever preferred_lft forever
137: veth8ca6d43@if136: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master docker0 state UP group default
    link/ether fa:96:37:77:a9:a9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f896:37ff:fe77:a9a9/64 scope link
       valid_lft forever preferred_lft forever

范例: 查看新建容器后桥接状态

[root@ubuntu1804 ~]#brctl show
bridge name bridge id       STP enabled interfaces
docker0     8000.0242027fa8c6   no      veth8ca6d43
4.1.2.2 创建第二个容器后面的网络状态

范例: 再次创建第二个容器

[root@ubuntu1804 ~]#docker run -it --rm  alpine:3.11 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
140: eth0@if141: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
 / # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3  ab3ea580804a
/ # ping ab3ea580804a
PING ab3ea580804a (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0ttl=64time=0.037 ms
64 bytes from 172.17.0.3: seq=1ttl=64time=0.132 ms
^C
--- ab3ea580804a ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.037/0.084/0.132 ms
/ # ping 6b8d9f3a653e
ping: bad address '6b8d9f3a653e'
/ #
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
ab3ea580804a        alpine:3.11         "sh"9 seconds ago
Up 7 seconds                            vigilant_jones
6b8d9f3a653e        alpine:3.11         "sh"13 seconds ago
Up 12 seconds                           pensive_chandrasekhar

范例: 新建第二个容器后宿主机又多了一个虚拟网卡

[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:34:df:91 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:df91/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
group default
    link/ether 02:42:02:7f:a8:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:2ff:fe7f:a8c6/64 scope link
       valid_lft forever preferred_lft forever
137: veth8ca6d43@if136: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master docker0 state UP group default
    link/ether fa:96:37:77:a9:a9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f896:37ff:fe77:a9a9/64 scope link
       valid_lft forever preferred_lft forever
141: vethf599a47@if140: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master docker0 state UP group default
    link/ether 96:e7:52:fe:67:54 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::94e7:52ff:fefe:6754/64 scope link
       valid_lft forever preferred_lft forever

范例: 查看新建第二个容器后桥接状态

[root@ubuntu1804 ~]#brctl  show
bridge name bridge id       STP enabled interfaces
docker0     8000.0242027fa8c6   no      veth8ca6d43
                                        vethf599a47

4.1.3 容器间的通信

4.1.3.1 同一个宿主机的不同容器可相互通信

默认情况下

同一个宿主机的不同容器之间可以相互通信

dockerd   --icc    Enable inter-container communication (default true)
--icc=false#此配置可以禁止同一个宿主机的容器之间通信

不同宿主机之间的容器IP地址重复,默认不能相互通信

范例: 同一个宿主机的容器之间访问

[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:34:df:91 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:df91/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
group default
    link/ether 02:42:02:7f:a8:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:2ff:fe7f:a8c6/64 scope link
       valid_lft forever preferred_lft forever
137: veth8ca6d43@if136: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master docker0 state UP group default
    link/ether fa:96:37:77:a9:a9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::f896:37ff:fe77:a9a9/64 scope link
       valid_lft forever preferred_lft forever
141: vethf599a47@if140: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
master docker0 state UP group default
    link/ether 96:e7:52:fe:67:54 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::94e7:52ff:fefe:6754/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#docker run -it --rm  alpine:3.11 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
136: eth0@if137: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0ttl=64time=0.452 ms
64 bytes from 172.17.0.3: seq=1ttl=64time=0.190 ms
^C
---172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.190/0.321/0.452 ms
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0ttl=64time=0.139 ms
64 bytes from 172.17.0.1: seq=1ttl=64time=0.183 ms
^C
---172.17.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.139/0.161/0.183 ms
/ #
4.1.3.2 禁止同一个宿主机的不同容器间通信

范例: 同一个宿主机不同容器间禁止通信

#dockerd 的 --icc=false 选项可以禁止同一个宿主机的不同容器间通信
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--icc=false
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
#创建两个容器,测试无法通信
[root@ubuntu1804 ~]#docker run -it --name test1 --rm alpine  sh
/ # hostname -i
172.17.0.2
[root@ubuntu1804 ~]#docker run -it --name test2 --rm alpine  sh
/ # hostname -i
172.17.0.3
/ # ping 172.17.0.2

范例: 在第二个宿主机上创建容器,跨宿主机的容器之间默认不能通信

[root@ubuntu1804 ~]#docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
c9b1b535fdd9: Pull complete
Digest: sha256:ab00606a42621fb68f2ed6ad3c88be54397f981a7b70a79db3d1172b11c4367d
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
cab76bbb3db2        alpine              "sh"                About a minute ago
Up About a minute                       jolly_rosalind
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:6b:54:d3 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.101/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe6b:54d3/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:1d:73:8b:71 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
[root@ubuntu1804 ~]#docker run -it --rm  alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping -c 1 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
---172.17.0.3 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

4.1.4 修改默认docker0网桥的网络配置

默认docker后会自动生成一个docker0的网桥,使用的IP是172.17.0.1/16,可能和宿主机的网段发生冲突, 可以将其修改为其它网段的地址,避免冲突

范例: 将docker0的IP修改为指定IP

#方法1
[root@ubuntu1804 ~]#vim /etc/docker/daemon.json
[root@ubuntu1804 ~]#cat /etc/docker/daemon.json
{
"bip": "192.168.100.1/24",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
[root@ubuntu1804 ~]#systemctl restart docker.service
#方法2
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--bip=192.168.100.1/24
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker.service
#注意两种方法不可混用,否则将无法启动docker服务
#验证结果
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:48:f0:a2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe48:f0a2/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:c5:a7:cf:5c brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c5ff:fea7:cf5c/64 scope link
       valid_lft forever preferred_lft forever

4.1.5 修改默认网络设置使用自定义网桥

新建容器默认使用docker0的网络配置,可以修改默认指向自定义的网桥网络

范例: 用自定义的网桥代替默认的docker0

#查看默认网络
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:40:27:06 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe40:2706/64 scope link
       valid_lft forever preferred_lft forever
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:35:ba:e7:ce brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:35ff:feba:e7ce/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#apt -y install bridge-utils
[root@ubuntu1804 ~]#brctl addbr br0
[root@ubuntu1804 ~]#ip a a 192.168.100.1/24 dev br0
[root@ubuntu1804 ~]#brctl  show
bridge name bridge id       STP enabled interfaces
br0     8000.000000000000   no
docker0     8000.024235bae7ce   no
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:40:27:06 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe40:2706/64 scope link
       valid_lft forever preferred_lft forever
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:35:ba:e7:ce brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:35ff:feba:e7ce/64 scope link
       valid_lft forever preferred_lft forever
18: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
group default qlen 1000
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::9cf2:e0ff:fe4e:96b3/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
-b br0
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#ps -ef |grep dockerd
root      157731011:12 ?        00:00:00 /usr/bin/dockerd -H fd:// --
containerd=/run/containerd/containerd.sock -b br0
root      159602300011:14 pts/0    00:00:00 grep--color=auto dockerd
[root@ubuntu1804 ~]#docker run  --rm alpine hostname -i
192.168.100.2

4.2 容器名称互联

新建容器时,docker会自动分配容器名称,容器ID和IP地址,导致容器名称,容器ID和IP都不固定,那么如何区分不同的容器,实现和确定目标容器的通信呢?解决方案是给容器起个固定的名称,容器之间通过固定名称实现确定目标的通信

有两种固定名称:

容器名称容器名称的别名

注意: 两种方式都最少需要两个容器才能实现

4.2.1 通过容器名称互联

4.2.1.1 容器名称介绍

即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如: 一个业务前端静态页面是使用nginx,动态页面使用的是tomcat,另外还需要负载均衡调度器,如: haproxy 对请求调度至nginx 和tomcat的容器,由于容器在启动的时候其内部IP地址是DHCP 随机分配的,而给容器起个固定的名称,则是相对比较固定的,因此比较适用于此场景

注意: 如果被引用的容器地址变化,必须重启当前容器才能生效

4.2.1.2 容器名称实现

docker run 创建容器,可使用--link选项实现容器名称的引用,其本质就是在容器内的/etc/hosts中添加-link后指定的容器的IP和主机名的对应关系,从而实现名称解析

--link list                                    #Add link to another container
格式:
docker run --name <容器名称>                    #先创建指定名称的容器
docker run --link <目标通信的容器ID或容器名称>     #再创建容器时引用上面容器的名称
4.2.1.3 实战案例1: 使用容器名称进行容器间通信
  1. 先创建第一个指定容器名称的容器
[root@ubuntu1804 ~]#docker run -it --name server1 --rm  alpine:3.11 sh
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  cdb5173003f5
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
150: eth0@if151: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.038 ms
^C
---172.17.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.038/0.038/0.038 ms
/ # ping server1
ping: bad address 'server1'
/ # ping cdb5173003f5
PING cdb5173003f5 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.040 ms
64 bytes from 172.17.0.2: seq=1ttl=64time=0.128 ms
^C
--- cdb5173003f5 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.040/0.084/0.128 ms
/ #
  1. 新建第二个容器时引用第一个容器的名称

会自动将第一个主机的名称加入/etc/hosts文件,从而可以利用第一个容器名称进行访问

[root@ubuntu1804 ~]#docker run -it  --rm --name server2  --link server1
alpine:3.11 sh
/ # env
HOSTNAME=395d8c3392ee
SHLVL=1
HOME=/root
TERM=xterm
SERVER1_NAME=/server2/server1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  server1 cdb5173003f5
172.17.0.3  7ca466320980
/ # ping server1
PING server1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.111 ms
^C
--- server1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.111/0.111/0.111 ms
/ # ping server2
ping: bad address 'server2'
/ # ping 7ca466320980
PING 7ca466320980 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0ttl=64time=0.116 ms
64 bytes from 172.17.0.3: seq=1ttl=64time=0.069 ms
^C
--- 7ca466320980 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.069/0.092/0.116 ms
/ # ping cdb5173003f5
PING cdb5173003f5 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.072 ms
64 bytes from 172.17.0.2: seq=1ttl=64time=0.184 ms
^C
--- cdb5173003f5 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.072/0.128/0.184 ms
/ #
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
    STATUS              PORTS               NAMES
7ca466320980        alpine:3.11         "sh"24 seconds ago
   Up 23 seconds                           server2
cdb5173003f5        alpine:3.11         "sh"7 minutes ago
    Up 7 minutes                            server1
4.2.1.4 实战案例2: 实现 wordpress 和 MySQL 两个容器互连
[root@centos7 ~]#tree lamp_docker/
lamp_docker/
├── env_mysql.list
├── env_wordpress.list
└── mysql
    └── mysql_test.cnf
1 directory, 3 files
[root@centos7 ~]#cat lamp_docker/env_mysql.list
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=wppass
[root@centos7 ~]#cat lamp_docker/env_wordpress.list
WORDPRESS_DB_HOST=mysql:3306
WORDPRESS_DB_NAME=wordpress
WORDPRESS_DB_USER=wpuser
WORDPRESS_DB_PASSWORD=wppass
WORDPRESS_TABLE_PREFIX=wp_
[root@centos7 ~]#cat lamp_docker/mysql/mysql_test.cnf
[mysqld]
server-id=100
log-bin=mysql-bin
[root@centos7 ~]#docker run --name mysql -v
/root/lamp_docker/mysql/:/etc/mysql/conf.d -v /data/mysql:/var/lib/mysql --env-
file=/root/lamp_docker/env_mysql.list -d -p 3306:3306 mysql:5.7.30
[root@centos7 ~]#docker run -d   --name wordpress  --link mysql -v
/data/wordpress:/var/www/html/wp-content --env-
file=/root/lamp_docker/env_wordpress.list  -p 80:80 wordpress

4.2.2 通过自定义容器别名互联

4.2.2.1 容器别名介绍

自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,容器内程序之间也必须要随之发生变化,比如:程序通过固定的容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可以随意更改,只要不更改别名即可

4.2.2.2 容器别名实现

命令格式:

docker run --name <容器名称>
#先创建指定名称的容器
docker run --name <容器名称> --link <目标容器名称>:"<容器别名1>  <容器别名2> ..."
#给上面创建的容器起别名,来创建新容器
4.2.2.3 实战案例: 使用容器别名

范例: 创建第三个容器,引用前面创建的容器,并起别名

[root@ubuntu1804 ~]#docker run -it  --rm --name server3  --link server1:server1-
alias  alpine:3.11 sh
/ # env
HOSTNAME=395d8c3392ee
SHLVL=1
HOME=/root
TERM=xterm
SERVER1-ALIAS_NAME=/server3/server1-alias
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  server1-alias cdb5173003f5 server1
172.17.0.4  d9622c6831f7
/ # ping server1
PING server1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.101 ms
^C
--- server1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.101/0.101/0.101 ms
/ # ping server1-alias
PING server1-alias (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.073 ms
^C
--- server1-alias ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.073/0.073/0.073 ms
/ #

范例: 创建第四个容器,引用前面创建的容器,并起多个别名

[root@ubuntu1804 ~]#docker run -it  --rm --name server4  --link
server1:"server1-alias1 server1-alias2"  alpine:3.11 sh
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  server1-alias1 server1-alias2 cdb5173003f5 server1
172.17.0.5  db3d2f084c05
/ # ping server1
PING server1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.107 ms
^C
--- server1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.107/0.107/0.107 ms
/ # ping server1-alias1
PING server1-alias1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.126 ms
^C
--- server1-alias1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.126/0.126/0.126 ms
/ # ping server1-alias2
PING server1-alias2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.124 ms
^C
--- server1-alias2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.124/0.124/0.124 ms
/ #

4.3 Docker 网络连接模式

4.3.1 网络模式介绍

Docker 的网络支持5种网络模式:

none

bridge host container

network-name

范例: 查看默认的网络模式有三个

[root@ubuntu1804 ~]#docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
fe08e6d23c4c        bridge              bridge              local
cb64aa83626c        host                host                local
10619d45dcd4        none                null                local

4.3.2 网络模式指定

默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式格式

docker run --network <mode>
docker run --net=<mode>
<mode>:  可是以下值
none
bridge
host
container:<容器名或容器ID>
<自定义网络名称>

4.2.3 bridge网络模式

4.2.3.1 bridge 网络模式架构

本模式是docker的默认模式,即不指定任何模式就是bridge模式,也是使用比较多的模式,此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信

可以和外部网络之间进行通信,通过SNAT访问外网,使用DNAT可以让容器被外部主机访问,所以此模式也称为NAT模式

此模式宿主机需要启动ip_forward功能

bridge网络模式特点

网络资源隔离: 不同宿主机的容器无法直接通信,各自使用独立网络无需手动配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改可访问外网: 利用宿主机的物理网卡,SNAT连接外网外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问低性能较低: 因为可通过NAT,网络转换带来更的损耗

  • 端口管理繁琐: 每个容器必须手动指定唯一的端口,容器产生端口冲容
4.2.3.2 bridge 模式的默认设置

范例: 查看bridge模式信息

[root@ubuntu1804 ~]#docker network inspect bridge
[
    {
"Name": "bridge",
"Id":
"fe08e6d23c4c9de00bdab479446f136c09537a1551aa62ff2c95f8cfcabd6357",
"Created": "2020-01-31T16:11:32.718471804+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
                {
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {
"cdb5173003f52033c7c8183994cf763d2a64ff39c431431402fd8dedf4727393":
{
"Name": "server1",
"EndpointID":
"6977fb6f74b75014513c34296f1e23ff0197f81f3209bbf7fcd39ba8e9f54c0d",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
            }
        },
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
        },
"Labels": {}
    }
]
[root@ubuntu1804 ~]#

范例: 宿主机的网络状态

#安装docker后.默认启用ip_forward
[root@ubuntu1804 ~]#cat /proc/sys/net/ipv4/ip_forward
1
[root@ubuntu1804 ~]#iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 245 packets, 29850 bytes)
 pkts bytes target     prot opt in     out     source               destination
11636 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0
         ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 103 packets, 20705 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 144 packets, 10324 bytes)
 pkts bytes target     prot opt in     out     source               destination
00 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8
         ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 158 packets, 11500 bytes)
 pkts bytes target     prot opt in     out     source               destination
1257831 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination
2168 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0

范例: 通过宿主机的物理网卡利用SNAT访问外部网络

#在另一台主机上建立httpd服务器
[root@centos7 ~]#systemctl is-active httpd
active
#启动容器,默认是bridge网络模式
[root@ubuntu1804 ~]#docker run -it  --rm  alpine:3.11 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
166: eth0@if167: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
#可能访问其它宿主机
/ # ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7): 56 data bytes
64 bytes from 10.0.0.7: seq=0ttl=63time=0.764 ms
64 bytes from 10.0.0.7: seq=1ttl=63time=1.147 ms
^C
---10.0.0.7 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max =0.764/0.955/1.147 ms
/ # ping www.baidu.com
PING www.baidu.com (61.135.169.125): 56 data bytes
64 bytes from 61.135.169.125: seq=0ttl=127time=5.182 ms
^C
--- www.baidu.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =5.182/5.182/5.182 ms
/ # traceroute 10.0.0.7
traceroute to 10.0.0.7 (10.0.0.7), 30 hops max, 46 byte packets
1172.17.0.1 (172.17.0.1)  0.008 ms  0.008 ms  0.007 ms
210.0.0.7 (10.0.0.7)  0.255 ms  0.510 ms  0.798 ms
/ # wget -qO - 10.0.0.7
Website on 10.0.0.7
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    000 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     000 eth0
[root@centos7 ~]#curl 127.0.0.1
Website on 10.0.0.7
[root@centos7 ~]#tail  /var/log/httpd/access_log
127.0.0.1 -- [01/Feb/2020:19:31:16 +0800] "GET / HTTP/1.1"20020"-"
"curl/7.29.0"
10.0.0.100 -- [01/Feb/2020:19:31:21 +0800] "GET / HTTP/1.1"20020"-""Wget"
4.2.3.3 修改默认的 bridge 模式网络配置

有两种方法修改默认的bridge 模式的网络配置,但两种方式只能选一种,否则会导致冲容,docker服务无法启动

范例: 修改bridge模式默认的网段方法1

[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:6b:54:d3 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe6b:54d3/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:e0:ef:72:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:feef:7205/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#docker run -it --rm  alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ #exit
#修改桥接地址
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--bip=10.100.0.1/24
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:6b:54:d3 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.101/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe6b:54d3/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:e0:ef:72:05 brd ff:ff:ff:ff:ff:ff
    inet 10.100.0.1/24 brd 10.100.0.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:feef:7205/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#docker run -it --rm  alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
179: eth0@if180: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:0a:64:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.100.0.2/24 brd 10.100.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # exit
[root@ubuntu1804 ~]#docker network inspect bridge
[
    {

"Name": "bridge", "Id": "ace11446c233d1fef534d9c734bf3ab5524afdbe76934a1a0e64803d03d54f98", "Created": "2020-02-02T13:23:58.037630754+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "10.100.0.0/24", "Gateway": "10.100.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ] [root@ubuntu1804 ~]# : 修改bridge网络配置方法2修改bridge网络配置方法2bridge网络配置方法2网络配置方法22 [root@ubuntu1804 ~]#vim /etc/docker/daemon.json { "hosts": ["tcp://0.0.0.0:2375", "fd://"], "bip": "192.168.100.100/24", # 分配 docker0 网卡的 IP,24 是容器 IP 的 netmask "fixed-cidr": "192.168.100.128/26", # 分配容器 IP 范围 ,26 不是容器 IP 的子网掩码 , 只表示地址范围 "fixed-cidr-v6": "2001:db8::/64", "mtu": 1500, "default-gateway": "192.168.100.200", # 网关必须和 bip 在同一个网段 "default-gateway-v6": "2001:db8:abcd::89", "dns": [ "1.1.1.1", "8.8.8.8"] } [root@ubuntu1804 ~]#systemctl restart docker [root@ubuntu1804 ~]#ip a show docker0

范例: 修改bridge网络配置方法2修改bridge网络配置方法2bridge网络配置方法2网络配置方法22

3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
group default
    link/ether 02:42:23:be:97:75 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.100/24 brd 192.168.100.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:23ff:febe:9775/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#docker run -it --name b1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
36: eth0@if37: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:c0:a8:64:80 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.128/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # cat /etc/resolv.conf
search wangxiaochun.com wang.org
nameserver 1.1.1.1
nameserver 8.8.8.8
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.200 0.0.0.0         UG    000 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     000 eth0
[root@ubuntu1804 ~]#docker network inspect bridge
[
    {
"Name": "bridge",
"Id":
"381bc2df514b0901e2a7570708aa93a3af05f298f27d4d077b52a8b324fad66c",
"Created": "2020-07-27T21:58:31.419420569+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
                {
"Subnet": "192.168.100.0/24",
"IPRange": "192.168.100.128/26",
"Gateway": "192.168.100.100",
"AuxiliaryAddresses": {
"DefaultGatewayIPv4": "192.168.100.200"
                    }
                },
                {
"Subnet": "2001:db8::/64",
"AuxiliaryAddresses": {
"DefaultGatewayIPv6": "2001:db8:abcd::89"
                    }
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {
"2f16c9f5efc1eefe766f6ae6ba7fcfa3434e8f4876ecdcf48c3343acd9e45b2d":
{
"Name": "b1",
"EndpointID":
"0a0fdf3d786310dca53e04f0734b9f0eeaa79aac147c7a3c69ac8d04444570f3",
"MacAddress": "02:42:c0:a8:64:80",
"IPv4Address": "192.168.100.128/24",
"IPv6Address": ""
            }
        },
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
        },
"Labels": {}
    }
]

4.2.4 Host 模式

如果指定host模式启动的容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器内除网络以外的其它资源,如: 文件系统、系统进程等仍然和宿主机保持隔离

此模式由于直接使用宿主机的网络无需转换,网络性能最高,但是各容器内使用的端口不能相同,适用于运行容器端口比较固定的业务

Host 网络模式特点:

  • 使用参数 --network host 指定

  • 共享宿主机网络

  • 网络性能无损耗

  • 网络故障排除相对简单

  • 各容器网络无隔离

网络资源无法分别统计

端口管理困难: 容易产生端口冲突

不支持端口映射

范例:

#查看宿主机的网络设置
[root@ubuntu1804 ~]#ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:2ff:fe7f:a8c6  prefixlen 64  scopeid 0x20<link>
        ether 02:42:02:7f:a8:c6  txqueuelen 0  (Ethernet)
        RX packets 63072  bytes 152573158 (152.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 56611  bytes 310696704 (310.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.100  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe34:df91  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:34:df:91  txqueuelen 1000  (Ethernet)
        RX packets 2029082  bytes 1200597401 (1.2 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7272209  bytes 11576969391 (11.5 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 3533  bytes 320128 (320.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3533  bytes 320128 (320.1 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@ubuntu1804 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    000 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     000 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     000 docker0
#打开容器前确认宿主机的80/tcp端口没有打开
[root@ubuntu1804 ~]#ss -ntl|grep :80
#创建host模式的容器
[root@ubuntu1804 ~]#docker run -d --network host --name web1 nginx-centos7-
base:1.6.1
41fb5b8e41db26e63579a424df643d1f02e272dc75e76c11f4e313a443187ed1
#创建容器后,宿主机的80/tcp端口打开
[root@ubuntu1804 ~]#ss -ntlp|grep :80
LISTEN   01280.0.0.0:80               0.0.0.0:*
users:(("nginx",pid=43762,fd=6),("nginx",pid=43737,fd=6))
#进入容器
[root@ubuntu1804 ~]#docker exec -it web1 bash
#进入容器后仍显示宿主机的主机名提示符信息
[root@ubuntu1804 /]# hostname
ubuntu1804.wang.org
[root@ubuntu1804 /]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:2ff:fe7f:a8c6  prefixlen 64  scopeid 0x20<link>
        ether 02:42:02:7f:a8:c6  txqueuelen 0  (Ethernet)
        RX packets 63072  bytes 152573158 (145.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 56611  bytes 310696704 (296.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.100  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe34:df91  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:34:df:91  txqueuelen 1000  (Ethernet)
        RX packets 2028984  bytes 1200589212 (1.1 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7272137  bytes 11576960933 (10.7 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 3533  bytes 320128 (312.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3533  bytes 320128 (312.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@ubuntu1804 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    000 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     000 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     000 docker0
#从容器访问远程主机
[root@ubuntu1804 /]# curl 10.0.0.7
Website on 10.0.0.7
#查看远程主机的访问日志
[root@centos7 ~]#tail -n1 /var/log/httpd/access_log
10.0.0.100 -- [01/Feb/2020:19:58:06 +0800] "GET / HTTP/1.1"20020"-"
"curl/7.29.0"
#远程主机可以访问容器的web服务
[root@centos7 ~]#curl 10.0.0.100/app/
Test Page in app

范例: host模式下端口映射无法实现

[root@ubuntu1804 ~]#ss -ntl|grep :81
[root@ubuntu1804 ~]#docker run -d --network host --name web2 -p 81:80  nginx-
centos7-base:1.6.1
WARNING: Published ports are discarded when using host network mode
6b6a910d79d94b188f719bc6ad00c274acd76a4a2929212157cd49b5219d44ae
#host模块下端口映射不成功,但是容器可以启动
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED
           STATUS                     PORTS               NAMES
6b6a910d79d9        nginx-centos7-base:1.6.1   "/apps/nginx/sbin/ng…"6
seconds ago        Exited (1) 2 seconds ago                       web2
b27c0fd28b40        nginx-centos7-base:1.6.1   "/apps/nginx/sbin/ng…"   About a
minute ago   Up About a minute                              web1

范例: 对比前面host模式的容器和bridge模式的端口映射

[root@ubuntu1804 ~]#docker port web1
[root@ubuntu1804 ~]#docker port web2
[root@ubuntu1804 ~]#docker run -d --network bridge -p 8001:80 --name web3 nginx-
centos7-base:1.6.1
4095372b9a561704eac98ccef8041a80a2cdc2aa7b57d2798dec1a8dcb00c377
[root@ubuntu1804 ~]#docker port web3
80/tcp -> 0.0.0.0:8001

4.2.5 none 模式

在使用none 模式后,Docker 容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用

none模式特点

使用参数 --network none 指定

  • 默认无网络功能,无法和外部通信

  • 无法实现端口映射

  • 适用于测试环境

范例: 启动none模式的容器

[root@ubuntu1804 ~]#docker run -d --network none -p 8001:80 --name web1-none
nginx-centos7-base:1.6.1
5207dcbd0aeea88548819267d3751135e337035475cf3cd63a5e1be6599c0208
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED
           STATUS              PORTS               NAMES
5207dcbd0aee        nginx-centos7-base:1.6.1   "/apps/nginx/sbin/ng…"   About a
minute ago   Up About a minute                       web1-none
[root@ubuntu1804 ~]#docker port web1-none
[root@ubuntu1804 ~]#docker exec -it web1-none bash
[root@5207dcbd0aee /]# ifconfig -a
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@5207dcbd0aee /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
[root@5207dcbd0aee /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        000.0.0.0:80              0.0.0.0:*               LISTEN
[root@5207dcbd0aee /]# ping www.baidu.com
ping: www.baidu.com: Name or service not known
[root@5207dcbd0aee /]# ping 172.17.0.1
connect: Network is unreachable
[root@5207dcbd0aee /]#

4.2.6 Container 模式

使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信

Container 模式特点

使用参数 –-network container:名称或ID 指定与宿主机网络空间隔离

空器间共享网络空间适合频繁的容器间的网络通信直接使用对方的网络,较少使用默认不支持端口映射

范例: 通过容器模式实现 wordpress

[root@ubuntu2004 ~]#rm -rf /data/wordpess /data/mysql/
[root@ubuntu2004 ~]#docker run -d  -p 80:80 --name wordpress -v
/data/wordpess:/var/www/html --restart=always  wordpress:php7.4-apache
[root@ubuntu2004 ~]#docker run --network container:wordpress -e
MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e
MYSQL_PASSWORD=123456 --name mysql -d  -v /data/mysql:/var/lib/mysql --
restart=always mysql:8.0.29-oracle

范例: 通过容器模式实现LNP架构

#准备nginx连接php-fpm的配置文件
[root@ubuntu2004 ~]#cat /data/nginx/conf.d/php.conf
server {
    listen 80;
    server_name www.wang.org;
    root /usr/share/nginx/html;
    index index.php;
    location ~ \.php$ {
       root           /usr/share/nginx/html;
       fastcgi_pass   127.0.0.1:9000;
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       include        fastcgi_params;
    }
}
#准备php的测试页文件
[root@ubuntu2004 ~]#cat /data/nginx/html/index.php
<?php
phpinfo();
?>
#启动nginx
[root@ubuntu2004 ~]#docker run -d --name nginx -v
/data/nginx/conf.d/:/etc/nginx/conf.d/ -v /data/nginx/html:/usr/share/nginx/html
-p 80:80 wangxiaochun/nginx:1.20.0

# 启动 php-fpm

[root@ubuntu2004 ~]#docker run -d --network container:nginx --name php-fpm -v
/data/nginx/html/:/usr/share/nginx/html php:8.1-fpm
#注意:php:8.1-fpm镜像缺少连接数据库的相关包,无法直接连接MySQL

范例:

#创建第一个容器
[root@ubuntu1804 ~]#docker run -it --name server1 -p 80:80 alpine:3.11 sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:9 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:766 (766.0 B)  TX bytes:0 (0.0 B)
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
/ # netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
/ #
#在另一个终端执行下面操作
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS                NAMES
4d342fac169f        alpine:3.11         "sh"29 seconds ago
Up 28 seconds       0.0.0.0:80->80/tcp   server1
[root@ubuntu1804 ~]#docker port server1
80/tcp -> 0.0.0.0:80
#无法访问web服务
[root@ubuntu1804 ~]#curl 127.0.0.1/app/
curl: (52) Empty reply from server
#创建第二个容器,基于第一个容器的container的网络模式
[root@ubuntu1804 ~]#docker run -d --name server2 --network container:server1
nginx-centos7-base:1.6.1
7db90f38590ade11e1c833a8b2175810c71b3f222753c5177bb8b05952f08a7b
#可以访问web服务
[root@ubuntu1804 ~]#curl 127.0.0.1/app/
Test Page in app
[root@ubuntu1804 ~]#docker exec -it server2 bash
#和第一个容器共享相同的网络
[root@4d342fac169f /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 29  bytes 2231 (2.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12  bytes 1366 (1.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 10  bytes 860 (860.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10  bytes 860 (860.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@4d342fac169f /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        000.0.0.0:80              0.0.0.0:*               LISTEN
#可访问外网
[root@4d342fac169f /]# ping www.baidu.com
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1ttl=127time=3.99 ms
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=2ttl=127time=5.03 ms
^C
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev =3.999/4.514/5.030/0.519 ms
[root@4d342fac169f /]#

范例: 第一个容器使用host网络模式,第二个容器与之共享网络

[root@ubuntu1804 ~]#docker run -d --name c1  --network host  nginx-
centos7.8:v5.0-1.18.0
5a60804f3917d82dfe32db140411cf475f20acce0fe4674d94e4557e1003d8e0
[root@ubuntu1804 ~]#docker run -it  --name c2 --network container:c1
centos7.8:v1.0
[root@ubuntu1804 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:63:8b:ac brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe63:8bac/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:24:86:98:fb brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:24ff:fe86:98fb/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#docker exec -it c1 bash
[root@ubuntu1804 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:63:8b:ac brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe63:8bac/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:24:86:98:fb brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:24ff:fe86:98fb/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 /]#

范例:第一个容器使用none网络模式,第二个容器与之共享网络

[root@ubuntu1804 ~]#docker run -d --name c1  --network none  nginx-
centos7.8:v5.0-1.18.0
caf5b57299c8359f21f30b8894c5f8496ff39b44ead6a732056000689cb0c91c
[root@ubuntu1804 ~]#docker run -it  --name c2 --network container:c1
centos7.8:v1.0
[root@caf5b57299c8 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
[root@caf5b57299c8 /]#

4.3.7 自定义网络模式

除了以上的网络模式,也可以自定义网络,使用自定义的网段地址,网关等信息

注意: 自定义网络内的容器可以直接通过容器名进行相互的访问,而无需使用 --link

可以使用自定义网络模式,实现不同集群应用的独立网络管理,而互不影响,而且在网一个网络内,可以直接利用容器名相互访问,非常便利

4.3.7.1 自定义网络实现
[root@ubuntu1804 ~]#docker network  --help
Usage:  docker network COMMAND
Manage networks
Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
ls          List networks
  prune       Remove all unused networks
rm          Remove one or more networks

创建自定义网络:

docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
#注意mode不支持host和none,默认是bridge模式

查看自定义网络信息

docker network inspect <自定义网络名称或网络ID>

引用自定义网络

docker run --network  <自定义网络名称> <镜像名称>
docker run --net  <自定义网络名称> --ip <指定静态IP> <镜像名称>
#注意:静态IP只支持自定义网络模型

删除自定义网络

doccker network rm <自定义网络名称或网络ID>

范例:内置的三个网络无法删除

[root@ubuntu1804 ~]#docker network rm test-net
test-net
[root@ubuntu1804 ~]#docker network rm none
Error response from daemon: none is a pre-defined network and cannot be removed
[root@ubuntu1804 ~]#docker network rm bridge
Error response from daemon: bridge is a pre-defined network and cannot be
removed
[root@ubuntu1804 ~]#docker network rm host
Error response from daemon: host is a pre-defined network and cannot be removed
4.3.7.2 实战案例: 自定义网络
4.3.7.2.1 创建自定义的网络
[root@ubuntu1804 ~]#docker  network create -d bridge --subnet 172.27.0.0/16 --
gateway 172.27.0.1 test-net
c90dee3b7937e007ed31a8d016a9e54c0174d0d26487b154db0aff04d9016d5b
[root@ubuntu1804 ~]#docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
cabde0b33c94        bridge              bridge              local
cb64aa83626c        host                host                local
10619d45dcd4        none                null                local
c90dee3b7937        test-net            bridge              local
[root@ubuntu1804 ~]#docker inspect test-net
[
    {
"Name": "test-net",
"Id":
"00ab0f2d29e82d387755e1bea19532dc279fa134a565e496d308ec62f7edf434",
"Created": "2020-07-22T09:59:09.431393706+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
                {
"Subnet": "172.27.0.0/16",
"Gateway": "172.27.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
    }
]
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:34:df:91 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.100/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe34:df91/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:9b:31:73:2b brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:9bff:fe31:732b/64 scope link
       valid_lft forever preferred_lft forever
#新添加了一个虚拟网卡
14: br-c90dee3b7937: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue
state DOWN group default
    link/ether 02:42:58:7c:f0:93 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.1/16 brd 172.27.255.255 scope global br-c90dee3b7937
       valid_lft forever preferred_lft forever
    inet6 fe80::42:58ff:fe7c:f093/64 scope link
       valid_lft forever preferred_lft forever
#新加了一个网桥
[root@ubuntu1804 ~]#brctl show
bridge name bridge id       STP enabled interfaces
br-00ab0f2d29e8     8000.024245e647ec   no
docker0     8000.0242cfd26f0a   no
[root@ubuntu1804 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    000 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     000 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     000 docker0
172.27.0.0      0.0.0.0         255.255.0.0     U     000 br-
c90dee3b7937

4.3.7.2.2 利用自定义的网络创建容器

[root@ubuntu1804 ~]#docker run -it --rm --network test-net alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # / # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.27.0.1      0.0.0.0         UG    000 eth0
172.27.0.0      0.0.0.0         255.255.0.0     U     000 eth0
/ # cat /etc/resolv.conf
search wangxiaochun.com wang.org
nameserver 127.0.0.11
options ndots:0
/ # ping -c1 www.baidu.com
PING www.baidu.com (111.206.223.172): 56 data bytes
64 bytes from 111.206.223.172: seq=0ttl=127time=5.053 ms
#再开一个新终端窗口查看网络
[root@ubuntu1804 ~]#docker inspect test-net
[
    {
"Name": "test-net",
"Id":
"00ab0f2d29e82d387755e1bea19532dc279fa134a565e496d308ec62f7edf434",
"Created": "2020-07-22T09:59:09.431393706+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
                {
"Subnet": "172.27.0.0/16",
"Gateway": "172.27.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
#出现此网络中容器的网络信息
"Containers": {
"89e54ed71c111ac7b41a62ce20191707cf53a3a234ba3e25ac11c1a4a6bed7ef":
{
"Name": "frosty_ellis",
"EndpointID":
"cf72bf192df73a8b290d8b18dd8507fef64a1f9480d4d65f74c23258d20dbafb",
"MacAddress": "02:42:ac:1b:00:02",
"IPv4Address": "172.27.0.2/16",
"IPv6Address": ""
            }
        },
"Options": {},
"Labels": {}
    }
]
4.3.7.3 实战案例: 自定义网络中的容器之间通信
[root@ubuntu1804 ~]#docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c2f770f19400        bridge              bridge              local
220d4008a6a0        host                host                local
adb6f338ff6d        none                null                local
00ab0f2d29e8        test-net            bridge              local
[root@ubuntu1804 ~]#docker run -it --rm --network test-net --name test1  alpine
sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.27.0.2  c3446876a38b
#等后面步骤中容器test2创建好可以再访问
/ # ping -c1 test2
PING test2 (172.27.0.3): 56 data bytes
64 bytes from 172.27.0.3: seq=0ttl=64time=0.072 ms
--- test2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.072/0.072/0.072 ms
[root@ubuntu1804 ~]#docker run -it --rm --network test-net --name test2 alpine
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
25: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.3/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.27.0.3  305fd14a4b70
/ # ping -c1 test1
PING test1 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0ttl=64time=0.074 ms
--- test1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.074/0.074/0.074 ms

结论: 自定义网络中的容器之间可以直接利用容器名进行通信

4.3.7.4 实战案例: 利用自定义网络实现 wordpress
[root@ubuntu2004 ~]#docker  network create -d bridge --subnet 172.27.0.0/16 --
gateway 172.27.0.1 bridge2
[root@ubuntu2004 ~]#docker run -d  -p 8080:80 --network bridge2 --name wordpress
-v /data/wordpess2:/var/www/html --restart=always  wordpress:php7.4-apache
[root@ubuntu2004 ~]#docker run --network container:wordpress2 -e
MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e
MYSQL_PASSWORD=123456 --name mysql2 -d  -v /data/mysql2:/var/lib/mysql --
restart=always mysql:8.0.29-oracle

4.3.7.5 实战案例: 利用自定义网络实现 Redis Cluster

4.3.7.5.1 创建自定义网络
[root@ubuntu1804 ~]#docker network create net-redis --subnet 172.18.0.0/16
09b9dded99787835dccc029e16fa2782292d22c3e258f60a1db15d44e7a3bd93
[root@ubuntu1804 ~]#docker inspect net-redis
[
    {
"Name": "net-redis",
"Id":
"09b9dded99787835dccc029e16fa2782292d22c3e258f60a1db15d44e7a3bd93",
"Created": "2020-07-22T14:16:43.295465692+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
                {
"Subnet": "172.18.0.0/16"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
    }
]

4.3.7.5.2 创建6个redis容器配置

# 通过脚本创建六个redis容器配置
[root@ubuntu1804 ~]#for port in {1..6};do
mkdir-p /data/redis/node-${port}/conf
cat  >> /data/redis/node-${port}/conf/redis.conf << EOF
port 6379
bind 0.0.0.0
masterauth 123456
requirepass 123456
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.18.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
[root@ubuntu1804 ~]#tree /data/redis/
/data/redis/
├── node-1
│   └── conf
│       └── redis.conf
├── node-2
│   └── conf
│       └── redis.conf
├── node-3
│   └── conf
│       └── redis.conf
├── node-4
│   └── conf
│       └── redis.conf
├── node-5
│   └── conf
│       └── redis.conf
└── node-6
    └── conf
        └── redis.conf
12 directories, 6 files
[root@ubuntu1804 ~]#cat /data/redis/node-1/conf/redis.conf
port 6379
bind 0.0.0.0
masterauth 123456
requirepass 123456
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.18.0.11
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
4.3.7.5.3 创建6个 redis 容器
# 通过脚本运行六个redis容器
[root@ubuntu1804 ~]#for port in {1..6};do
    docker run -p637${port}:6379 -p1667${port}:16379 --name redis-${port} \
-v /data/redis/node-${port}/data:/data \
-v /data/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d--net net-redis --ip172.18.0.1${port} redis:5.0.9-alpine3.11 redis-
server /etc/redis/redis.conf
done
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED
        STATUS              PORTS
NAMES
2525235efae6        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"23 seconds
ago      Up 21 seconds       0.0.0.0:6376->6379/tcp, 0.0.0.0:16676->16379/tcp
redis-6
bd89dbb445ae        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"24 seconds
ago      Up 22 seconds       0.0.0.0:6375->6379/tcp, 0.0.0.0:16675->16379/tcp
redis-5
51cb6244d34d        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"26 seconds
ago      Up 23 seconds       0.0.0.0:6374->6379/tcp, 0.0.0.0:16674->16379/tcp
redis-4
1a49a47eb72d        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"27 seconds
ago      Up 25 seconds       0.0.0.0:6373->6379/tcp, 0.0.0.0:16673->16379/tcp
redis-3
a03e957680f0        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"28 seconds
ago      Up 26 seconds       0.0.0.0:6372->6379/tcp, 0.0.0.0:16672->16379/tcp
redis-2
b5332c0cba81        redis:5.0.9-alpine3.11   "docker-entrypoint.s…"31 seconds
ago      Up 28 seconds       0.0.0.0:6371->6379/tcp, 0.0.0.0:16671->16379/tcp
redis-1

4.3.7.5.4 创建 redis cluster

#连接redis cluster
[root@ubuntu1804 ~]#docker exec -it redis-1 /bin/sh
/data # redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
127.0.0.1:6379> exit
#不支持 { } 扩展
/data # echo {1..10}
{1..10}
/data # echo $-
smi
# 创建集群
/data # redis-cli -a 123456 --cluster create 172.18.0.11:6379 172.18.0.12:6379
172.18.0.13:6379 172.18.0.14:6379 172.18.0.15:6379 172.18.0.16:6379 --cluster-
replicas 1
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0-5460
Master[1] -> Slots 5461-10922
Master[2] -> Slots 10923-16383
Adding replica 172.18.0.15:6379 to 172.18.0.11:6379
Adding replica 172.18.0.16:6379 to 172.18.0.12:6379
Adding replica 172.18.0.14:6379 to 172.18.0.13:6379
M: 0f9bd0d24495f826702a030703896f7690bebdee 172.18.0.11:6379
   slots:[0-5460] (5461 slots) master
M: 9b6ab0b8f75516d6acd9d566d0d349f1fdd29540 172.18.0.12:6379
   slots:[5461-10922] (5462 slots) master
M: 599f69b43a3579ec064b1854680c77997c809470 172.18.0.13:6379
   slots:[10923-16383] (5461 slots) master
S: c64dfd1bd6c964a3c6425a28f6ab0f0e1bcea1ba 172.18.0.14:6379
   replicates 599f69b43a3579ec064b1854680c77997c809470
S: 2f69287f52ec7243a0b894491814d2afe28a46d2 172.18.0.15:6379
   replicates 0f9bd0d24495f826702a030703896f7690bebdee
S: 06295ce4884948858cf60243629a595afa461b21 172.18.0.16:6379
   replicates 9b6ab0b8f75516d6acd9d566d0d349f1fdd29540
Can I set the above configuration? (type 'yes' to accept): #输入yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node172.18.0.11:6379)
M: 0f9bd0d24495f826702a030703896f7690bebdee 172.18.0.11:6379
   slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 2f69287f52ec7243a0b894491814d2afe28a46d2 172.18.0.15:6379
   slots: (0 slots) slave
   replicates 0f9bd0d24495f826702a030703896f7690bebdee
S: c64dfd1bd6c964a3c6425a28f6ab0f0e1bcea1ba 172.18.0.14:6379
   slots: (0 slots) slave
   replicates 599f69b43a3579ec064b1854680c77997c809470
M: 9b6ab0b8f75516d6acd9d566d0d349f1fdd29540 172.18.0.12:6379
   slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 599f69b43a3579ec064b1854680c77997c809470 172.18.0.13:6379
   slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 06295ce4884948858cf60243629a595afa461b21 172.18.0.16:6379
   slots: (0 slots) slave
   replicates 9b6ab0b8f75516d6acd9d566d0d349f1fdd29540
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
4.3.7.5.5 测试访问 redis cluster
#连接redis cluster
/data # redis-cli  -a 123456 -c
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
127.0.0.1:6379>  cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:267
cluster_stats_messages_pong_sent:278
cluster_stats_messages_sent:545
cluster_stats_messages_ping_received:273
cluster_stats_messages_pong_received:267
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:545
127.0.0.1:6379> cluster nodes
#看到172.18.0.{11,12,13}为master,172.18.0.{14,15,16}为slave
#以下为master/slave关系
#172.18.0.11<--->172.18.0.15
#172.18.0.12<--->172.18.0.16
#172.18.0.13<--->172.18.0.14
2f69287f52ec7243a0b894491814d2afe28a46d2 172.18.0.15:6379@16379 slave
0f9bd0d24495f826702a030703896f7690bebdee 015954042695815 connected
0f9bd0d24495f826702a030703896f7690bebdee 172.18.0.11:6379@16379 myself,master -
015954042690001 connected 0-5460
c64dfd1bd6c964a3c6425a28f6ab0f0e1bcea1ba 172.18.0.14:6379@16379 slave
599f69b43a3579ec064b1854680c77997c809470 015954042680004 connected
9b6ab0b8f75516d6acd9d566d0d349f1fdd29540 172.18.0.12:6379@16379 master -0
15954042689762 connected 5461-10922
599f69b43a3579ec064b1854680c77997c809470 172.18.0.13:6379@16379 master -0
15954042694813 connected 10923-16383
06295ce4884948858cf60243629a595afa461b21 172.18.0.16:6379@16379 slave
9b6ab0b8f75516d6acd9d566d0d349f1fdd29540 015954042680006 connected
#添加key到redis-2上
127.0.0.1:6379> set name wang
-> Redirected to slot [5798] located at 172.18.0.12:6379
OK
#添加key到redis-1上
172.18.0.12:6379> set title cto
-> Redirected to slot [2217] located at 172.18.0.11:6379
OK
172.18.0.11:6379> get name
-> Redirected to slot [5798] located at 172.18.0.12:6379
"wang"
172.18.0.12:6379> get title
-> Redirected to slot [2217] located at 172.18.0.11:6379
"cto"

4.3.7.5.6 测试故障实现 redis cluster 高可用性

#模拟redis-2故障
[root@ubuntu1804 ~]#docker stop  redis-2
redis-2
#再次查看cluster状态,可以看到redis-2出错
[root@ubuntu1804 ~]#docker exec -it redis-1 /bin/sh
/data # redis-cli -a 123456 --cluster check 127.0.0.1:6379
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
Could not connect to Redis at 172.18.0.12:6379: Host is unreachable
#查看到 172.18.0.16提升为新的master
172.18.0.16:6379 (06295ce4...) -> 1 keys | 5462 slots | 0 slaves.
172.18.0.13:6379 (599f69b4...) -> 0 keys | 5461 slots | 1 slaves.
172.18.0.15:6379 (2f69287f...) -> 1 keys | 5461 slots | 1 slaves.
[OK] 2 keys in3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node127.0.0.1:6379)
S: 0f9bd0d24495f826702a030703896f7690bebdee 127.0.0.1:6379
   slots: (0 slots) slave
   replicates 2f69287f52ec7243a0b894491814d2afe28a46d2
M: 06295ce4884948858cf60243629a595afa461b21 172.18.0.16:6379
   slots:[5461-10922] (5462 slots) master
M: 599f69b43a3579ec064b1854680c77997c809470 172.18.0.13:6379
   slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: 2f69287f52ec7243a0b894491814d2afe28a46d2 172.18.0.15:6379
   slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: c64dfd1bd6c964a3c6425a28f6ab0f0e1bcea1ba 172.18.0.14:6379
   slots: (0 slots) slave
   replicates 599f69b43a3579ec064b1854680c77997c809470
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/data # redis-cli  -a 123456 -c
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
127.0.0.1:6379>  cluster nodes
06295ce4884948858cf60243629a595afa461b21 172.18.0.16:6379@16379 master -0
15954065731288 connected 5461-10922
599f69b43a3579ec064b1854680c77997c809470 172.18.0.13:6379@16379 master -0
15954065726233 connected 10923-16383
0f9bd0d24495f826702a030703896f7690bebdee 172.18.0.11:6379@16379 myself,slave
2f69287f52ec7243a0b894491814d2afe28a46d2 015954065710001 connected
2f69287f52ec7243a0b894491814d2afe28a46d2 172.18.0.15:6379@16379 master -0
15954065716147 connected 0-5460
9b6ab0b8f75516d6acd9d566d0d349f1fdd29540 172.18.0.12:6379@16379 master,fail -
159540453383915954045325282 connected
c64dfd1bd6c964a3c6425a28f6ab0f0e1bcea1ba 172.18.0.14:6379@16379 slave
599f69b43a3579ec064b1854680c77997c809470 015954065721184 connected
127.0.0.1:6379> get name
-> Redirected to slot [5798] located at 172.18.0.16:6379
"wang"
172.18.0.16:6379> get title
-> Redirected to slot [2217] located at 172.18.0.15:6379
"cto"

4.3.8 同一个宿主机之间不同网络的容器通信

开两个容器,一个使用自定义网络容器,一个使用默认brideg网络的容器,默认因iptables规则导致无法通信

[root@ubuntu1804 ~]#docker run -it --rm  --name test1 alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.27.0.2    #无法ping通自定义网络容器
PING 172.27.0.2 (172.27.0.2): 56 data bytes
[root@ubuntu1804 ~]#docker run -it --rm --network test-net --name test2 alpine
sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 172.17.0.2    #无法ping 通默认的网络容器
PING 172.27.0.2 (172.17.0.2): 56 data bytes
4.3.8.1 实战案例 1: 修改iptables实现同一宿主机上的不同网络的容器间通信
#确认开启ip_forward
[root@ubuntu1804 ~]#cat /proc/sys/net/ipv4/ip_forward
1
#默认网络和自定义网络是两个不同的网桥
[root@ubuntu1804 ~]#brctl  show
bridge name bridge id       STP enabled interfaces
br-c90dee3b7937     8000.0242587cf093   no      veth984a5b4
docker0     8000.02429b31732b   no      veth1a20128
[root@ubuntu1804 ~]#iptables -vnL
Chain INPUT (policy ACCEPT 1241 packets, 87490 bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
85972156 DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0
85972156 DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0
0.0.0.0/0
00 ACCEPT     all  --  *      br-c90dee3b7937  0.0.0.0/0
0.0.0.0/0            ctstate RELATED,ESTABLISHED
00 DOCKER     all  --  *      br-c90dee3b7937  0.0.0.0/0
0.0.0.0/0
00 ACCEPT     all  --  br-c90dee3b7937 !br-c90dee3b7937  0.0.0.0/0
0.0.0.0/0
00 ACCEPT     all  --  br-c90dee3b7937 br-c90dee3b7937  0.0.0.0/0
0.0.0.0/0
00 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
         ctstate RELATED,ESTABLISHED
00 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
00 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0
00 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0
Chain OUTPUT (policy ACCEPT 1456 packets, 209K bytes)
 pkts bytes target     prot opt in     out     source               destination
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
 pkts bytes target     prot opt in     out     source               destination
28924276 DOCKER-ISOLATION-STAGE-2  all  --  br-c90dee3b7937 !br-c90dee3b7937
0.0.0.0/0            0.0.0.0/0
57047880 DOCKER-ISOLATION-STAGE-2  all  --  docker0 !docker0  0.0.0.0/0
0.0.0.0/0
00 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (2 references)
 pkts bytes target     prot opt in     out     source               destination
57047880 DROP       all  --  *      br-c90dee3b7937  0.0.0.0/0
0.0.0.0/0
28924276 DROP       all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
00 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0
Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination
85972156 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0
[root@ubuntu1804 ~]#
[root@ubuntu1804 ~]#iptables-save
# Generated by iptables-save v1.6.1 on Sun Feb  2 14:33:19 2020
*filter
:INPUT ACCEPT [1283:90246]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [1489:217126]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o br-c90dee3b7937 -m conntrack --ctstate RELATED,ESTABLISHED -j
ACCEPT
-A FORWARD -o br-c90dee3b7937 -j DOCKER
-A FORWARD -i br-c90dee3b7937 ! -o br-c90dee3b7937 -j ACCEPT
-A FORWARD -i br-c90dee3b7937 -o br-c90dee3b7937 -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-c90dee3b7937 ! -o br-c90dee3b7937 -j DOCKER-
ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o br-c90dee3b7937 -j DROP #注意此行规则
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP   #注意此行规则
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sun Feb  2 14:33:19 2020
# Generated by iptables-save v1.6.1 on Sun Feb  2 14:33:19 2020
*nat
:PREROUTING ACCEPT [887:75032]
:INPUT ACCEPT [6:1028]
:OUTPUT ACCEPT [19:1444]
:POSTROUTING ACCEPT [19:1444]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s172.27.0.0/16 ! -o br-c90dee3b7937 -j MASQUERADE
-A POSTROUTING -s172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i br-c90dee3b7937 -j RETURN
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Sun Feb  2 14:33:19 2020
[root@ubuntu1804 ~]#iptables-save > iptables.rule
[root@ubuntu1804 ~]#vim iptables.rule
#修改下面两行的规则
-A DOCKER-ISOLATION-STAGE-2 -o br-c90dee3b7937 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j ACCEPT
#或者执行下面命令
[root@ubuntu1804 ~]#iptables -I DOCKER-ISOLATION-STAGE-2  -j ACCEPT
[root@ubuntu1804 ~]#iptables-restore < iptables.rule
#再次两个容器之间可以相互通信
/ # ping 172.27.0.2
PING 172.27.0.2 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=896ttl=63time=0.502 ms
64 bytes from 172.27.0.2: seq=897ttl=63time=0.467 ms
64 bytes from 172.27.0.2: seq=898ttl=63time=0.227 ms
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=63time=0.163 ms
64 bytes from 172.17.0.2: seq=1ttl=63time=0.232 ms
4.3.8.2 实战案例 2: 通过解决docker network connect 实现同一个宿主机不同网络的容器间通信

可以使用docker network connect命令实现同一个宿主机不同网络的容器间相互通信

#将CONTAINER连入指定的NETWORK中,使此CONTAINER可以与NETWORK中的其它容器进行通信
docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings           Add network-scoped alias for the container
--driver-opt strings      driver options for the network
--ip string               IPv4 address (e.g., 172.30.100.104)
--ip6 string              IPv6 address (e.g., 2001:db8::33)
--link list               Add link to another container
--link-local-ip strings   Add a link-local address for the container
#将CONTAINER与指定的NETWORK断开连接,使此CONTAINER可以与CONTAINER中的其它容器进行无法通信
#如果将容器从自定义的网络删除,将加入默认的网络,即docker0网桥中,获取172.17.0.0/16
#如果将容器从默认的网络docker0删除,将加入none网络
docker network disconnect [OPTIONS] NETWORK CONTAINER
Disconnect a container from a network
Options:
-f, --force   Force the container to disconnect from a network
4.3.8.2.1 上面案例中test1和test2的容器间默认无法通信
#每个网络中有属于此网络的容器信息
[root@ubuntu1804 ~]#docker network  inspect bridge
[
    {
"Name": "bridge",
"Id":
"c2f770f19400aa482054a92f2ff6ce54cae2ed45a15c7d98e0959c64dfefd58d",
"Created": "2020-07-22T09:23:20.265208248+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
                {
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {
"9bc707b1a810c4bab39a4c0ed3ff5867cc45b21fe8ae6737f2a9d0163ed2c7a9":
{
"Name": "test1",
"EndpointID":
"475bba6925c426158b3c523e07b6773c884d404d82e6c19d5e4a41f54f8856c2",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
            }
        },
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
        },
"Labels": {}
    }
]
#每个网络中有属于此网络的容器信息
[root@ubuntu1804 ~]#docker network  inspect test-net
[
    {
"Name": "test-net",
"Id":
"00ab0f2d29e82d387755e1bea19532dc279fa134a565e496d308ec62f7edf434",
"Created": "2020-07-22T09:59:09.431393706+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
                {
"Subnet": "172.27.0.0/16",
"Gateway": "172.27.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {
"c3446876a38b3d7e70ca35429051dea7373643a95689d22f252faedc31f3c427":
{
"Name": "test2",
"EndpointID":
"13fb11baeca7e90abdc9183334315e95df4a55367d3add1472d741a556cb662c",
"MacAddress": "02:42:ac:1b:00:02",
"IPv4Address": "172.27.0.2/16",
"IPv6Address": ""
            }
        },
"Options": {},
"Labels": {}
    }
]

4.3.8.2.2 让默认网络中容器test1可以连通自定义网络test-net的容器test2

[root@ubuntu1804 ~]#docker network connect test-net test1
[root@ubuntu1804 ~]#docker network  inspect test-net
[
    {
"Name": "test-net",
"Id":
"00ab0f2d29e82d387755e1bea19532dc279fa134a565e496d308ec62f7edf434",
"Created": "2020-07-22T09:59:09.431393706+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
                {
"Subnet": "172.27.0.0/16",
"Gateway": "172.27.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {
"9bc707b1a810c4bab39a4c0ed3ff5867cc45b21fe8ae6737f2a9d0163ed2c7a9":
{
"Name": "test1",
"EndpointID":
"600891a1f0727f0fddcb9c123540d02963a30a54d011554e0dfd1c108ecabdd2",
"MacAddress": "02:42:ac:1b:00:03",
"IPv4Address": "172.27.0.3/16",
"IPv6Address": ""
            },
"c3446876a38b3d7e70ca35429051dea7373643a95689d22f252faedc31f3c427":
{
"Name": "test2",
"EndpointID":
"13fb11baeca7e90abdc9183334315e95df4a55367d3add1472d741a556cb662c",
"MacAddress": "02:42:ac:1b:00:02",
"IPv4Address": "172.27.0.2/16",
"IPv6Address": ""
            }
        },
"Options": {},
"Labels": {}
    }
]
#在test1容器中可以看到新添加了一个网卡,并且分配了test-net网络的IP信息
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
29: eth1@if30: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.3/16 brd 172.27.255.255 scope global eth1
       valid_lft forever preferred_lft forever
#test1可以连接test2容器
/ # ping -c1 172.27.0.2
PING 172.27.0.2 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0ttl=64time=0.100 ms
---172.27.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.100/0.100/0.100 ms
#在test2容器中没有变化,仍然无法连接test1
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
^C
---172.17.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

4.3.8.2.3 让自定义网络中容器test2可以连通默认网络的容器test1

#将自定义网络中的容器test2也加入到默认网络中,使之和默认网络中的容器test1通信
[root@ubuntu1804 ~]#docker network connect bridge test2
[root@ubuntu1804 ~]#docker network  inspect bridge
[
    {
"Name": "bridge",
"Id":
"c2f770f19400aa482054a92f2ff6ce54cae2ed45a15c7d98e0959c64dfefd58d",
"Created": "2020-07-22T09:23:20.265208248+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
                {
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
                }
            ]
        },
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
        },
"ConfigOnly": false,
"Containers": {
"9bc707b1a810c4bab39a4c0ed3ff5867cc45b21fe8ae6737f2a9d0163ed2c7a9":
{
"Name": "test1",
"EndpointID":
"475bba6925c426158b3c523e07b6773c884d404d82e6c19d5e4a41f54f8856c2",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
            },
"c3446876a38b3d7e70ca35429051dea7373643a95689d22f252faedc31f3c427":
{
"Name": "test2",
"EndpointID":
"a049010b37dd5a40c1ff8e8d0b327b70727316dd86b2c69c05231bfd6c985af6",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
            }
        },
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
        },
"Labels": {}
    }
]
#确认自定义网络的容器test2中添加了新网卡,并设置默认网络的IP信息
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
31: eth1@if32: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1
       valid_lft forever preferred_lft forever
#test2可以连接test1容器
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.128 ms
---172.17.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =0.128/0.128/0.128 ms
#在test1中可以利用test2容器名通信
/ # ping -c1 test2
PING test2 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0ttl=64time=0.076 ms
#在test2中可以利test1容器名通信
/ # ping -c1 test1
PING test1 (172.27.0.3): 56 data bytes
64 bytes from 172.27.0.3: seq=0ttl=64time=0.075 ms
4.3.8.2.4 断开不同网络中容器的通信
#将test1 断开和网络test-net中其它容器的通信
[root@ubuntu1804 ~]#docker network  disconnect test-net test1
#在容器test1中无法和test2通信
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping  -c1 172.27.0.2
PING 172.27.0.2 (172.27.0.2): 56 data bytes
---172.27.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#在容器test2中仍能和test1通信
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
31: eth1@if32: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1
       valid_lft forever preferred_lft forever
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0ttl=64time=0.085 ms
#将test2 断开和默认网络中其它容器的通信
[root@ubuntu1804 ~]#docker network  disconnect bridge test2
#在容器test2中无法和test1通信
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
---172.17.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

4.4 实现跨宿主机的容器之间网络互联

同一个宿主机之间的各个容器之间是可以直接通信的,但是如果访问到另外一台宿主机的容器呢?

4.4.1 方式1: 利用桥接实现跨宿主机的容器间互联

#分别将两个宿主机都执行下面操作
[root@ubuntu1804 ~]#apt -y install bridge-utils
[root@ubuntu1804 ~]#brctl addif docker0 eth0
#在两个宿主机上各启动一个容器,需要确保IP不同,相互测试访问
#第一个宿主机的容器
[root@ubuntu1804 ~]#docker run -it --name b1 busybox
/ # hostname -i
172.17.0.2
/ # httpd -h /data/html/ -f -v
[::ffff:172.17.0.3]:42488:response:200
#第二个宿主机的容器
[root@ubuntu1804 ~]#docker run -it --name b2 busybox
/ # hostname -i
172.17.0.3
/#wget-q0 - http://172.17.0.2
httpd website in busybox

4.4.2 方式2: 利用NAT实现跨主机的容器间互联

4.4.2.1 docker跨主机互联实现说明

跨主机互联是说A宿主机的容器可以访问B主机上的容器,但是前提是保证各宿主机之间的网络是可以相互通信的,然后各容器才可以通过宿主机访问到对方的容器

实现原理: 是在宿主机做一个网络路由就可以实现A宿主机的容器访问B主机的容器的目的

注意: 此方式只适合小型网络环境,复杂的网络或者大型的网络可以使用google开源的k8s进行互联

4.4.2.2 修改各宿主机网段

Docker默认网段是172.17.0.x/24,而且每个宿主机都是一样的,因此要做路由的前提就是各个主机的网络不能一致

4.4.2.2.1 第一个宿主机A上更改网段
[root@ubuntu1804 ~]#vim /etc/docker/daemon.json
[root@ubuntu1804 ~]#cat /etc/docker/daemon.json
{
"bip": "192.168.100.1/24",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
[root@ubuntu1804 ~]# systemctl restart docker
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:6b:54:d3 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.101/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe6b:54d3/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:e0:ef:72:05 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e0ff:feef:7205/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    000 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     000 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     000 docker0

4.4.2.2.2 第二个宿主机B更改网段

[root@ubuntu1804 ~]#vim /etc/docker/daemon.json
{
"bip": "192.168.200.1/24",
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
group default qlen 1000
    link/ether 00:0c:29:01:f3:0c brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.102/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe01:f30c/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
    link/ether 02:42:e8:c0:a4:d8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.1/24 brd 192.168.200.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:e8ff:fec0:a4d8/64 scope link
       valid_lft forever preferred_lft forever
[root@ubuntu1804 ~]#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.2        0.0.0.0         UG    000 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     000 eth0
192.168.200.0   0.0.0.0         255.255.255.0   U     000 docker0
4.4.2.3 在两个宿主机分别启动一个容器

第一个宿主机启动容器server1

[root@ubuntu1804 ~]#docker run -it --name server1 --rm  alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.2/24 brd 192.168.100.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG    000 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     000 eth0

第二个宿主机启动容器server2

[root@ubuntu1804 ~]#docker run -it --name server2 --rm  alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:c0:a8:c8:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.2/24 brd 192.168.200.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.200.1   0.0.0.0         UG    000 eth0
192.168.200.0   0.0.0.0         255.255.255.0   U     000 eth0

从第一个宿主机的容器server1无法和第二个宿主机的server2相互访问

[root@ubuntu1804 ~]#docker run -it --name server1 --rm  alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:0a:64:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.100.0.2/16 brd 10.100.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping -c1 192.168.200.2
PING 192.168.200.2 (192.168.200.2): 56 data bytes
---192.168.200.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
4.4.2.4 添加静态路由和iptables规则

在各宿主机添加静态路由,网关指向对方宿主机的IP

4.4.2.4.1 在第一台宿主机添加静态路由和iptables规则
#添加路由
[root@ubuntu1804 ~]#route add -net 192.168.200.0/24 gw 10.0.0.102
#修改iptables规则
[root@ubuntu1804 ~]#iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT
#或者修改FORWARD默认规则
[root@ubuntu1804 ~]#iptables -P FORWARD ACCEPT
4.4.2.4.2 在第二台宿主机添加静态路由和iptables规则
#添加路由
[root@ubuntu1804 ~]#route add -net 192.168.100.0/24 gw 10.0.0.101
#修改iptables规则
[root@ubuntu1804 ~]#iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT
#或者修改FORWARD默认规则
[root@ubuntu1804 ~]#iptables -P FORWARD ACCEPT
4.4.2.5 测试跨宿主机之间容器互联

宿主机A的容器server1访问宿主机B容器server2,同时在宿主机B上tcpdump抓包观察

/ # ping -c1 192.168.200.2
PING 192.168.200.2 (192.168.200.2): 56 data bytes
64 bytes from 192.168.200.2: seq=0ttl=62time=1.022 ms
---192.168.200.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =1.022/1.022/1.022 ms
#宿主机B的抓包可以观察到
[root@ubuntu1804 ~]#tcpdump  -i eth0 -nn icmp
tcpdump: verbose output suppressed, use -v or -vvfor full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:57:37.912925 IP 10.0.0.101 > 192.168.200.2: ICMP echo request, id 2560, seq
0, length 64
16:57:37.913208 IP 192.168.200.2 > 10.0.0.101: ICMP echo reply, id 2560, seq 0,
length 64

宿主机B的容器server2访问宿主机B容器server1,同时在宿主机A上tcpdump抓包观察

/ # ping -c1 192.168.100.2
PING 192.168.100.2 (192.168.100.2): 56 data bytes
64 bytes from 192.168.100.2: seq=0ttl=62time=1.041 ms
---192.168.100.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max =1.041/1.041/1.041 ms
#宿主机A的抓包可以观察到
[root@ubuntu1804 ~]#tcpdump -i eth0 -nn icmp
tcpdump: verbose output suppressed, use -v or -vvfor full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:59:11.775784 IP 10.0.0.102 > 192.168.100.2: ICMP echo request, id 2560, seq
0, length 64
16:59:11.776113 IP 192.168.100.2 > 10.0.0.102: ICMP echo reply, id 2560, seq 0,
length 64
4.4.2.6 创建第三个容器测试
#在第二个宿主机B上启动第一个提供web服务的nginx容器server3
#注意无需打开端口映射
[root@ubuntu1804 ~]#docker run  -d --name server3 centos7-nginx:1.6.1
69fc554fd00e4f7880c139283b64f2701feafb91047b217906b188c1f461b699
[root@ubuntu1804 ~]#docker exec -it server3 bash
[root@69fc554fd00e /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.200.3  netmask 255.255.255.0  broadcast 192.168.200.255
        ether 02:42:c0:a8:c8:03  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 656 (656.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@69fc554fd00e /]#
#从server1中访问server3的页面可以成功
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
    link/ether 02:42:0a:64:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.100.0.2/16 brd 10.100.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # wget -qO - http://192.168.200.3/app
Test Page in app
/ #
#从server3容器观察访问日志,可以看到来自于第一个宿主机,而非server1容器
[root@69fc554fd00e /]# tail -f /apps/nginx/logs/access.log
10.0.0.101 -- [02/Feb/2020:09:02:00 +0000] "GET /app HTTP/1.1"301169"-"
"Wget"
#用tcpdump抓包80/tcp的包,可以观察到以下内容
[root@ubuntu1804 ~]#tcpdump  -i eth0 -nn port 80
tcpdump: verbose output suppressed, use -v or -vvfor full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:03:35.885627 IP 10.0.0.101.43578 > 192.168.200.3.80: Flags [S], seq
3672256868, win 29200, options [mss 1460,sackOK,TS val 4161963574 ecr
0,nop,wscale 7], length 0
17:03:35.885768 IP 192.168.200.3.80 > 10.0.0.101.43578: Flags [S.], seq
2298407060, ack 3672256869, win 28960, options [mss 1460,sackOK,TS val
3131173298 ecr 4161963574,nop,wscale 7], length 0
17:03:35.886312 IP 10.0.0.101.43578 > 192.168.200.3.80: Flags [.], ack 1, win
229, options [nop,nop,TS val 4161963575 ecr 3131173298], length 0
17:03:35.886507 IP 10.0.0.101.43578 > 192.168.200.3.80: Flags [P.], seq 1:80,
ack 1, win 229, options [nop,nop,TS val 4161963575 ecr 3131173298], length 79:
HTTP: GET /app HTTP/1.1
17:03:35.886541 IP 192.168.200.3.80 > 10.0.0.101.43578: Flags [.], ack 80, win
227, options [nop,nop,TS val 3131173299 ecr 4161963575], length 0
17:03:35.887179 IP 192.168.200.3.80 > 10.0.0.101.43578: Flags [P.], seq 1:365,
ack 80, win 227, options [nop,nop,TS val 3131173299 ecr 4161963575], length 364:
HTTP: HTTP/1.1 301 Moved Permanently
17:03:35.887222 IP 192.168.200.3.80 > 10.0.0.101.43578: Flags [F.], seq 365, ack
80, win 227, options [nop,nop,TS val 3131173299 ecr 4161963575], length 0
17:03:35.890139 IP 10.0.0.101.43580 > 192.168.200.3.80: Flags [.], ack
1660534352, win 229, options [nop,nop,TS val 4161963579 ecr 3131173301], length
0
17:03:35.890297 IP 10.0.0.101.43580 > 192.168.200.3.80: Flags [P.], seq 0:80,
ack 1, win 229, options [nop,nop,TS val 4161963579 ecr 3131173301], length 80:
HTTP: GET /app/ HTTP/1.1
17:03:35.890327 IP 192.168.200.3.80 > 10.0.0.101.43580: Flags [.], ack 80, win
227, opons [nop,nop,TS val 3131173303 ecr 4161963579], length 0

5 容器单机编排工具 Docker Compose

5.1 Docker Compose介绍

当在宿主机启动较多的容器时候,如果都是手动操作会觉得比较麻烦而且容易出错,此时推荐使用 docker 单机编排工具 docker-compose

docker-compose 是 docker 容器的一种单机编排服务,docker-compose 是一个管理多个容器的工具,比如: 可以解决容器之间的依赖关系,就像启动一个nginx 前端服务的时候会调用后端的tomcat, 那就得先启动tomcat,但是启动tomcat 容器还需要依赖数据库,那就还得先启动数据库,dockercompose 可以用来解决这样的嵌套依赖关系,并且可以替代docker命令对容器进行创建、启动和停止等手工的操作

因此,如果说docker命令就像linux的命令,docker compose就像shell脚本,可以自动的执行容器批量操作,从而实现自动化的容器管理,或者说docker命令相当于ansible命令,那么docker compose文件,就相当于ansible-playbook的yaml文件

docker-compose 项目是Docker 官方的开源项目,负责实现对Docker 容器集群的快速编排,dockercompose 将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container) github地址: https://github.com/docker/compose

官方地址: https://docs.docker.com/compose/

5.2 安装和准备

5.2.1 安装Docker Compose

5.2.1.1 方法1: 在线安装,通过pip安装

python-pip 包将安装一个 pip 的命令,pip 命令是一个python 安装包的安装工具,其类似于ubuntu 的 apt 或者 redhat 的yum,但是pip 只安装 python 相关的安装包,可以在多种操作系统安装和使用pip

此方式当前安装的版本较新,为docker_compose-1.25.3,推荐使用

Ubuntu:
# apt  update
# apt  install -y  python-pip
CentOS:
# yum install epel-release
# yum install -y python-pip
# pip install --upgrade pip

范例: 基于python3 安装 docker-compose

#配置加速
[root@ubuntu2004 ~]#mkdir ~/.pip
[root@ubuntu2004 ~]#cat > ~/.pip/pip.conf <<-EOF
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
EOF
[root@ubuntu2004 ~]#apt -y install python3-pip
[root@ubuntu2004 ~]#pip3 install --upgrade pip
[root@ubuntu2004 ~]#pip3 install docker-compose
[root@ubuntu2004 ~]#docker-compose --version
docker-compose version 1.27.4, build unknown

范例:基于python2安装docker-compose

[root@ubuntu1804 ~]#apt -y install python-pip
[root@ubuntu1804 ~]#pip install docker-compose
[root@ubuntu1804 ~]#docker-compose --version
docker-compose version 1.25.3, build unknown
5.2.1.2 方法2: 在线直接从包仓库安装

此方法安装的版本较旧,不推荐使用

#ubuntu安装,此为默认版本
[root@ubuntu1804 ~]#apt -y install docker-compose
[root@ubuntu1804 ~]#docker-compose --version
docker-compose version 1.17.1, build unknown
#CentOS7安装,依赖EPEL源
[root@centos7 ~]#yum -y install docker-compose
[root@centos7 ~]#docker-compose --version
docker-compose version 1.18.0, buil 8dd22a9
5.2.1.3 方法3: 离线安装,直接从github或国内镜像站下载安装对应版本

参看说明: https://github.com/docker/compose/releases

此方法安装版本可方便指定,推荐方法,但网络下载较慢

[root@ubuntu1804 ~]#curl -L
https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname
-s`-`uname -m` -o /usr/local/bin/docker-compose
#从国内镜像站下载
[root@ubuntu1804 ~]#curl -L
https://get.daocloud.io/docker/compose/releases/download/1.25.3/docker-
compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
[root@ubuntu1804 ~]#chmod +x /usr/local/bin/docker-compose

5.2.2 查看命令格式

官方文档: https://docs.docker.com/compose/reference/

docker-compose --help
Define and run multi-container applications with Docker.
Usage:
  docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
  docker-compose -h|--help
#选项说明:
-f,–file FILE #指定Compose 模板文件,默认为docker-compose.yml
-p,–project-name NAME #指定项目名称,默认将使用当前所在目录名称作为项目名。
--verbose#显示更多输出信息
--log-level LEVEL    #定义日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
--no-ansi#不显示ANSI 控制字符
-v, --version#显示版本
#以下为命令选项,需要在docker-compose.yml|yaml 文件所在在目录里执行
config  -q#查看当前配置,没有错误不输出任何信息
up #创建并启动容器
build  #构建镜像
bundle #从当前docker compose 文件生成一个以<当前目录>为名称的json格式的Docker Bundle 备
份文件
create #创建服务
down #停止和删除所有容器、网络、镜像和卷
events #从容器接收实时事件,可以指定json 日志格式
exec #进入指定容器进行操作
help #显示帮助细信息
images #显示镜像信息
kill#强制终止运行中的容器
logs #查看容器的日志
pause #暂停服务
port #查看端口
ps#列出容器
pull #重新拉取镜像,镜像发生变化后,需要重新拉取镜像
push #上传镜像
restart#重启服务
rm#删除已经停止的服务
run #一次性运行容器
scale  #设置指定服务运行的容器个数,新版已废弃
start#启动服务
stop#停止服务
top#显示容器运行状态
unpause #取消暂定

范例:

[root@ubuntu1804 ~]#docker-compose --version
docker-compose version 1.25.3, build d4d1b42b

5.2.3 docker compose 文件格式

官方文档: https://docs.docker.com/compose/compose-file/

docker compose 文件是一个yaml格式的文件,所以注意行首的缩进很严格

默认docker-compose命令会调用当前目录下的docker-compose.yml的文件,因此一般执行dockercompose命令前先进入docker-compose.yml文件所在目录

docker compose文件的格式很不同版本,版本不同,语法和格式有所不同,参看以下列表

Compose file format Docker Engine release
3.7 18.06.0+
3.6 18.02.0+
3.5 17.12.0+
3.4 17.09.0+
3.3 17.06.0+
3.2 17.04.0+
3.1 1.13.1+
3.0 1.13.0+
2.4 17.12.0+
2.3 17.06.0+
2.2 1.13.0+
2.1 1.12.0+
2.0 1.10.0+
1.0 1.9.1.+

docker compose版本众多,以下通过具体示例说明docker compose的使用方法

5.3 Docker compose 启动单个容器

注意: 使用 Docker Compose之前,先要安装 Docker

5.3.1 创建 docker compose 文件

docker compose 文件可在任意目录,创建文件名为 docker-compose.yml 或者dockercompose.yaml 配置文件,要注意前后的缩进

[root@ubuntu1804 ~]#docker-compose --version
docker-compose version 1.25.4, build unknown
[root@ubuntu1804 ~]#mkdir /data/docker-compose
[root@ubuntu1804 ~]#cd /data/docker-compose
[root@ubuntu1804 docker-compose]#vim  docker-compose.yml
[root@ubuntu1804 docker-compose]#cat docker-compose.yml
version: '2.1'
services:
  service-nginx-web:
    container_name: nginx-web
    expose:
-80
-443
    image: harbor.wang.org/example/nginx-centos7-base:1.6.1
    network_mode: bridge
    ports:
-80:80/tcp
-443:443/tcp
restart: always
    healthcheck: #服务健康状态检查
    test: ["CMD", "curl", "-f", "http://127.0.0.1"]
    interval: 5s #健康检查间隔时间,默认为30s
    timeout: 5s  #每次检查失败的超时时间,默认为30s
    retries: 3#连续失败次数,当连续失败达到retries次数后,将容器置为unhealthy状态,默认3
次
    start_period: 60s #此时间后每间隔interval的时间检查一次,连续retries次后才将容器置为
unhealthy状态,但是start_period时间内检查成功则认为检查成功,此时容器状态为healthy

5.3.2 查看配置和格式检查

[root@ubuntu1804 docker-compose]#docker-compose  config
version: '2.1'
services:
  service-nginx-web:
    container_name: nginx-web
....
[root@ubuntu1804 docker-compose]#docker-compose  config -q
#改错ocker-compose文件格式
[root@ubuntu1804 docker-compose]#vim docker-compose.yml
service-nginx-web   #改此行,最后的”:"删除
[root@ubuntu1804 docker-compose]#docker-compose  config -q
ERROR: yaml.scanner.ScannerError: mapping values are not allowed here
in"./docker-compose.yml", line 2, column 8
[root@ubuntu1804 docker-compose]#

5.3.3 启动容器

注意: 必须要在docker compose文件所在的目录执行

#前台启动
[root@ubuntu1804 docker-compose]#docker-compose up
Pulling service-nginx-web (harbor.wang.org/example/nginx-centos7-base:1.6.1)...
ERROR: Get https://harbor.wang.org/v2/: dial tcp 10.0.0.102:443: connect:
connection refused
[root@ubuntu1804 docker-compose]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry harbor.wang.org
[root@ubuntu1804 docker-compose]#systemctl daemon-reload
[root@ubuntu1804 docker-compose]#systemctl restart docker
[root@ubuntu1804 docker-compose]#docker-compose up
Pulling service-nginx-web (10.0.0.102/example/nginx-centos7-base:1.6.1)...
1.6.1: Pulling from example/nginx-centos7-base
f34b00c7da20: Pull complete
544476d462f7: Pull complete
39345915aa1b: Pull complete
d5376f2bbd9e: Pull complete
4596aecee927: Pull complete
1617b995c379: Pull complete
d00df95be654: Pull complete
Digest: sha256:82e9e7d8bf65e160ba79a92bb25ae42cbbf791092d1e09fb7de25f91b31a21ff
Status: Downloaded newer image for10.0.0.102/example/nginx-centos7-base:1.6.1
Creating nginx-web ... done
Attaching to nginx-web
#以上是前台执行不退出

5.3.4 验证docker compose执行结果

#上面命令是前台执行,所以要查看结果,可以再开一个终端窗口进行观察
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                                         COMMAND
         CREATED             STATUS              PORTS
           NAMES
d71030504f6a        harbor.wang.org/example/nginx-centos7-base:1.6.1
"/apps/nginx/sbin/ng…"15 seconds ago      Up 13 seconds (healthy)
0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   nginx-web
[root@ubuntu1804 ~]#docker-compose ps
ERROR:
        Can't find a suitable configuration file in this directory or any
        parent. Are you in the right directory?
        Supported filenames: docker-compose.yml, docker-compose.yaml
[root@ubuntu1804 ~]#cd /data/docker-compose/
[root@ubuntu1804 docker-compose]#docker-compose ps
  Name             Command           State                    Ports
---------------------------------------------------------------------------------
----
nginx-web   /apps/nginx/sbin/nginx   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp
[root@ubuntu1804 docker-compose]#curl 127.0.0.1/app/
Test Page in app
[root@ubuntu1804 docker-compose]#docker-compose images
Container                Repository                  Tag      Image Id       Size
---------------------------------------------------------------------------------
--
nginx-web   harbor.wang.org/example/nginx-centos7-base   1.6.1   ea3840c349e5
413.4 MB
[root@ubuntu1804 docker-compose]#docker-compose exec service-nginx-web bash
[root@17c17ad30193 /]#
[root@17c17ad30193 /]#
[root@17c17ad30193 /]#
[root@17c17ad30193 /]# tail -f /apps/nginx/logs/access.log
172.17.0.1 -- [04/Feb/2020:16:01:42 +0800] "GET /app/ HTTP/1.1"20017"-"
"curl/7.58.0"
10.0.0.101 -- [04/Feb/2020:16:06:29 +0800] "GET /app/ HTTP/1.1"20017"-"
"curl/7.58.0"
10.0.0.102 -- [04/Feb/2020:16:08:22 +0800] "GET /app/ HTTP/1.1"20017"-"
"curl/7.58.0"

5.3.5 结束前台执行

[root@ubuntu1804 docker-compose]#docker-compose up
Pulling service-nginx-web (10.0.0.102/example/nginx-centos7-base:1.6.1)...
1.6.1: Pulling from example/nginx-centos7-base
f34b00c7da20: Pull complete
544476d462f7: Pull complete
39345915aa1b: Pull complete
d5376f2bbd9e: Pull complete
4596aecee927: Pull complete
1617b995c379: Pull complete
d00df95be654: Pull complete
Digest: sha256:82e9e7d8bf65e160ba79a92bb25ae42cbbf791092d1e09fb7de25f91b31a21ff
Status: Downloaded newer image for10.0.0.102/example/nginx-centos7-base:1.6.1
Creating nginx-web ... done
Attaching to nginx-web
^CGracefully stopping... (press Ctrl+C again to force)  #ctrl+c键,结束容器
Stopping nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose ps
  Name             Command           State    Ports
---------------------------------------------------
nginx-web   /apps/nginx/sbin/nginx   Exit 0
[root@ubuntu1804 docker-compose]#docker ps -a
CONTAINER ID        IMAGE                                         COMMAND
         CREATED             STATUS                          PORTS
NAMES
d71030504f6a       harbor.wang.org/example/nginx-centos7-base:1.6.1
"/apps/nginx/sbin/ng…"5 minutes ago       Exited (0) About a minute ago
                nginx-web
[root@ubuntu1804 docker-compose]#docker-compose start
Starting service-nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose ps
  Name             Command           State                    Ports
---------------------------------------------------------------------------------
----
nginx-web   /apps/nginx/sbin/nginx   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp
#关闭容器
[root@ubuntu1804 docker-compose]#docker-compose kill
Killing nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose ps
  Name             Command            State     Ports
-----------------------------------------------------
nginx-web   /apps/nginx/sbin/nginx   Exit 137

5.3.6 删除容器

[root@ubuntu1804 docker-compose]#docker-compose ps
  Name             Command           State    Ports
---------------------------------------------------
nginx-web   /apps/nginx/sbin/nginx   Exit 0
#只删除停止的容器
[root@ubuntu1804 docker-compose]#docker-compose rm
Going to remove nginx-web
Are you sure? [yN] y
Removing nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose up -d
Creating nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose rm
No stopped containers
#停止并删除容器及镜像
[root@ubuntu1804 docker-compose]#docker-compose down
Stopping nginx-web ... done
Removing nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose ps
Name   Command   State   Ports
------------------------------
[root@ubuntu1804 docker-compose]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
#也会自动删除镜像
[root@ubuntu1804 docker-compose]#docker-compose  images
Container   Repository   Tag   Image Id   Size
----------------------------------------------

5.3.7 后台执行

[root@ubuntu1804 docker-compose]#docker-compose  up -d
Creating nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
  Name             Command           State                    Ports
---------------------------------------------------------------------------------
----
nginx-web   /apps/nginx/sbin/nginx   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp
[root@ubuntu1804 docker-compose]#curl 127.0.0.1/app/
Test Page in app
[root@ubuntu1804 docker-compose]#curl http://127.0.0.1/app/
Test Page in app

5.3.8 停止和启动与日志查看

[root@ubuntu1804 docker-compose]#docker-compose stop
Stopping nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
  Name             Command           State    Ports
---------------------------------------------------
nginx-web   /apps/nginx/sbin/nginx   Exit 0
[root@ubuntu1804 docker-compose]#docker-compose start
Starting service-nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
  Name             Command           State                    Ports
---------------------------------------------------------------------------------
----
nginx-web   /apps/nginx/sbin/nginx   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp
[root@ubuntu1804 docker-compose]#docker-compose  restart
Restarting nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
  Name             Command           State                    Ports
---------------------------------------------------------------------------------
----
nginx-web   /apps/nginx/sbin/nginx   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp

# 执行上面操作时,可以同时开一个终端,观察日事件

[root@ubuntu1804 docker-compose]#docker-compose events
2020-02-0415:38:13.253822 container kill
5d92e4da8679a973145e5b4db364ae8cf8596a03c4fd0b3b6a28213a2f155be6
(image=harbor.wang.org/example/nginx-centos7-base:1.6.1, name=nginx-web)
2020-02-0415:38:13.531208 container die
5d92e4da8679a973145e5b4db364ae8cf8596a03c4fd0b3b6a28213a2f155be6
(image=harbor.wang.org/example/nginx-centos7-base:1.6.1, name=nginx-web)
2020-02-0415:38:13.631137 container stop
5d92e4da8679a973145e5b4db364ae8cf8596a03c4fd0b3b6a28213a2f155be6
(image=harbor.wang.org/example/nginx-centos7-base:1.6.1, name=nginx-web)
2020-02-0415:38:15.137495 container start
5d92e4da8679a973145e5b4db364ae8cf8596a03c4fd0b3b6a28213a2f155be6
(image=harbor.wang.org/example/nginx-centos7-base:1.6.1, name=nginx-web)
2020-02-0415:38:15.137546 container restart
5d92e4da8679a973145e5b4db364ae8cf8596a03c4fd0b3b6a28213a2f155be6
(image=10.0.0.102/example/nginx-centos7-base:1.6.1, name=nginx-web)

# 以 json 格式显示日志

[root@ubuntu1804 docker-compose]#docker-compose events --json
{"time": "2020-02-04T15:48:22.423539", "type": "container", "action": "kill",
"id": "19d72e9bc85842d8879d7dcf2a3d2defd79a5a0c3c3d974ddfbbbc6e95bf910b",
"service": "service-nginx-web", "attributes": {"name": "nginx-web", "image":
"10.0.0.102/example/nginx-centos7-base:1.6.1"}}
{"time": "2020-02-04T15:48:22.537200", "type": "container", "action":
"exec_die", "id":
"19d72e9bc85842d8879d7dcf2a3d2defd79a5a0c3c3d974ddfbbbc6e95bf910b", "service":
"service-nginx-web", "attributes": {"name": "nginx-web", "image":
"10.0.0.102/example/nginx-centos7-base:1.6.1"}}
{"time": "2020-02-04T15:48:22.745670", "type": "container", "action": "die",
"id": "19d72e9bc85842d8879d7dcf2a3d2defd79a5a0c3c3d974ddfbbbc6e95bf910b",
"service": "service-nginx-web", "attributes": {"name": "nginx-web", "image":
"10.0.0.102/example/nginx-centos7-base:1.6.1"}}
{"time": "2020-02-04T15:48:22.863375", "type": "container", "action": "stop",
"id": "19d72e9bc85842d8879d7dcf2a3d2defd79a5a0c3c3d974ddfbbbc6e95bf910b",
"service": "service-nginx-web", "attributes": {"name": "nginx-web", "image":
"10.0.0.102/example/nginx-centos7-base:1.6.1"}}
{"time": "2020-02-04T15:48:23.979421", "type": "container", "action": "start",
"id": "19d72e9bc85842d8879d7dcf2a3d2defd79a5a0c3c3d974ddfbbbc6e95bf910b",
"service": "service-nginx-web", "attributes": {"name": "nginx-web", "image":
"10.0.0.102/example/nginx-centos7-base:1.6.1"}}
{"time": "2020-02-04T15:48:23.979468", "type": "container", "action": "restart",
"id": "19d72e9bc85842d8879d7dcf2a3d2defd79a5a0c3c3d974ddfbbbc6e95bf910b",
"service": "service-nginx-web", "attributes": {"name": "nginx-web", "image":
"10.0.0.102/example/nginx-centos7-base:1.6.1"}}

5.3.9 暂停和恢复

[root@ubuntu1804 docker-compose]#docker-compose  pause
Pausing nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
  Name             Command           State                     Ports
---------------------------------------------------------------------------------
-----
nginx-web   /apps/nginx/sbin/nginx   Paused   0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp
[root@ubuntu1804 docker-compose]#curl -m 1  http://127.0.0.1/app/
curl: (28) Operation timed out after 1002 milliseconds with 0 bytes received
[root@ubuntu1804 docker-compose]#docker-compose  unpause
Unpausing nginx-web ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
  Name             Command           State                    Ports
---------------------------------------------------------------------------------
----
nginx-web   /apps/nginx/sbin/nginx   Up      0.0.0.0:443->443/tcp, 0.0.0.0:80-
>80/tcp
[root@ubuntu1804 docker-compose]#curl -m 1  http://127.0.0.1/app/
Test Page in app

5.4 Docker Compose 启动多个容器

5.4.1 编辑 docker-compose 文件并使用数据卷

注意: 同一个文件 ,数据卷的优先级比镜像内的文件优先级高

[root@ubuntu1804 docker-compose]#vim docker-compose.yml
[root@ubuntu1804 docker-compose]#cat  docker-compose.yml
service-nginx-web:
  image: harbor.wang.org/example/nginx-centos7-base:1.6.1
  container_name: nginx-web
  volumes:
- /data/nginx:/apps/nginx/html/#指定数据卷,将宿主机/data/nginx挂载到容
器/apps/nginx/html
  expose:
-80
-443
  ports:
-"80:80"
-"443:443"
service-tomcat-app1:
  image: harbor.wang.org/example/tomcat-web:app1
  container_name: tomcat-app1
  expose:
-8080
  ports:
-"8081:8080"
service-tomcat-app2:
  image: harbor.wang.org/example/tomcat-web:app2
  container_name: tomcat-app2
  expose:
-8080
  ports:
-"8082:8080"
#在宿主机准备nginx测试页面文件
[root@ubuntu1804 docker-compose]#mkdir /data/nginx
[root@ubuntu1804 docker-compose]#echo Docker compose test page >
/data/nginx/index.html

5.4.2 启动容器并验证结果

[root@ubuntu1804 docker-compose]#docker-compose up -d
Pulling service-tomcat-app1 (10.0.0.102/example/tomcat-web:app1)...
app1: Pulling from example/tomcat-web
f34b00c7da20: Already exists
544476d462f7: Already exists
39345915aa1b: Already exists
4b792f2bae38: Already exists
4439447a3522: Already exists
fe34d2ec1dd0: Already exists
b8487ca03126: Already exists
5a475b7d8b1a: Already exists
df8703d3d2dd: Already exists
f0da1ffa7aa7: Pull complete
80fd4c70e670: Pull complete
c2a0247d7bfa: Pull complete
b0977ed809cd: Pull complete
Digest: sha256:e0aba904df6095ea04c594d6906101f8e5f4a6ceb0a8f9b24432c47698d0caa8
Status: Downloaded newer image for10.0.0.102/example/tomcat-web:app1
Pulling service-tomcat-app2 (10.0.0.102/example/tomcat-web:app2)...
app2: Pulling from example/tomcat-web
f34b00c7da20: Already exists
544476d462f7: Already exists
39345915aa1b: Already exists
4b792f2bae38: Already exists
4439447a3522: Already exists
fe34d2ec1dd0: Already exists
b8487ca03126: Already exists
5a475b7d8b1a: Already exists
df8703d3d2dd: Already exists
f0da1ffa7aa7: Already exists
80fd4c70e670: Already exists
1a55cb76a801: Pull complete
565ab795f82a: Pull complete
Digest: sha256:c4d6f166c3933f6c1ba59c84ea0518ed653af25f28b87981c242b0deff4209bb
Status: Downloaded newer image for10.0.0.102/example/tomcat-web:app2
Creating tomcat-app1 ... done
Creating tomcat-app2 ... done
Creating nginx-web   ... done
[root@ubuntu1804 docker-compose]#docker-compose  ps
   Name                  Command               State                    Ports
---------------------------------------------------------------------------------
--------------
nginx-web     /apps/nginx/sbin/nginx           Up      0.0.0.0:443->443/tcp,
0.0.0.0:80->80/tcp
tomcat-app1   /apps/tomcat/bin/run_tomcat.sh   Up      8009/tcp, 0.0.0.0:8081-
>8080/tcp
tomcat-app2   /apps/tomcat/bin/run_tomcat.sh   Up      8009/tcp, 0.0.0.0:8082-
>8080/tcp
[root@ubuntu1804 docker-compose]#curl http://127.0.0.1/
Docker compose test page
[root@ubuntu1804 docker-compose]#curl http://127.0.0.1:8081/app/
Tomcat Page in app1
[root@ubuntu1804 docker-compose]#curl http://127.0.0.1:8082/app/
Tomcat Page in app2

5.4.3 指定同时启动容器的数量

[root@ubuntu1804 docker-compose]#vim docker-compose.yml
[root@ubuntu1804 docker-compose]#cat docker-compose.yml
service-nginx-web:
  image: 10.0.0.102/example/nginx-centos7-base:1.6.1
#  container_name: nginx-web #同时启动多个同一镜像的容器,不要指定容器名称,否则会冲突
  expose:
-80
-443
#  ports:                    #同时启动多个同一镜像的容器,不要指定端口号,否则会冲突
#    - "80:80"
#    - "443:443"
#再加一个service
service-tomcat:
  image: 10.0.0.102/example/tomcat-base:v8.5.50
[root@ubuntu1804 docker-compose]#docker-compose  ps
Name   Command   State   Ports
------------------------------
[root@ubuntu1804 docker-compose]#docker-compose  up -d --scale service-nginx-
web=2
Creating docker-compose_service-tomcat_1 ...done
Creating docker-compose_service-nginx-web_1 ...done
Creating docker-compose_service-nginx-web_2 ...done
[root@ubuntu1804 docker-compose]#docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
-----
docker-compose_service-nginx-web_1 /apps/nginx/sbin/nginx Up443/tcp,
80/tcp
docker-compose_service-nginx-web_2 /apps/nginx/sbin/nginx Up443/tcp,
80/tcp
docker-compose_service-tomcat_1 /bin/bash Exit0
[root@ubuntu1804 docker-compose]#docker-compose up -d --scale service-nginx-
web=3 --scale service-tomcat=2
Starting docker-compose_service-tomcat_1 ...done
Starting docker-compose_service-nginx-web_1 ...done
Starting docker-compose_service-nginx-web_2 ...done
Creating docker-compose_service-nginx-web_3 ...done
Creating docker-compose_service-tomcat_2 ...done
[root@ubuntu1804 docker-compose]#docker-compose ps

Name Command State Ports
---------------------------------------------------------------------------------
-----
docker-compose_service-nginx-web_1 /apps/nginx/sbin/nginx Up443/tcp,
80/tcp
docker-compose_service-nginx-web_2 /apps/nginx/sbin/nginx Up443/tcp,
80/tcp
docker-compose_service-nginx-web_3 /apps/nginx/sbin/nginx Up443/tcp,
80/tcp
docker-compose_service-tomcat_1 /bin/bash Exit0
docker-compose_service-tomcat_2 /bin/bash Exit0
[root@ubuntu1804 docker-compose]#docker-compose up -d
Stopping and removing docker-compose_service-nginx-web_2 ...done

Stopping and removing docker-compose_service-nginx-web_3 ...done
Stopping and removing docker-compose_service-tomcat_2 ...done
Starting docker-compose_service-tomcat_1 ...done
Starting docker-compose_service-nginx-web_1 ...done

[root@ubuntu1804 docker-compose]#docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
-----
docker-compose_service-nginx-web_1 /apps/nginx/sbin/nginx Up443/tcp,
80/tcp
docker-compose_service-tomcat_1 /bin/bash Exit0

5.4.4 扩容和缩容

注意: 新版中scale 命令已废弃

#扩容
[root@ubuntu1804 docker-compose]#docker-compose scale service-nginx-web=3
#缩容为0,即删除容器
[root@ubuntu1804 docker-compose]#docker-compose scale service-nginx-web=0

5.5 实战案例: 实现 Wordpress 应用

version: '3'
services:
  db:
    image: mysql:8.0
    container_name: db
    restart: unless-stopped
    environment:
      - MYSQL_DATABASE=wordpress
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=123456
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - wordpress-network
  wordpress:
    depends_on:
      - db
    image: wordpress:5.8.3-apache
    container_name: wordpress
    restart: unless-stopped
    ports:
      - "80:80"
    environment:
      - WORDPRESS_DB_HOST=db:3306
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=123456
      - WORDPRESS_DB_NAME=wordpress
    volumes:
      - wordpress:/var/www/html
    networks:
      - wordpress-network
volumes:
  wordpress:
  dbdata:
networks:
  wordpress-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/16

5.6 实战案例: 搭建运维平台 Spug

Spug是面向中小型企业设计的轻量级无Agent的自动化运维平台,整合了主机管理、主机批量执行、主机在线终端、文件在线上传下载、应用发布部署、在线任务计划、配置中心、监控、报警等一系列功能。

Spug是上海时巴克科技有限公司旗下的开源运维项目,公司旗下现有产品「Spug开源运维平台」 「Spug推送助手」,公司专注为中小企业服务。

参考链接

https://spug.cc/docs/install-docker

范例: 基于docker-compose 部署 Spug

#安装docker和docker-compse
略
#创建docker-compse.yml文件
#vi docker-compose.yml
version: "3.9"
services:
  db:
    image: mariadb:10.8
    container_name: spug-db
    restart: always
    command: --character-set-server=utf8mb4 --collation-
server=utf8mb4_unicode_ci
    volumes:
      - /data/spug/mysql:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=spug
      - MYSQL_USER=spug
      - MYSQL_PASSWORD=spug.cc
      - MYSQL_ROOT_PASSWORD=spug.cc
  spug:
    image: openspug/spug-service
    container_name: spug
    privileged: true
    restart: always
    volumes:
      - /data/spug/service:/data/spug
      - /data/spug/repos:/data/repos
    ports:
# 如果80端口被占用可替换为其他端口,例如: - "8000:80"
      - "80:80"
    environment:
      - SPUG_DOCKER_VERSION=v3.2.1
      - MYSQL_DATABASE=spug
      - MYSQL_USER=spug
      - MYSQL_PASSWORD=spug.cc
      - MYSQL_HOST=db
      - MYSQL_PORT=3306
    depends_on:
      - db
#启动项目
#docker compose up -d
#初始化:以下操作会创建一个用户名为 admin 密码为 spug.dev 的管理员账户,可自行替换管理员账户/
密码。
docker exec spug init_spug admin spug.dev
#访问测试:在浏览器中输入 http://localhost:80 访问(默认账户密码在上面一步初始化时设置)。

5.7 案例: 一键生成 docker-compose.yml

利用网站将docker 命令自动生成 Docker Compose

https://www.composerize.com/

6 Docker 仓库管理

Docker仓库,类似于yum仓库,是用来保存镜像的仓库。为了方便的管理和使用docker镜像,可以将镜像集中保存至Docker仓库中,将制作好的镜像push到仓库集中保存,在需要镜像时,从仓库中pull镜像即可。

Docker 仓库分为公有云仓库和私有云仓库

公有云仓库: 由互联网公司对外公开的仓库

官方阿里云等第三方仓库

私有云仓库: 组织内部搭建的仓库,一般只为组织内部使用,常使用下面软件搭建仓库

docker registory docker harbor

6.1 官方 Docker 仓库

将自制的镜像上传至docker仓库;https://hub.docker.com/

6.1.1 注册账户

访问hub.docker.com注册账户,并登录

6.1.2 使用用户仓库管理镜像

每个注册用户都可以上传和管理自已的镜像

6.1.2.1 用户登录

上传镜像前需要执行docker login命令登录,登录后生成~/.docker/config.json文件保存验证信息格式

docker login [OPTIONS] [SERVER]
选项:
-p, --password string   Password
--password-stdin    Take the password from stdin
-u, --username string   Username

范例:

#登录docker官方仓库方法1
[root@ubuntu1804 ~]#docker login  -u wangxiaochun -pP@ssw0rd!  docker.io
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

#登录docker官方仓库方法2
[root@ubuntu1804 ~]#docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't
have a Docker ID, head over to https://hub.docker.com to create one.
Username: wangxiaochun
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@ubuntu1804 ~]#
#登录成功后,自动生成验证信息,下次会自动登录,而无需手动登录
[root@ubuntu1804 ~]#cat .docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "d2FuZ3hpYW9jaHVuOmxidG9vdGgwNjE4"
        }
    },
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.5 (linux)"
    }
}[root@ubuntu1804 ~]#
6.1.2.2 给本地镜像打标签

上传本地镜像前必须先给上传的镜像用docker tag 命令打标签

标签格式: docker.io/ 用户帐号 / 镜像名 :TAG

范例:

[root@ubuntu1804 ~]#docker tag alpine: 3.11 docker.io/wangxiaochun/alpine:3.11-v1
[root@ubuntu1804 ~]#docker images
REPOSITORY TAG
SIZE
IMAGE ID CREATED
haproxy-centos72.1.2
428MB
5eccdb29a0584 hours ago
nginx-ubuntu18041.16.1
378MB
19efdd23ac8718 hours ago
nginx-alpine1.16.1
211MB
978a43bbb61d19 hours ago
alpine-base3.11
182MB
b162eecf4da920 hours ago
tomcat-web app2
838MB
0e1760fe79a640 hours ago
tomcat-web app1
838MB
76016219a0ca40 hours ago
tomcat-base v8.5.50
824MB
8d5395cb72c441 hours ago
centos7-jdk 8u212
809MB
e0fe770a7ccd42 hours ago
centos7-base
403MB
v1 34ab3afcd3b343 hours ago
alpine 3.11 e7d92cdc71fe12 days ago
5.59MB
alpine latest e7d92cdc71fe12 days ago
5.59MB
wangxiaochun/alpine
5.59MB
3.11-v1 e7d92cdc71fe12 days ago
ubuntu 18.04 ccc6e87d482b2 weeks ago
64.2MB
ubuntu
64.2MB
bionic ccc6e87d482b2 weeks ago
centos
204MB
centos7.7.1908 08d05d1d58592 months ago
6.1.2.3 上传本地镜像至官网
#如tag省略,将上传指定REPOSITORY的所有版本,如下示例
#[root@ubuntu1804 ~]#docker push docker.io/wangxiaochun/alpine
[root@ubuntu1804 ~]#docker push docker.io/wangxiaochun/alpine:3.11-v1
The push refers to repository [docker.io/wangxiaochun/alpine]
5216338b40a7: Mounted from wanglinux/alpine-base
3.11-v1: digest:
sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45 size:
528
6.1.2.4 在官网验证上传的镜像

6.1.2.5 下载上传的镜像并创建容器

在另一台主机上下载镜像

[root@centos7 ~]#docker pull wangxiaochun/alpine:3.11-v1
3.11-v1: Pulling from wangxiaochun/alpine
c9b1b535fdd9: Already exists
Digest: sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45
Status: Downloaded newer image for wangxiaochun/alpine:3.11-v1
docker.io/wangxiaochun/alpine:3.11-v1
[root@centos7 ~]#docker images
REPOSITORY              TAG                 IMAGE ID            CREATED
  SIZE
wangxiaochun/alpine     3.11-v1             e7d92cdc71fe        12 days ago
5.59MB
[root@centos7 ~]#docker run -it --rm wangxiaochun/alpine:3.11-v1 sh
/ # cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
/ # du -sh /
5.6M    /
/ # exit
[root@centos7 ~]#

6.1.3 使用组织管理镜像

组织类似于名称空间,每个组织的名称全网站唯一,一个组织可以有多个用户帐户使用,并且可以指定不同用户对组织内的仓库不同的权限

三种不同权限

  • Read-only: Pull and view repository details and builds

  • Read &Write: Pull, push, and view a repository; view, cancel, retry or trigger builds

  • Admin: Pull, push, view, edit, and delete a repository; edit build settings; update the repository description

6.1.3.1 创建组织

6.1.3.2 创建组织内的团队,并分配权限

6.1.3.3 上传镜像前登录帐号
[root@ubuntu1804 ~]#docker login docker.io
Login with your Docker ID to push and pull images from Docker Hub. If you don't
have a Docker ID, head over to https://hub.docker.com to create one.
Username: wangxiaochun
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@ubuntu1804 ~]#cat .docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "d2FuZ3hpYW9jaHVuOmxidG9vdGgwNjE4"
        }
    },
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.5 (linux)"
    }
}[root@ubuntu1804 ~]#
6.1.3.4 给本地镜像打标签
[root@ubuntu1804 ~]#docker tag alpine-
base:3.11
base:3.11 docker.io/wanglinux/alpine-
[root@ubuntu1804 ~]#docker images
REPOSITORY TAG
SIZE
IMAGE ID CREATED
haproxy-centos72.1.2
428MB
5eccdb29a0584 hours ago
nginx-ubuntu18041.16.1
378MB
19efdd23ac8718 hours ago
nginx-alpine1.16.1
211MB
978a43bbb61d19 hours ago
alpine-base3.11
182MB
b162eecf4da920 hours ago
wanglinux/alpine-base 3.11 b162eecf4da920 hours ago
182MB
tomcat-web
838MB
app2 0e1760fe79a640 hours ago
tomcat-web
838MB
app1 76016219a0ca40 hours ago
tomcat-base
824MB
v8.5.50 8d5395cb72c441 hours ago
centos7-jdk
809MB
8u212 e0fe770a7ccd42 hours ago
centos7-base
403MB
v1 34ab3afcd3b343 hours ago
alpine
5.59MB
3.11 e7d92cdc71fe12 days ago
alpine
5.59MB
latest e7d92cdc71fe12 days ago
wangxiaochun/alpine
5.59MB
3.11-v1 e7d92cdc71fe12 days ago
ubuntu
64.2MB
18.04 ccc6e87d482b2 weeks ago
ubuntu
64.2MB
bionic ccc6e87d482b2 weeks ago
centos
204MB
centos7.7.1908 08d05d1d58592 months ago
6.1.3.5 上传镜像到指定的组织
[root@ubuntu1804 ~]#docker push docker.io/wanglinux/alpine-base:3.11
The push refers to repository [docker.io/wanglinux/alpine-base]
1783f0912dfb: Pushed
1e5e8d5ab333: Pushed
5216338b40a7: Mounted from library/alpine
3.11: digest:
sha256:7931fed46d377698dacb194d46017c53bc24f2e9ee41e893e6900c07d1153536 size:
947
6.1.3.6 在网站看查看上传的镜像

6.1.3.7 下载上传的镜像并运行容器

在另一台主机上下载镜像

[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@centos7 ~]#docker pull wanglinux/alpine-base:3.11
3.11: Pulling from wanglinux/alpine-base
c9b1b535fdd9: Pull complete
327af1e87fd8: Pull complete
d88818b49372: Pull complete
Digest: sha256:7931fed46d377698dacb194d46017c53bc24f2e9ee41e893e6900c07d1153536
Status: Downloaded newer image for wanglinux/alpine-base:3.11
docker.io/wanglinux/alpine-base:3.11
[root@centos7 ~]#docker images
REPOSITORY              TAG                 IMAGE ID            CREATED
  SIZE
wanglinux/alpine-base   3.11                b162eecf4da9        20 hours ago
   182MB
[root@centos7 ~]#docker run -it --rm wanglinux/alpine-base:3.11 sh
/ # cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
/ # du -sh /
190.1M  /
/ # exit
[root@centos7 ~]#

6.2 阿里云 Docker 仓库

6.2.1 注册和登录阿里云仓库

用浏览器访问http://cr.console.aliyun.com,输入注册的用户信息登录网站

6.2.2 设置仓库专用管理密码

6.2.3 创建仓库

此步可不事先执行,docker push 时可以自动创建私有仓库

查看仓库的路径用于上传镜像使用

6.2.4 上传镜像前先登录阿里云

#用前面设置的专用仓库管理密码登录
[root@ubuntu1804 ~]#docker login --username=29308620@qq.com registry.cn-
beijing.aliyuncs.com
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#登录密码保存在~/.docker/config.json文件中,下次将不会需要再输入密码登录
[root@ubuntu1804 ~]#cat .docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "d2FuZ3hpYW9jaHVuOmxidG9vdGgwNjE4"
        },
"registry.cn-beijing.aliyuncs.com": {
"auth": "MjkzMDg2MjBAcXEuY29tOmxidG9vdGgwNjE4"
        }
    },
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.5 (linux)"
    }
}[root@ubuntu1804 ~]#

6.2.5 给上传的镜像打标签

[root@ubuntu1804 ~]#docker tag alpin e-base:3.11 registry.cn-
beijing.aliyuncs. com/wangxiaochun/al pine:3.11-v1
[root@ubuntu1804 ~]#docker tag cento s7-base:v1 registry.cn-
beijing.aliyuncs. com/wangxiaochun/ce ntos7-base:v1
[root@ubuntu1804 ~]#docker images
REPOSITORY TAG
IMAGE ID CREATED SIZE
haproxy-centos7 2.1.2
5eccdb29a058 6 hours ago 428MB
nginx-ubuntu1804 1.16.1
19efdd23ac87 21 hours ago 378MB
nginx-alpine 1.16.1
978a43bbb61d 22 hours ago 211MB
alpine-base 3.11
b162eecf4da9 23 hours ago 182MB
wanglinux/alpine- base 3.11
b162eecf4da9 23 hours ago 182MB
registry.cn-beiji ng.aliyuncs.com/wan gxiaochun/alpine3.11-v1
b162eecf4da9 23 hours ago 182MB
tomcat-web app2
0e1760fe79a6 43 hours ago 838MB
tomcat-web app1
76016219a0ca 43 hours ago 838MB
tomcat-base v8.5.50
8d5395cb72c4 44 hours ago 824MB
centos7-jdk 8u212
e0fe770a7ccd 45 hours ago 809MB
centos7-base v1
34ab3afcd3b3 46 hours ago 403MB
registry.cn-beiji ng.aliyuncs.com/wan gxiaochun/centos7-base v1
34ab3afcd3b3 46 hours ago 403MB
alpine 3.11
e7d92cdc71fe 12 days ago 5.59MB
alpine latest
e7d92cdc71fe 12 days ago 5.59MB
wangxiaochun/alpi ne 3.11-v1
e7d92cdc71fe 12 days ago 5.59MB
ubuntu 18.04
ccc6e87d482b 2 weeks ago 64.2MB
ubuntu bionic
ccc6e87d482b 2 weeks ago 64.2MB
centos centos7.7.1908
08d05d1d5859 2 months ago 204MB

6.2.6 上传镜像至阿里云

[root@ubuntu1804 ~]# docker push registry.cn-
beijing.aliyuncs.com/wangxiaochun/alpine:3.11-v1
The push refers to repository [registry.cn-
beijing.aliyuncs.com/wangxiaochun/alpine]
1783f0912dfb: Pushed
1e5e8d5ab333: Pushed
5216338b40a7: Pushed
3.11-v1: digest:
sha256:7931fed46d377698dacb194d46017c53bc24f2e9ee41e893e6900c07d1153536 size:
947
[root@ubuntu1804 ~]#docker push registry.cn-
beijing.aliyuncs.com/wangxiaochun/centos7-base:v1
The push refers to repository [registry.cn-
beijing.aliyuncs.com/wangxiaochun/centos7-base]
2073413aebd6: Pushed
6ec9af97c369: Pushed
034f282942cd: Pushed
v1: digest:
sha256:02cd943f2569c7c55f08a979fd9661f1fd7893c424bca7b343188654ba63d98d size:
949

6.2.7 在网站查看上传的镜像

6.2.8 从另一台主机上下载刚上传的镜像并运行容器

[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@centos7 ~]# docker pull registry.cn-
beijing.aliyuncs.com/wangxiaochun/alpine:3.11-v1
3.11-v1: Pulling from wangxiaochun/alpine
c9b1b535fdd9: Pull complete
327af1e87fd8: Pull complete
d88818b49372: Pull complete
Digest: sha256:7931fed46d377698dacb194d46017c53bc24f2e9ee41e893e6900c07d1153536
Status: Downloaded newer image for registry.cn-
beijing.aliyuncs.com/wangxiaochun/alpine:3.11-v1
registry.cn-beijing.aliyuncs.com/wangxiaochun/alpine:3.11-v1
[root@centos7 ~]#docker images
REPOSITORY                                             TAG                 IMAGE
ID            CREATED             SIZE
registry.cn-beijing.aliyuncs.com/wangxiaochun/alpine   3.11-v1
b162eecf4da9        22 hours ago        182MB
[root@centos7 ~]#docker run -it --rm b162eecf4da9 sh
/ # cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
/ # du -sh /
190.1M  /
/ # exit
[root@centos7 ~]#docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
[root@centos7 ~]#
#上传的centos7-base:v1为私有镜像,需要登录才能下载
[root@centos7 ~]#docker pull registry.cn-
beijing.aliyuncs.com/wangxiaochun/centos7-base:v1
Error response from daemon: pull access denied for registry.cn-
beijing.aliyuncs.com/wangxiaochun/centos7-base, repository does not exist or may
require 'docker login': denied: requested access to the resource is denied
[root@centos7 ~]#docker login registry.cn-beijing.aliyuncs.com
Username: lbtooth
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@centos7 ~]#cat .docker/config.json
{
"auths": {
"registry.cn-beijing.aliyuncs.com": {
"auth": "bGJ0b290aDpsYnRvb3RoMDYxOA=="
        }
    },
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.5 (linux)"
    }
}[root@centos7 ~]#
[root@centos7 ~]#docker pull registry.cn-
beijing.aliyuncs.com/wangxiaochun/centos7-base:v1
v1: Pulling from wangxiaochun/centos7-base
f34b00c7da20: Pull complete
544476d462f7: Pull complete
39345915aa1b: Pull complete
Digest: sha256:02cd943f2569c7c55f08a979fd9661f1fd7893c424bca7b343188654ba63d98d
Status: Downloaded newer image for registry.cn-
beijing.aliyuncs.com/wangxiaochun/centos7-base:v1
registry.cn-beijing.aliyuncs.com/wangxiaochun/centos7-base:v1
[root@centos7 ~]#docker images
REPOSITORY                                                   TAG
IMAGE ID            CREATED             SIZE
registry.cn-beijing.aliyuncs.com/wangxiaochun/alpine         3.11-v1
b162eecf4da9        23 hours ago        182MB
registry.cn-beijing.aliyuncs.com/wangxiaochun/centos7-base   v1
34ab3afcd3b3        46 hours ago        403MB
[root@centos7 ~]#

6.3 私有云单机仓库 Docker Registry

6.3.1 Docker Registry 介绍

Docker Registry作为Docker的核心组件之一负责单主机的镜像内容的存储与分发,客户端的docker pull以及push命令都将直接与registry进行交互,最初版本的registry 由Python实现,由于设计初期在安全性,性能以及API的设计上有着诸多的缺陷,该版本在0.9之后停止了开发,由新项目distribution(新的docker register被称为Distribution)来重新设计并开发下一代registry,新的项目由go语言开发,所有的API,底层存储方式,系统架构都进行了全面的重新设计已解决上一代registry中存在的问题,2016 年4月份registry 2.0正式发布,docker 1.6版本开始支持registry 2.0,而八月份随着docker 1.8 发布, docker hub正式启用2.1版本registry全面替代之前版本 registry,新版registry对镜像存储格式进行了重新设计并和旧版不兼容,docker 1.5和之前的版本无法读取2.0的镜像,另外,Registry 2.4版本之后支持了回收站机制,也就是可以删除镜像了,在2.4版本之前是无法支持删除镜像的,所以如果你要使用最好是大于Registry 2.4版本的

官方文档地址: https://docs.docker.com/registry/

官方github 地址: https://github.com/docker/distribution

官方部署文档: https://github.com/docker/docker.github.io/blob/master/registry/deploying.md

以下介绍通过官方提供的docker registry 镜像来简单搭建本地私有仓库环境

环境: 三台主机

10.0.0.100: 充当registry仓库服务器 10.0.0.101: 上传镜像 10.0.0.102: 下载镜像

6.3.2 下载 Docker Registry 镜像

[root@ubuntu1804 ~]#docker pull registry:2.7.1
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
registry            2.7.1               708bc6af7e5e        6 days ago
25.8MB

6.3.3 搭建单机仓库

6.3.2.1 创建授权用户密码使用目录
[root@ubuntu1804 ~]#mkdir -p  /etc/docker/auth
6.3.2.2 创建授权的registry用户和密码

创建registry用户,用于上传和下载镜像

[root@ubuntu1804 ~]#apt -y install apache2-utils
[root@ubuntu1804 ~]#htpasswd -Bbn wang 123456 > /etc/docker/auth/registry
[root@ubuntu1804 ~]#cat /etc/docker/auth/registry
wang:$2y$05$nlRIIYEUBTSLdN2PkzodUue4ry7X/UyscpkkEufTDhEdI8nsyJMR6
#旧版本可以按下面方法生成用户和密码文件
[root@ubuntu1804 ~]#docker run --entrypoint htpasswd registry:2.7.1 -Bbn wang
123456 > /etc/docker/auth/registry

6.3.2.3 启动docker registry 容器

[root@ubuntu1804 ~]# docker run -d -p 5000:5000 --restart=always --name registry
-v /etc/docker/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e
REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry registry:2.7.1
998f970dd8ca6b98002f20ae27330fe607ca78f35bedcc8a6180688e48a907a7
6.3.2.4 验证端口和容器
[root@ubuntu1804 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
998f970dd8ca registry:2.7.1"/entrypoint.sh /etc…" About a minute
ago Up About a minute0.0.0.0:5000->5000/tcp registry
[root@ubuntu1804 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN0 640.0.0.0:20490.0.0.0:*
LISTEN0 1280.0.0.0:481310.0.0.0:*
LISTEN0 1280.0.0.0:338350.0.0.0:*
LISTEN0 1280.0.0.0:580290.0.0.0:*
LISTEN0 1280.0.0.0:1110.0.0.0:*
LISTEN0 128127.0.0.53%lo:530.0.0.0:*
LISTEN0 1280.0.0.0:220.0.0.0:*
LISTEN0 640.0.0.0:464290.0.0.0:*
LISTEN0 128127.0.0.1:60140.0.0.0:*
LISTEN0 64 [::]:2049 [::]:*
LISTEN0 128 *:5000 *:*
LISTEN0 128 [::]:39471 [::]:*
LISTEN0 128 [::]:111 [::]:*
LISTEN0 64 [::]:43601 [::]:*
LISTEN0 128 [::]:56725 [::]:*
LISTEN0 128 [::]:22 [::]:*
LISTEN0 128 [::]:57881 [::]:*
LISTEN0 128 [::1]:6014 [::]:*

6.3.4 登录仓库

6.3.4.1 直接登录报错
#docker login 默认使用 https 登录,而docker registry为http,所以默认登录失败
[root@ubuntu1804 ~]#docker login 10.0.0.100:500
Username: wang
Password:
Error response from daemon: Get https://10.0.0.100:5000/v2/: dial tcp
10.0.0.100:5000: connect: connection refused
6.3.4.2 将registry仓库服务器地址加入service 单元文件

官方文档:

https://docs.docker.com/registry/insecure/

范例:

#修改配置让docker login支持http协议
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
[root@ubuntu1804 ~]#grep ExecStart /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry10.0.0.100:5000
#或者修改下面文件
[root@ubuntu1804 ~]#vim  /etc/docker/daemon.json
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries": ["10.0.0.100:5000"]
}
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#ps aux|grep dockerd
root       20921.3  8.4 75708883056 ?        Ssl  19:19   0:00
/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --
insecure-registry10.0.0.100:5000
root       22330.0  0.1  144281012 pts/0    S+19:20   0:00 grep--
color=auto dockerd
6.3.4.3 再次登录验证成功

在10.0.0.101主机上执行下面登录

[root@ubuntu1804 ~]#docker login 10.0.0.100:5000
Username: wang
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@ubuntu1804 ~]#

6.3.5 打标签并上传镜像

在10.0.0.101主机上执行打标签上传

[root@ubuntu1804 ~]#docker tag centos7-base:v1 10.0.0.100:5000/centos7-base:v1
[root@ubuntu1804 ~]#docker push 10.0.0.100:5000/centos7-base:v1
The push refers to repository [10.0.0.100:5000/centos7-base]
2073413aebd6: Pushed
6ec9af97c369: Pushed
034f282942cd: Pushed
v1: digest:
sha256:02cd943f2569c7c55f08a979fd9661f1fd7893c424bca7b343188654ba63d98d size:
949

6.3.6 下载镜像并启动容器

在10.0.0.102主机上下载镜像并启动容器

6.3.6.1 先修改docker的service 文件
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
[root@ubuntu1804 ~]#grep ExecStart /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry10.0.0.100:5000
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
6.3.6.2 登录registry仓库服务器
[root@ubuntu1804 ~]#docker login 10.0.0.100:5000
Username: wang
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
6.3.6.3 下载镜像并启动容器
[root@ubuntu1804 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@ubuntu1804 ~]#docker pull  10.0.0.100:5000/centos7-base:v1
v1: Pulling from centos7-base
f34b00c7da20: Pull complete
544476d462f7: Pull complete
39345915aa1b: Pull complete
Digest: sha256:02cd943f2569c7c55f08a979fd9661f1fd7893c424bca7b343188654ba63d98d
Status: Downloaded newer image for10.0.0.100:5000/centos7-base:v1
10.0.0.100:5000/centos7-base:v1
[root@ubuntu1804 ~]#docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED
          SIZE
10.0.0.100:5000/centos7-base   v1                  34ab3afcd3b3        2 days
ago          403MB
[root@ubuntu1804 ~]#docker run -it --rm  34ab3afcd3b3 bash
[root@2bcb26b1b568 /]# cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
[root@2bcb26b1b568 /]# exit
exit
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
STATUS              PORTS               NAMES
[root@ubuntu1804 ~]#

6.4 Docker 之分布式仓库 Harbor

6.4.1 Harbor 介绍和架构

6.4.1.1 Harbor 介绍

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,由VMware开源,其通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源 Docker Distribution。作为一个企业级私有Registry服务器,Harbor 提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有 Registry 中, 确保数据和知识产权在公司内部网络中管控,另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等

vmware 官方开源服务: https://vmware.github.io/

harbor 官方github 地址: https://github.com/vmware/harbor harbor 官方网址: https://goharbor.io/ harbor 官方文档: https://goharbor.io/docs/

github文档: https://github.com/goharbor/harbor/tree/master/docs

6.4.1.2 Harbor功能官方介绍

基于角色的访问控制: 用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限

  • 镜像复制: 镜像可在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景

图形化用户界面: 用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间 AD/LDAP 支: Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理审计管理: 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理

国际化: 已拥有中文、英文、德文、日文和俄文的本地化版本。更多的语言将会添加进来

RESTful API: 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易部署简单: 提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备

6.4.1.3 Harbor 组成

#harbor是由很多容器组成实现完整功能
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE                                    COMMAND
     CREATED              STATUS                        PORTS
                                         NAMES
4ec3c3885407        goharbor/nginx-photon:v1.7.6             "nginx -g 'daemon
of…"   About a minute ago   Up About a minute (healthy)   0.0.0.0:80->80/tcp,
0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp   nginx
5707b4ac41d8        goharbor/harbor-portal:v1.7.6            "nginx -g 'daemon
of…"   About a minute ago   Up About a minute (healthy)   80/tcp
                                            harbor-portal
0ed230b9b714        goharbor/harbor-jobservice:v1.7.6        "/harbor/start.sh"
      About a minute ago   Up About a minute
                                           harbor-jobservice
fec659188349        goharbor/harbor-core:v1.7.6              "/harbor/start.sh"
      About a minute ago   Up About a minute (healthy)
                                           harbor-core
910d14c1d7f7        goharbor/harbor-adminserver:v1.7.6       "/harbor/start.sh"
2 minutes ago        Up About a minute (healthy)
                                           harbor-adminserver
4348f503aa0e        goharbor/harbor-db:v1.7.6                "/entrypoint.sh
post…"2 minutes ago        Up About a minute (healthy)   5432/tcp
                                              harbor-db
beff6886f0f1        goharbor/harbor-registryctl:v1.7.6       "/harbor/start.sh"
2 minutes ago        Up About a minute (healthy)
                                           registryctl
428c99d274bf        goharbor/registry-photon:v2.6.2-v1.7.6   "/entrypoint.sh
/etc…"2 minutes ago        Up About a minute (healthy)   5000/tcp
                                              registry
775b4026fa4e        goharbor/redis-photon:v1.7.6             "docker-
entrypoint.s…"2 minutes ago        Up About a minute             6379/tcp
                                                      redis
c6f44e2034c6        goharbor/harbor-log:v1.7.6               "/bin/sh -c
/usr/loc…"2 minutes ago        Up 2 minutes (healthy)
  • Proxy: 对应启动组件nginx。它是一个nginx反向代理,代理Notary client(镜像认证)、Docker client(镜像上传下载等)和浏览器的访问请求(Core Service)给后端的各服务

  • UI(Core Service): 对应启动组件harbor-ui。底层数据存储使用mysql数据库,主要提供了四个子功能:

UI: 一个web管理页面ui

  • API: Harbor暴露的API服务

  • Auth: 用户认证服务,decode后的token中的用户信息在这里进行认证;auth后端可以接 db、ldap、uaa三种认证实现

  • Token服务(上图中未体现): 负责根据用户在每个project中的role来为每一个docker push/pull命令发布一个token,如果从docker client发送给registry的请求没有带token, registry会重定向请求到token服务创建token

  • Registry: 对应启动组件registry。负责存储镜像文件,和处理镜像的pull/push命令。Harbor对镜像进行强制的访问控制,Registry会将客户端的每个pull、push请求转发到token服务来获取有效的token

  • Admin Service: 对应启动组件harbor-adminserver。是系统的配置管理中心附带检查存储用量, ui和jobserver启动时候需要加载adminserver的配置

  • Job Sevice: 对应启动组件harbor-jobservice。负责镜像复制工作的,他和registry通信,从一个 registry pull镜像然后push到另一个registry,并记录job_log

  • Log Collector: 对应启动组件harbor-log。日志汇总组件,通过docker的log-driver把日志汇总到一起

  • DB: 对应启动组件harbor-db,负责存储project、 user、 role、replication、image_scan、 access等的metadata数据

6.4.2 安装 Harbor

下载地址: https://github.com/vmware/harbor/releases

安装文档:

https://goharbor.io/docs/2.6.0/install-config/
https://github.com/goharbor/harbor/blob/master/docs/install-config/_index.md

安装要求

https://goharbor.io/docs/2.6.0/install-config/installation-prereqs/

环境准备: 共四台主机

两台主机harbor服务器,地址: 10.0.0.101|102 两台主机harbor客户端上传和下载镜像

6.4.2.1 安装 Docker
[root@ubuntu1804 ~]#cat install_docker_for_ubuntu1804.sh
COLOR="echo -e \\033[1;31m"
END="\033[m"
DOCKER_VERSION="5:19.03.5~3-0~ubuntu-bionic"
install_docker(){
apt update
apt  -y install apt-transport-https ca-certificates curl software-properties-
common
curl-fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key
add -
add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-
ce/linux/ubuntu $(lsb_release -cs) stable"
apt update
${COLOR}"Docker有以下版本"${END}
apt-cache madison docker-ce
${COLOR}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep5
apt -y  install docker-ce=${DOCKER_VERSION}docker-ce-cli=${DOCKER_VERSION}
mkdir-p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl enable --now docker
docker version && ${COLOR}"Docker 安装成功"${END} ||  ${COLOR}"Docker 安装失
败"${END}
}
dpkg -s docker-ce &> /dev/null && ${COLOR}"Docker已安装"${END} || install_docker
[root@ubuntu1804 ~]#bash install_docker_for_ubuntu1804.sh
[root@ubuntu1804 ~]#docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 1307:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 1307:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
6.4.2.2 先安装docker compose
#docker compose 必须先于harbor安装,否则会报以下错误
[root@ubuntu1804 ~]#/apps/harbor/install.sh
[Step 0]: checking installation environment ...

Note: docker version: 19.03.5 ✖ Need to install docker-compose(1.7.1+) by yourself first and run this script again [root@ubuntu1804 ~]#

安装docker compose

#方法1:  通过pip安装,版本较新docker_compose-1.25.3,推荐使用
[root@ubuntu1804 ~]#apt -y install python-pip
[root@ubuntu1804 ~]#pip install docker-compose
[root@ubuntu1804 ~]#docker-compose --version
docker-compose version 1.25.3, build unknown
#方法2:  直接从github下载安装对应版本
#参看说明:  https://github.com/docker/compose/releases
curl-L https://github.com/docker/compose/releases/download/1.25.3/docker-
compose-`uname -s`-`uname -m`-o /usr/bin/docker-compose
chmod+x /usr/bin/docker-compose
#方法3:  直接安装,版本较旧docker-compose-1.17.1-2,不推荐使用
[root@ubuntu1804 ~]#apt -y install docker-compose
[root@ubuntu1804 ~]#docker-compose --version
docker-compose version 1.17.1, build unknown
6.4.2.3 下载 Harbor 安装包并解压缩

以下使用 harbor 稳定版本1.7.6 安装包

方法1: 下载离线完整安装包,推荐使用

[root@ubuntu1804 ~]#wget https://storage.googleapis.com/harbor-releases/release-
1.7.0/harbor-offline-installer-v1.7.6.tgz
[root@ubuntu1804 ~]#wget
https://github.com/goharbor/harbor/releases/download/v2.5.2/harbor-offline-
installer-v2.5.2.tgz

方法2: 下载在线安装包 ,比较慢,不是很推荐

[root@ubuntu1804 ~]#wget https://storage.googleapis.com/harbor-releases/release-
1.7.0/harbor-online-installer-v1.7.6.tgz
[root@ubuntu1804 ~]#ls -lh harbor-o*
-rw-r--r--1 root root 568M Sep 1813:24 harbor-offline-installer-v1.7.6.tgz
-rw-r--r--1 root root 275K Sep 1813:37 harbor-online-installer-v1.7.6.tgz

解压缩离线包

[root@ubuntu1804 ~]#mkdir /apps
[root@ubuntu1804 ~]#tar xvf harbor-offline-installer-v1.7.6.tgz  -C /apps/
6.4.2.4 编辑 harbor 配置文件

最新文档: https://github.com/goharbor/harbor/blob/master/docs/install-config/configure-yml-file. md

#新版配置文件为yml格式
[root@ubuntu2004~]#mv /apps/harbor/harbor.yml.tmpl /apps/harbor/harbor.yml
[root@ubuntu2004 ~]#vim /apps/harbor/harbor.yml
#旧版配置文件为文本格式
[root@ubuntu1804 ~]#vim /apps/harbor/harbor.cfg
#只需要修改下面两行
hostname =10.0.0.101  #修改此行,指向当前主机IP 或 FQDN,建议配置IP
harbor_admin_password =123456#修改此行指定harbor登录用户admin的密码,默认用户/密
码:admin/Harbor12345

# 可选项

data_volume: /data/harbor  #指定存放数据的目录,建议放在独立的大容量快速磁盘或存储上
ui_url_protocol = http #默认即可,如果修改为https,需要指定下面证书路径
ssl_cert = /data/cert/server.crt #默认即可,https时,需指定下面证书文件路径
ss_cert_key = /data/cert/server.key   #默认即可,https时,需指定下面私钥文件路径

6.4.2.5 运行 harbor 安装脚本
#先安装python
root@ubuntu1804 ~]#apt -y install python
#安装docker harbor
root@ubuntu1804 ~]#/apps/harbor/install.sh
[Step 0]: checking installation environment ...
Note: docker version: 19.03.5
Note: docker-compose version: 1.25.3
[Step 1]: loading Harbor images ...
......
[Step 4]: starting Harbor ...
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating registryctl        ... done
Creating harbor-db          ... done
Creating redis              ... done
Creating registry           ... done
Creating harbor-adminserver ... done
Creating harbor-core        ... done
Creating harbor-jobservice  ... done
Creating harbor-portal      ... done
Creating nginx              ... done

✔ ----Harbor has been installed and started successfully.----

Now you should be able to visit the admin portal at http://10.0.0.101.
For more details, please visit https://github.com/goharbor/harbor .
#安装harbor后会自动开启很多相关容器
[root@ubuntu1804 ~]#docker ps
CONTAINER ID        IMAGE                                    COMMAND
     CREATED             STATUS                    PORTS
                                     NAMES
1b47a3eeedd2        goharbor/nginx-photon:v1.7.6             "nginx -g 'daemon
of…"14 minutes ago      Up 14 minutes (healthy)   0.0.0.0:80->80/tcp,
0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp   nginx
5f3a0a0db734        goharbor/harbor-portal:v1.7.6            "nginx -g 'daemon
of…"14 minutes ago      Up 14 minutes (healthy)   80/tcp
                                        harbor-portal
8e4265efe8ee        goharbor/harbor-jobservice:v1.7.6        "/harbor/start.sh"
14 minutes ago      Up 14 minutes
                                       harbor-jobservice
d1a048525d79        goharbor/harbor-core:v1.7.6              "/harbor/start.sh"
14 minutes ago      Up 14 minutes (healthy)
                                       harbor-core
4a989eb92af1        goharbor/harbor-adminserver:v1.7.6       "/harbor/start.sh"
14 minutes ago      Up 14 minutes (healthy)
                                       harbor-adminserver
c875d3959c56        goharbor/registry-photon:v2.6.2-v1.7.6   "/entrypoint.sh
/etc…"14 minutes ago      Up 14 minutes (healthy)   5000/tcp
                                          registry
2a963125a0e6        goharbor/redis-photon:v1.7.6             "docker-
entrypoint.s…"14 minutes ago      Up 14 minutes             6379/tcp
                                                  redis
a0751df44d68        goharbor/harbor-registryctl:v1.7.6       "/harbor/start.sh"
14 minutes ago      Up 14 minutes (healthy)
                                       registryctl
b0ef6ed0d46b        goharbor/harbor-db:v1.7.6                "/entrypoint.sh
post…"14 minutes ago      Up 14 minutes (healthy)   5432/tcp
                                          harbor-db
8e667c6ccbc1        goharbor/harbor-log:v1.7.6               "/bin/sh -c
/usr/loc…"14 minutes ago      Up 14 minutes (healthy)   127.0.0.1:1514-
>10514/tcp                                          harbor-log
[root@ubuntu1804 ~]#
6.4.2.5 实现开机自动启动 harbor
6.4.2.5.1 方法1: 通过service文件实现
[root@harbor ~]#vim /lib/systemd/system/harbor.service
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f  /apps/harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f /apps/harbor/docker-compose.yml down
[Install]
WantedBy=multi-user.target
[root@harbor ~]#systemctl daemon-reload
[root@harbor ~]#systemctl enable harbor
6.4.2.5.2 方法2: 通过 rc.local实现
[root@harbor ~]#cat /etc/rc.local
#!/bin/bash
cd /apps/harbor
/usr/bin/docker-compose up
[root@harbor ~]#chmod +x /etc/rc.local
6.4.2.6 登录 harbor 主机网站

用浏览器访问: http://10.0.0.101/

用户名: admin 密码: 即前面harbor.cfg中指定的密码

6.4.2.7 实战案例: 一键安装Harbor脚本

6.4.2.7.1 安装 harbor 1.7.6

[root@ubuntu1804 ~]#cat install_harbor_for_ubuntu1804.sh
#!/bin/bash
#Description: Install harbor on ubuntu1804
#Author: wangxiaochun
COLOR="echo -e \E[1;31m"
END="\E[m"
DOCKER_VERSION="5:19.03.5~3-0~ubuntu-bionic"
HARBOR_VERSION=1.7.6
IPADDR=`hostname -I|awk '{print $1}'`
HARBOR_ADMIN_PASSWORD=123456
install_docker(){
${COLOR}"开始安装 Docker....."${END}
sleep1
apt update
apt  -y install apt-transport-https ca-certificates curl software-properties-
common
curl-fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg |
sudo apt-key add -
add-apt-repository "deb [arch=amd64]
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs)
stable"
apt update
${COLOR}"Docker有以下版本:"${END}
sleep2
apt-cache madison docker-ce
${COLOR}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep5
apt -y  install docker-ce=${DOCKER_VERSION}docker-ce-cli=${DOCKER_VERSION}
mkdir-p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
docker version && ${COLOR}"Docker 安装完成"${END} ||  ${COLOR}"Docker 安装失
败"${END}
}
install_docker_compose(){
${COLOR}"开始安装 Docker compose....."${END}
sleep1
curl-L https://github.com/docker/compose/releases/download/1.25.3/docker-
compose-`uname -s`-`uname -m`-o /usr/bin/docker-compose
chmod+x /usr/bin/docker-compose
docker-compose --version &&  ${COLOR}"Docker Compose 安装完成"${END} ||
${COLOR}"Docker compose 安装失败"${END}
}
install_harbor(){
${COLOR}"开始安装 Harbor....."${END}
sleep1
wget https://storage.googleapis.com/harbor-releases/release-1.7.0/harbor-offline-
installer-v${HARBOR_VERSION}.tgz
mkdir /apps
tar xvf harbor-offline-installer-v${HARBOR_VERSION}.tgz  -C /apps/
sed-i.bak -e's/^hostname =.*/hostname = '$IPADDR'/'-e
's/^harbor_admin_password =.*/harbor_admin_password = '$HARBOR_ADMIN_PASSWORD'/'
/apps/harbor/harbor.cfg
apt -y install python
/apps/harbor/install.sh && ${COLOR}"Harbor 安装完成"${END} ||  ${COLOR}"Harbor 安装
失败"${END}
}
harbor_service (){
cat > /lib/systemd/system/harbor.service <<EOF
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f  /apps/harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f /apps/harbor/docker-compose.yml down
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable  harbor &>/dev/null ||  ${COLOR}"Harbor已配置为开机自动启动"${END}
}
dpkg -s docker-ce &> /dev/null && ${COLOR}"Docker已安装"${END} || install_docker
docker-compose --version &> /dev/null && ${COLOR}"Docker Compose已安装"${END} ||
install_docker_compose
install_harbor
harbor_service

6.4.2.7.2 安装 harbor 1.10.4

[root@ubuntu1804 ~]#cat install_harbor1.10.4_for_ubuntu1804.sh
#!/bin/bash
#
#********************************************************************
#Author:            zhanghui
#QQ:                19661891
#Date:              2021-01-18
#FileName:          install_harbor1.10.4_for_ubuntu1804.sh
#URL:               www.neteagles.cn
#Description:       The test script
#Copyright (C):     2021 All rights reserved
#********************************************************************
COLOR="echo -e \\033[1;31m"
END="\033[m"
DOCKER_VERSION="5:19.03.14~3-0~ubuntu-bionic"
IPADDR=`hostname -I|awk '{print $1}'`
HARBOR_ADMIN_PASSWORD=123456
DOCKER_COMPOSE_VERSION=1.27.4
HARBOR_VERSION=1.10.4
install_docker(){
dpkg -s docker-ce &> /dev/null && ${COLOR}"Docker已安装,退出"${END} && exit
apt update
apt-get -y install apt-transport-https ca-certificates curl software-properties-
common
curl-fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg |
sudo apt-key add -
add-apt-repository "deb [arch=amd64]
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs)
stable"
apt update
${COLOR}"Docker有以下版本"${END}
apt-cache madison docker-ce
${COLOR}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep5
apt -y install docker-ce=${DOCKER_VERSION}docker-ce-cli=${DOCKER_VERSION}
mkdir-p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://hzw5xiv7.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl enable --now docker
docker version && ${COLOR}"Docker 安装成功"${END} || ${COLOR}"Docker 安装失
败"${END}
}
install_docker_compose(){
${COLOR}"开始安装 Docker compose....."${END}
sleep1
mv /root/docker-compose-Linux-x86_64-${DOCKER_COMPOSE_VERSION} /usr/bin/docker-
compose
chmod+x /usr/bin/docker-compose
docker-compose --version &&  ${COLOR}"Docker Compose 安装完成"${END} ||
${COLOR}"Docker compose 安装失败"${END}
}
install_harbor(){
${COLOR}"开始安装 Harbor....."${END}
sleep1
ls /apps &> /dev/null || mkdir /apps
tar -xvf /root/harbor-offline-installer-v${HARBOR_VERSION}.tgz -C /apps/
sed-i.bak -e's/^hostname: .*/hostname: '''$IPADDR'''/'-e
's/^harbor_admin_password: .*/harbor_admin_password:
'''$HARBOR_ADMIN_PASSWORD'''/'-e's/^https:/#https:/'-e's/  port: 443/
#port: 443/'-e's@  certificate: /your/certificate/path@  #certificate:
/your/certificate/path@'-e's@  private_key: /your/private/key/path@
#private_key: /your/private/key/path@' /apps/harbor/harbor.yml
apt -y install python
/apps/harbor/install.sh && ${COLOR}"Harbor 安装完成"${END} ||  ${COLOR}"Harbor 安装
失败"${END}
}
harbor_service (){
cat > /lib/systemd/system/harbor.service <<EOF
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f /apps/harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f /apps/harbor/docker-compose.yml down
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable harbor &>/dev/null && ${COLOR}"Harbor已配置为开机自动启动"${END}
}
dpkg -s docker-ce &> /dev/null && ${COLOR}"Docker已安装"${END} || install_docker
docker-compose --version &> /dev/null && ${COLOR}"Docker Compose已安装"${END} ||
install_docker_compose
install_harbor
harbor_service

6.4.3 使用单主机 Harbor

6.4.3.1 建立项目

harbor上必须先建立项目,才能上传镜像

6.4.3.2 命令行登录 harbor
#方法1
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry10.0.0.101 --insecure-registry10.0.0.102
#方法2
[root@ubuntu1804 ~]#vim  /etc/docker/daemon.json
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries": ["10.0.0.101:80","10.0.0.102:80"]  #说明: ":80"可省略
}
[root@ubuntu1804 ~]#systemctl daemon-reload
[root@ubuntu1804 ~]#systemctl restart docker
[root@ubuntu1804 ~]#docker login 10.0.0.101
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#查看进程是否添加上面设置
[root@ubuntu1804 ~]#ps aux|grep dockerd
root      173477.8  9.6 83927294784 ?        Ssl  22:54   0:15
/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --
insecure-registry10.0.0.101 --insecure-registry10.0.0.102
root      176300.0  0.1  144281008 pts/4    S+22:57   0:00 grep--
color=auto dockerd
[root@ubuntu1804 ~]#cat .docker/config.json
{
"auths": {
"10.0.0.101": {
"auth": "YWRtaW46MTIzNDU2"
        },
"https://index.docker.io/v1/": {
"auth": "d2FuZ3hpYW9jaHVuOmxidG9vdGgwNjE4"
        },
"registry.cn-beijing.aliyuncs.com": {
"auth": "MjkzMDg2MjBAcXEuY29tOmxidG9vdGgwNjE4"
        }
    },
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.5 (linux)"
    }
}
6.4.3.3 给本地镜像打标签并上传到 Harbor

修改 images 的名称,不修改成指定格式无法将镜像上传到 harbor 仓库格式为:

Harbor主机IP/项目名/image名:版本

范例:

#上传镜像前,必须先登录harbor
[root@ubuntu1804 ~]#docker login 10.0.0.101
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@ubuntu1804 ~]#docker tag alpine-base:3.11 10.0.0.101/example/alpine-
base:3.11
[root@ubuntu1804 ~]#docker push 10.0.0.101/example/alpine-base:3.11

访问harbor网站验证上传镜像成功

范例: 如果不事先建立项目,上传镜像失败

[root@ubuntu1804 ~]#docker tag centos7-base:v1 10.0.0.101/example2/centos7-
base:v1
[root@ubuntu1804 ~]#docker push 10.0.0.101/example2/centos7-base:v1
The push refers to repository [10.0.0.101/example2/centos7-base]
2073413aebd6: Preparing
6ec9af97c369: Preparing
034f282942cd: Preparing
denied: requested access to the resource is denied
[root@ubuntu1804 ~]#docker tag centos7-base:v1 10.0.0.101/example/centos7-
base:v1
[root@ubuntu1804 ~]#docker push 10.0.0.101/example/centos7-base:v1
The push refers to repository [10.0.0.101/example/centos7-base]
2073413aebd6: Pushed
6ec9af97c369: Pushed
034f282942cd: Pushed
v1: digest:
sha256:02cd943f2569c7c55f08a979fd9661f1fd7893c424bca7b343188654ba63d98d size:
949

可以看到操作的日志记录

6.4.3.4 下载 Harbor 的镜像

在10.0.0.103的CentOS 7 的主机上无需登录,即可下载镜像

下载前必须修改docker的service 文件,加入harbor服务器的地址才可以下载

范例: 修改docker的service文件

[root@centos7 ~]#docker pull 10.0.0.101/example/centos7-base:v1
Error response from daemon: Get https://10.0.0.101/v2/: dial tcp 10.0.0.101:443:
connect: connection refused
#方法1
[root@ubuntu1804 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--insecure-registry10.0.0.101 --insecure-registry10.0.0.102
#方法2
[root@ubuntu1804 ~]#vim/etc/docker/daemon.json
{
"insecure-registries": ["10.0.0.101", "10.0.0.102"]
}
[root@centos7 ~]#systemctl daemon-reload
[root@centos7 ~]#systemctl restart docker
[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE

范例: 从harbor下载镜像

[root@centos7 ~]#docker pull 10.0.0.101/example/centos7-base:v1
v1: Pulling from example/centos7-base
f34b00c7da20: Pull complete
544476d462f7: Pull complete
39345915aa1b: Pull complete
Digest: sha256:02cd943f2569c7c55f08a979fd9661f1fd7893c424bca7b343188654ba63d98d
Status: Downloaded newer image for10.0.0.101/example/centos7-base:v1
10.0.0.101/example/centos7-base:v1
[root@centos7 ~]#docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED
            SIZE
10.0.0.101/example/centos7-base   v1                  34ab3afcd3b3        2 days
ago          403MB
6.4.3.5 创建自动打标签上传镜像脚本
#在10.0.0.100上修改以前的build.sh脚本
[root@ubuntu1804 ~]#cd /data/dockerfile/web/nginx/1.16.1-alpine/
[root@ubuntu1804 1.16.1-alpine]#vim build.sh
[root@ubuntu1804 1.16.1-alpine]#cat build.sh
#!/bin/bash
TAG=$1
docker build -t10.0.0.101/example/nginx-alpine:1.16.1-${TAG} .
docker push 10.0.0.101/example/nginx-alpine:1.16.1-${TAG}
docker rmi -f10.0.0.101/example/nginx-alpine:1.16.1-${TAG}
[root@ubuntu1804 1.16.1-alpine]#bash build.sh v1

登录harbor网站验证脚本上传镜像成功

6.4.3.6 修改 Harbor 配置

后期如果修改harbor配置,比如: 修改IP地址等,可执行以下步骤生效

方法1:

[root@ubuntu1804 ~]#cd /apps/harbor/
[root@ubuntu1804 harbor]#docker-compose stop
Stopping nginx              ... done
Stopping harbor-portal      ... done
Stopping harbor-jobservice  ... done
Stopping harbor-core        ... done
Stopping harbor-adminserver ... done
Stopping harbor-db          ... done
Stopping registryctl        ... done
Stopping registry           ... done
Stopping redis              ... done
Stopping harbor-log         ...
#所有相关容器都退出
[root@ubuntu1804 harbor]#docker ps  -a
CONTAINER ID        IMAGE                                    COMMAND
     CREATED             STATUS                        PORTS               NAMES
4ec3c3885407        goharbor/nginx-photon:v1.7.6             "nginx -g 'daemon
of…"32 minutes ago      Exited (0) 51 seconds ago
nginx
5707b4ac41d8        goharbor/harbor-portal:v1.7.6            "nginx -g 'daemon
of…"32 minutes ago      Exited (0) 50 seconds ago
harbor-portal
0ed230b9b714        goharbor/harbor-jobservice:v1.7.6        "/harbor/start.sh"
32 minutes ago      Exited (137) 41 seconds ago
harbor-jobservice
fec659188349        goharbor/harbor-core:v1.7.6              "/harbor/start.sh"
32 minutes ago      Exited (137) 30 seconds ago
harbor-core
910d14c1d7f7        goharbor/harbor-adminserver:v1.7.6       "/harbor/start.sh"
32 minutes ago      Exited (137) 20 seconds ago
harbor-adminserver
4348f503aa0e        goharbor/harbor-db:v1.7.6                "/entrypoint.sh
post…"32 minutes ago      Exited (255) 48 seconds ago
harbor-db
beff6886f0f1        goharbor/harbor-registryctl:v1.7.6       "/harbor/start.sh"
32 minutes ago      Exited (137) 41 seconds ago
registryctl
428c99d274bf        goharbor/registry-photon:v2.6.2-v1.7.6   "/entrypoint.sh
/etc…"32 minutes ago      Exited (137) 20 seconds ago
registry
775b4026fa4e        goharbor/redis-photon:v1.7.6             "docker-
entrypoint.s…"32 minutes ago      Exited (137) 30 seconds ago
      redis
c6f44e2034c6        goharbor/harbor-log:v1.7.6               "/bin/sh -c
/usr/loc…"32 minutes ago      Exited (137) 9 seconds ago
   harbor-log

# 修改 harbor 配置

[root@ubuntu1804 harbor]#vim harbor.cfg
#更新配置
[root@ubuntu1804 ~]#/apps/harbor/prepare
Clearing the configuration file: /apps/harbor/common/config/db/env
Clearing the configuration file: /apps/harbor/common/config/core/private_key.pem
Clearing the configuration file: /apps/harbor/common/config/core/env
Clearing the configuration file: /apps/harbor/common/config/core/app.conf
Clearing the configuration file: /apps/harbor/common/config/adminserver/env
Clearing the configuration file: /apps/harbor/common/config/registryctl/env
Clearing the configuration file:
/apps/harbor/common/config/registryctl/config.yml
Clearing the configuration file: /apps/harbor/common/config/registry/root.crt
Clearing the configuration file: /apps/harbor/common/config/registry/config.yml
Clearing the configuration file: /apps/harbor/common/config/log/logrotate.conf
Clearing the configuration file: /apps/harbor/common/config/nginx/nginx.conf
Clearing the configuration file: /apps/harbor/common/config/jobservice/env
Clearing the configuration file:
/apps/harbor/common/config/jobservice/config.yml
loaded secret from file: /data/secretkey
Generated configuration file: /apps/harbor/common/config/nginx/nginx.conf
Generated configuration file: /apps/harbor/common/config/adminserver/env
Generated configuration file: /apps/harbor/common/config/core/env
Generated configuration file: /apps/harbor/common/config/registry/config.yml
Generated configuration file: /apps/harbor/common/config/db/env
Generated configuration file: /apps/harbor/common/config/jobservice/env
Generated configuration file: /apps/harbor/common/config/jobservice/config.yml
Generated configuration file: /apps/harbor/common/config/log/logrotate.conf
Generated configuration file: /apps/harbor/common/config/registryctl/env
Generated configuration file: /apps/harbor/common/config/core/app.conf
Generated certificate, key file: /apps/harbor/common/config/core/private_key.pem,
cert file: /apps/harbor/common/config/registry/root.crt
The configuration files are ready, please use docker-compose to start the
service.
#重新启动docker compose
[root@ubuntu1804 harbor]#docker-compose  start
Starting log         ... done
Starting postgresql  ... done
Starting redis       ... done
Starting adminserver ... done
Starting registry    ... done
Starting core        ... done
Starting jobservice  ... done
Starting portal      ... done
Starting proxy       ... done
Starting registryctl ... done
#相关容器自动启动
[root@ubuntu1804 harbor]#docker ps
CONTAINER ID        IMAGE                                    COMMAND
     CREATED             STATUS                             PORTS
                                             NAMES
4ec3c3885407        goharbor/nginx-photon:v1.7.6             "nginx -g 'daemon
of…"34 minutes ago      Up 9 seconds (health: starting)    0.0.0.0:80-
>80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp   nginx
5707b4ac41d8        goharbor/harbor-portal:v1.7.6            "nginx -g 'daemon
of…"34 minutes ago      Up 9 seconds (health: starting)    80/tcp
                                                harbor-portal
0ed230b9b714        goharbor/harbor-jobservice:v1.7.6        "/harbor/start.sh"
34 minutes ago      Up 10 seconds
                                                harbor-jobservice
fec659188349        goharbor/harbor-core:v1.7.6              "/harbor/start.sh"
34 minutes ago      Up 11 seconds (health: starting)
                                               harbor-core
910d14c1d7f7        goharbor/harbor-adminserver:v1.7.6       "/harbor/start.sh"
34 minutes ago      Up 14 seconds (health: starting)
                                               harbor-adminserver
4348f503aa0e        goharbor/harbor-db:v1.7.6                "/entrypoint.sh
post…"34 minutes ago      Up 13 seconds (health: starting)   5432/tcp
                                                  harbor-db
beff6886f0f1        goharbor/harbor-registryctl:v1.7.6       "/harbor/start.sh"
34 minutes ago      Up 12 seconds (health: starting)
                                               registryctl
428c99d274bf        goharbor/registry-photon:v2.6.2-v1.7.6   "/entrypoint.sh
/etc…"34 minutes ago      Up 13 seconds (health: starting)   5000/tcp
                                                  registry
775b4026fa4e        goharbor/redis-photon:v1.7.6             "docker-
entrypoint.s…"34 minutes ago      Up 11 seconds                      6379/tcp
                                                          redis
c6f44e2034c6        goharbor/harbor-log:v1.7.6               "/bin/sh -c
/usr/loc…"34 minutes ago      Up 16 seconds (health: starting)
127.0.0.1:1514->10514/tcp                                          harbor-log
[root@ubuntu1804 harbor]#

方法2:

[root@ubuntu1804 ~]#/apps/harbor/install.sh

6.4.4 实现 Harbor 高可用

Harbor支持基于策略的Docker镜像复制功能,这类似于MySQL的主从同步,其可以实现不同的数据中心、不同的运行环境之间同步镜像,并提供友好的管理界面,大大简化了实际运维中的镜像管理工作, 已经有用很多互联网公司使用harbor搭建内网docker仓库的案例,并且还有实现了双向复制功能

6.4.4.1 安装第二台 harbor主机

参考6.4.2的过程,在第二台主机上安装部署好harbor,并登录系统

注意: harbor.cfg中配置 hostname = 10.0.0.102

6.4.4.2 第二台harbor上新建项目

参考第一台harbor服务器的项目名称,在第二台harbor服务器上新建与之同名的项目

6.4.4.3 第二台harbor上仓库管理中新建目标

参考第一台主机信息,新建复制(同步)目标信息,将第一台主机设为复制的目标

输入第一台harbor服务器上的主机10.0.0.101,目标名指定需要复制的项目名:example和用户信息及密码admin

6.4.4.4 第二台harbor上新建复制规则实现到第一台harbor的单向复制

在第二台harbor上建立复制的目标主机,将第二台harbor上面的镜像复制到第一台harbor上

新版界面如下:事件驱动指当有新镜像上传时,自动触发同步,但初始时不会自动复制现在镜像

在新版中上述只是创建了复制规则,不会自动同步当前现有的镜像,可以点下面”新建规则“的右边按钮 “复制”,进行立即同步

6.4.4.5 在第一台harbor主机上重复上面操作

以上操作,只是实现了从第二台harbor主机10.0.0.102到第一台harbor主机10.0.101的单向同步在第一台harbor上再执行下面操作,才实现双向同步

6.4.4.6 确认同步成功

在第二台harbor主机上可以查看到从第一台主机同步过来的镜像

也可以查看到同步日志

6.4.4.7 上传镜像观察是否可以双高同步
[root@ubuntu1804 ~]#docker tag tomcat-web:app1 10.0.0.101/example/tomcat-
web:app1
[root@ubuntu1804 ~]#docker push 10.0.0.101/example/tomcat-web:app1
[root@ubuntu1804 ~]#docker tag tomcat-web:app2 10.0.0.102/example/tomcat-
web:app2
[root@ubuntu1804 ~]#docker push 10.0.0.102/example/tomcat-web:app2

6.4.4.8 删除镜像观察是否可自动同步

6.4.4.9 配置 Nginx 做为反向代理
#配置Nginx反向代理
[root@ubuntu2004 ~]#cat /etc/nginx/conf.d/harbor.wang.org.conf
upstream harbor {
    hash $remote_addr;  #添加会话粘性功能,否则无法登录harbor,提示“用户名或者密码不正确“
    server harbor1.wang.org:80;
    server harbor2.wang.org:80;
}
server {
    listen 80;
    server_name harbor.wang.org;
    client_max_body_size 10g;
    location / {
        proxy_pass http://harbor;
    }
}
#客户端docker配置
[root@rocky8 ~]#cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries": ["harbor.wang.org"]
}
[root@rocky8 ~]#systemctl restart docker
#客户端docker配置名称解析
[root@rocky8 ~]#vim /etc/hosts
10.0.0.100 harbor.wang.org
#如果harbor配置中的hostname: 指定harbor1.wang.org和harbor2.wang.org名称,还需要加下面解
析
10.0.0.101 harbor1.wang.org
10.0.0.102 harbor2.wang.org

6.4.5 Harbor 安全 Https 配置

基于安全考虑,生产建议采用 https 代替 http

6.4.5.1 新版实现实现 Harbor 的 Https 认证

新版2.5.0的Https实现方法出现了一些变化

官方文档:

https://goharbor.io/docs/2.6.0/install-config/configure-https/
https://goharbor.io/docs/2.5.0/install-config/configure-https/

6.4.5.1.1 生成 Harbor 服务器证书

#生成ca的私钥
openssl genrsa -out ca.key 4096
#生成ca的自签名证书
openssl req -x509-new-nodes-sha512-days3650 \
-subj"/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=ca.wang.org" \
-key ca.key \
-out ca.crt
#生成harbor主机的私钥
openssl genrsa -out harbor.wang.org.key 4096
#生成harbor主机的证书申请
openssl req -sha512-new \
-subj"/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=harbor.wang.org"
\
-key harbor.wang.org.key \
-out harbor.wang.org.csr
#创建x509 v3 扩展文件(新版新增加的要求)
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=wang.org
DNS.2=wang
DNS.3=harbor.wang.org   #此处必须和和harbor的网站名称一致
EOF
#给 harbor主机颁发证书
openssl x509 -req-sha512-days3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in harbor.wang.org.csr \
-out harbor.wang.org.crt
#最终文件列表如下
ca.crt  ca.key  ca.srl  harbor.wang.org.crt  harbor.wang.org.csr
harbor.wang.org.key  v3.ext

注意: 如果不生成创建x509 v3 扩展文件,会出现下面提示错误

docker login harbor.wang.org
Username: admin
Password:
Error response from daemon: Get "https://harbor.wang.org/v2/": x509: certificate
relies on legacy Common Name field, use SANs or temporarily enable Common Name
matching with GODEBUG=x509ignoreCN=0
6.4.5.1.2 配置 Harbor 服务器使用证书
mkdir /data/harbor/certs/
cp harbor.wang.org.crt harbor.wang.org.key /data/harbor/certs/
vim /apps/harbor/harbor.yml
......
hostname = harbor.wang.org #一定要证书名称相同
......
# https related config
https:
# https port for harbor, default is 443
  port: 443
# The path of cert and key files for nginx
  certificate: /data/harbor/certs/harbor.wang.org.crt  #修改两行,指定证书和私钥的路径
  private_key: /data/harbor/certs/harbor.wang.org.key
......
#使上面的配置生效
cd /apps/harbor/
./prepare
docker-compose down -v
docker-compose up -d

输入下面 http 链接自动跳转到 https

http://harbor.wang.org

6.4.5.2.3 配置 Docker 客户端使用证书文件
#转换harbor的crt证书文件为cert后缀,docker识别crt文件为CA证书,cert为客户端证书服务器,此步实
际可选
openssl x509 -inform PEM -in harbor.wang.org.crt -out harbor.wang.org.cert
#或者
cp-a harbor.wang.org.crt  harbor.wang.org.cert
#比较两个文件的不同,实际上是一样的
md5sum harbor.wang.org.crt harbor.wang.org.cert
#创建和harbor服务器同名的目录
mkdir-pv /etc/docker/certs.d/harbor.wang.org/
#如果使用containerd运行时
mkdir-pv /etc/containerd/certs.d/harbor.wang.org/
#在docker客户端使用上面的证书文件
#注意:官方介绍需要同时复制harbor.wang.org.key ca.crt,实际不需要
cp harbor.wang.org.cert或harbor.wang.org.crt  harbor.wang.org.key ca.crt
/etc/docker/certs.d/harbor.wang.org/
#实际只需要执行下面即可
cp harbor.wang.org.cert或harbor.wang.org.crt /etc/docker/certs.d/harbor.wang.org/
#新版如果无法登录,需重启docker服务
systemctl restart docker
#在docker客户端登录harbor服务器,注意:此时无需再配置insecure-registries项即可登录
docker login harbor.wang.org
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#登录成功后,自动保存登录信息,注意:auth对应的密码使用base64编码,可以还原明文密码
cat ~/.docker/config.json
{
"auths": {
"harbor.wang.org": {
"auth": "AHFGDFADD434aXhr"
          }
    }
}
6.4.5.2.4 Docker 客户端测试推送和拉取镜像

登录harbor 查看推送命令

docker push wangxiaochun/busybox:1.30.0
docker tag wangxiaochun/busybox:1.30.0 harbor.wang.org/library/busybox:1.30.0
docker push harbor.wang.org/library/busybox:1.30.0

验证推送是否成功

验证拉取

docker pull  harbor.wang.org/library/busybox:1.30.0
6.4.5.2 旧版实现 Harbor 的 Https 认证

旧版harbor默认使用http,为了安全,可以使用https

6.4.5.2.1 实现Harbor 的 https 认证
#安装docker
[root@ubuntu1804 ~]#bash install_docker_for_ubuntu1804.sh
#安装docker compose
[root@ubuntu1804 ~]#curl -L
https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname
-s`-`uname -m` -o /usr/local/bin/docker-compose
[root@ubuntu1804 ~]#chmod +x /usr/local/bin/docker-compose
[root@ubuntu1804 ~]#docker-compose  --version
docker-compose version 1.25.3, build d4d1b42b

# 下载 harbor 离线安装包且解压缩

[root@ubuntu1804 ~]#wget https://storage.googleapis.com/harbor-releases/release-
1.7.0/harbor-offline-installer-v1.7.6.tgz
[root@ubuntu1804 ~]#mkdir /apps
[root@ubuntu1804 ~]#tar xvf harbor-offline-installer-v1.7.6.tgz  -C /apps/
#生成私钥和证书
[root@ubuntu1804 ~]#touch /root/.rnd
[root@ubuntu1804 ~]#mkdir /apps/harbor/certs/
[root@ubuntu1804 ~]#cd /apps/harbor/certs/

# 生成 CA 证书

[root@ubuntu1804 certs]#openssl req  -newkey rsa:4096 -nodes -sha256 -keyout
ca.key -x509  -subj "/CN=ca.wang.org" -days 365 -out ca.crt
#生成harbor主机的证书申请
[root@ubuntu1804 certs]#openssl req  -newkey rsa:4096 -nodes -sha256 -subj
"/CN=harbor.wang.org" -keyout harbor.wang.org.key -out harbor.wang.org.csr
#给harbor主机颁发证书
[root@ubuntu1804 certs]#openssl x509 -req -in harbor.wang.org.csr -CA ca.crt -
CAkey ca.key -CAcreateserial  -out harbor.wang.org.crt
[root@ubuntu1804 ~]#tree /apps/harbor/certs
/apps/harbor/certs
├── ca.crt
├── ca.key
├── ca.srl
├── harbor.wang.org.crt
├── harbor.wang.org.csr
└── harbor.wang.org.key
0 directories, 6 files
[root@ubuntu1804 ~]#vim /apps/harbor/harbor.cfg
hostname = harbor.wang.org
ui_url_protocol = https
ssl_cert = /apps/harbor/certs/harbor.wang.org.crt
ssl_cert_key = /apps/harbor/certs/harbor.wang.org.key
harbor_admin_password =123456
[root@ubuntu1804 ~]#apt -y install python
[root@ubuntu1804 ~]#/apps/harbor/install.sh
6.4.5.2.2 用https方式访问harbor网站

修改/etc/hosts文件

10.0.0.103 harbor.wang.org

打开浏览器,访问http://harbor.wang.org ,可以看到以下界面

查看证书

6.4.5.2.3 在harbor网站新建项目

6.4.5.2.4 在客户端下载CA的证书

直接登录和上传下载镜像会报错

[root@ubuntu1804 ~]#vim /etc/hosts
10.0.0.103 harbor.wang.org
#没有证书验证,直接登录失败
[root@ubuntu1804 ~]#docker login harbor.wang.org
Username: admin
Password:
Error response from daemon: Get https://harbor.wang.org/v2/: x509: certificate
signed by unknown authority

在客户端下载ca的证书

[root@ubuntu1804 ~]#mkdir -pv /etc/docker/certs.d/harbor.wang.org/
[root@ubuntu1804 ~]#scp -r harbor.wang.org:/apps/harbor/certs/ca.crt
/etc/docker/certs.d/harbor.wang.org/
[root@ubuntu1804 ~]#tree /etc/docker/certs.d/
/etc/docker/certs.d/
└── harbor.wang.org
    └── ca.crt
1 directory, 1 file
#上面证书配置无需重启服务即生效
6.4.5.2.5 从客户端上传镜像
#旧版无需重启docker服务,就可登录系统
[root@ubuntu1804 ~]#docker login harbor.wang.org
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#上传镜像
[root@ubuntu1804 ~]#docker tag alpine:3.11  harbor.wang.org/example/alpine:3.11
[root@ubuntu1804 ~]#docker push harbor.wang.org/example/alpine:3.11
The push refers to repository [harbor.wang.org/example/alpine]
5216338b40a7: Pushed
3.11: digest:
sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45 size:
528

在harbor网站上验证上传的镜像

6.4.5.2.6 在客户端下载镜像

[root@centos7 ~]#vim /etc/hosts
10.0.0.103 harbor.wang.org
[root@centos7 ~]#docker pull  harbor.wang.org/example/alpine:3.11
Error response from daemon: Get https://harbor.wang.org/v2/: x509: certificate
signed by unknown authority
[root@centos7 ~]#mkdir -pv /etc/docker/certs.d/harbor.wang.org/
[root@centos7 ~]#scp -r harbor.wang.org:/apps/harbor/certs/ca.crt
/etc/docker/certs.d/harbor.wang.org/
[root@centos7 ~]#tree /etc/docker/certs.d/
/etc/docker/certs.d/
└── harbor.wang.org
    └── ca.crt
1 directory, 1 file
[root@centos7 ~]#docker images
REPOSITORY          TAG                 IMAGE ID            CREATED
SIZE
[root@centos7 ~]#docker pull  harbor.wang.org/example/alpine:3.11
3.11: Pulling from example/alpine
c9b1b535fdd9: Pull complete
Digest: sha256:ddba4d27a7ffc3f86dd6c2f92041af252a1f23a8e742c90e6e1297bfa1bc0c45
Status: Downloaded newer image for harbor.wang.org/example/alpine:3.11
harbor.wang.org/example/alpine:3.11
[root@centos7 ~]#docker images
REPOSITORY                         TAG                 IMAGE ID
CREATED             SIZE
harbor.wang.org/example/alpine   3.11                e7d92cdc71fe        13 days
ago         5.59MB

7 Docker 的资源限制

7.1 Docker 资源限制

7.1.1 容器资源限制介绍

官方文档: https://docs.docker.com/config/containers/resource_constraints/

默认情况下,容器没有资源的使用限制,可以使用主机内核调度程序允许的尽可能多的资源

Docker 提供了控制容器使用资源的方法,可以限制容器使用多少内存或 CPU等

docker run 命令的运行时指定相关参数即可实现资源限制功能。

其中许多功能都要求宿主机的内核支持,要检查是否支持这些功能,可以使用docker info 命令 ,如果内核中的某项特性存在问题,可能会在输出结尾处看到警告, 如下所示:

WARNING: No swap limit support  #没有启用 swap 限制功能会出现此提示警报

可通过修改内核参数消除以上警告

官方文档: https://docs.docker.com/install/linux/linux-postinstall/#your-kernel-does-not-support-c group-swap-limit-capabilities

范例: 修改内核参数消除以上警告

[root@ubuntu1804 ~]#docker info
Client:
 Debug Mode: false
Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 1
 Server Version: 19.03.5
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339
 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
 init version: fec3683
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 4.15.0-29-generic
 Operating System: Ubuntu 18.04.1 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 1
 Total Memory: 962MiB
 Name: ubuntu1804.wang.org
 ID: 4LUN:CS4Y:SGYQ:ZAXU:M7C5:JYSB:ZFTO:JZ6D:CD7Q:TOVD:JBFS:AQM3
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
10.0.0.102
127.0.0.0/8
 Registry Mirrors:
  https://si7y70hh.mirror.aliyuncs.com/
 Live Restore Enabled: false
WARNING: No swap limit support

# 修改内核参数

[root@ubuntu1804 ~]#vim /etc/default/grub
GRUB_CMDLINE_LINUX="net.ifnames=0  cgroup_enable=memory swapaccount=1"
[root@ubuntu1804 ~]#update-grub
[root@ubuntu1804 ~]#reboot
[root@ubuntu1804 ~]#docker info
Client:
 Debug Mode: false
Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 1
 Server Version: 19.03.5
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk
syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339
 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
 init version: fec3683
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 4.15.0-29-generic
 Operating System: Ubuntu 18.04.1 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 1
 Total Memory: 962MiB
 Name: ubuntu1804.wang.org
 ID: 4LUN:CS4Y:SGYQ:ZAXU:M7C5:JYSB:ZFTO:JZ6D:CD7Q:TOVD:JBFS:AQM3
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
10.0.0.102
127.0.0.0/8
 Registry Mirrors:
  https://si7y70hh.mirror.aliyuncs.com/
 Live Restore Enabled: false
[root@ubuntu1804 ~]#

7.1.2 OOM (Out of Memory Exception)

对于 Linux 主机,如果没有足够的内存来执行某个应用,将会抛出OOM (Out of Memory) Exception 即内存不足的异常,随后系统会开始杀死进程以释放内存, 而凡是运行在宿主机的进程都有可能被 kill , 包括 Dockerd和其它的应用程序, 如果重要的系统进程被 Kill,会导致和该进程相关的服务全部宕机。 通常越消耗内存比较大的应用越容易被kill,比如: MySQL数据库,Java程序等

范例: OOM发生后的日志信息

产生 OOM 异常时, Dockerd尝试通过调整 Docker 守护程序上的 OOM 优先级来减轻这些风险,以便它比系统上的其他进程更不可能被杀死但是每个容器的 OOM 优先级并未调整, 这使得单个容器被杀死的可能性比 Docker守护程序或其他系统进程被杀死的可能性更大,不推荐通过在守护程序或容器上手动设置-- oom -score-adj为极端负数,或通过在容器上设置 -- oom-kill-disable来绕过这些安全措施

OOM 优先级机制:

linux会为每个进程计算一个分数,最终将分数最高的kill

/proc/PID/oom_score_adj
#范围为 -1000 到 1000,值越高容易被宿主机 kill掉,如果将该值设置为 -1000 ,则进程永远不会被
宿主机 kernel kill
/proc/PID/oom_adj
#范围为 -17 到+15 ,取值越高越容易被干掉,如果是 -17 ,则表示不能被 kill ,该设置参数的存在
是为了和旧版本的 Linux 内核兼容。
/proc/PID/oom_score
#这个值是系统综合进程的内存消耗量、 CPU 时间 (utime + 存活时间 (uptime - start time) 和
oom_adj 计算出的进程得分,消耗内存越多得分越高,容易被宿主机 kernel 强制杀死

范例: 查看OOM相关值

#按内存排序
[root@ubuntu1804 ~]#top
top-20:15:38 up  5:53,  3 users,  load average: 0.00, 0.00, 0.00
Tasks: 191 total,   1 running, 116 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   985104 total,   310592 free,   448296 used,   226216 buff/cache
KiB Swap:  1951740 total,  1892860 free,    58880 used.   384680 avail Mem
   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
19674201920022416569468412452 S  0.0  9.6   0:16.05 java
19675201920022355127481612440 S  0.0  7.6   0:14.89 java
19860 99
4969 root
200
200
183212
937880
67748
49352
960 S0.06.90:01.15 haproxy
12612 S0.05.00:46.07 dockerd
2981 root 200 793072 13552 1808 S0.01.40:13.78 containerd
500 root 19 -1 78560 7552 7112 S0.00.80:01.45 systemd-
journal
798 root 200 170416 6604 4084 S0.00.70:00.77 networkd-
dispat
1 root 200 78036 6200 4416 S0.00.60:05.39 systemd
1011 root 200 24548 5496 3012 S0.00.60:01.62bash
852 root 10 -10 25880 5264 4036 S0.00.50:00.00 iscsid
815 root 200 548292 4624 1224 S0.00.50:01.89 snapd
19586 root
200
109104
4532
3768 S0.00.50:00.29 containerd-
shim
19779 root 200 405532 4224 2828 S0.00.40:00.01 docker-proxy
19784 root 200 107696 4204 3652 S0.00.40:00.29 containerd-
shim
19424 root 200 109104 4084 3416 S0.00.40:00.27 containerd-
shim
20064 root 200 44076 4036 3360 R0.70.40:00.20top
19768 root 200 405532 4024 2644 S0.00.40:00.01 docker-proxy
19423 root 200 109104 3792 3064 S0.00.40:00.31 containerd-
shim
490 root 200 193112 3316 2864 S0.00.30:26.20 vmtoolsd
7108 root 200 105688 3204 2504 S0.00.30:00.11 sshd
[root@ubuntu1804
0
~]#cat /proc/19 674/oom _adj
[root@ubuntu1804
32
~]#cat /proc/19 674/oom _score
[root@ubuntu1804
~]#cat /proc/19 674/oom _score_adj
0
[root@ubuntu1804
0
~]#cat /proc/71 08/oom_ adj
[root@ubuntu1804
1
~]#cat /proc/71 08/oom_ score
[root@ubuntu1804
0
~]#cat /proc/71 08/oom_ score_adj
#docker服务进程的OOM默认值
[root@ubuntu1804 ~]#cat /proc/`pidof dockerd`/oom_adj
-8
[root@ubuntu1804 ~]#cat /proc/`pidof dockerd`/oom_score
0
[root@ubuntu1804 ~]#cat /proc/`pidof dockerd`/oom_score_adj
-500

7.2 Stress-ng 压力测试工具

7.2.1 Stress-ng 工具介绍

stress-ng是一个压力测试工具,可以通过软件仓库进行安装,也提供了docker版本的容器官方链接:https://kernel.ubuntu.com/~cking/stress-ng/ 官方文档:https://wiki.ubuntu.com/Kernel/Reference/stress-ng

Docker 镜像: lorel/docker-stress-ng

7.2.2 stress-ng 安装

范例: 软件包方式安装

[root@centos7 ~]#yum -y install stress-ng
[root@ubuntu1804 ~]#apt -y install stress-ng

范例: 容器方式安装

[root@ubuntu1804 ~]#docker pull lorel/docker-stress-ng
Using default tag: latest
latest: Pulling from lorel/docker-stress-ng
Image docker.io/lorel/docker-stress-ng:latest uses outdated schema1 manifest
format. Please upgrade to a schema2 image for better future compatibility. More
information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
c52e3ed763ff: Pull complete
a3ed95caeb02: Pull complete
7f831269c70e: Pull complete
Digest: sha256:c8776b750869e274b340f8e8eb9a7d8fb2472edd5b25ff5b7d55728bca681322
Status: Downloaded newer image for lorel/docker-stress-ng:latest
docker.io/lorel/docker-stress-ng:latest
[root@ubuntu1804 ~]#docker images
REPOSITORY               TAG                 IMAGE ID            CREATED
    SIZE
lorel/docker-stress-ng   latest              1ae56ccafe55        3 years ago
8.1MB

7.2.3 Stress-ng 使用

范例: 查看帮助

[root@ubuntu1804 ~]#docker run -it --rm lorel/docker-stress-ng
stress-ng, version 0.03.11
Usage: stress-ng [OPTION [ARG]]
--h,  --help             show help
--affinity N       start N workers that rapidly change CPU affinity
--affinity-ops N   stop when N affinity bogo operations completed
--affinity-rand    change affinity randomly rather than sequentially
--aio N            start N workers that issue async I/O requests
--aio-ops N        stop when N bogo async I/O requests completed
--aio-requests N   number of async I/O requests per worker
-a N, --all N            start N workers of each stress test
-b N, --backoff N        wait of N microseconds before work starts
-B N, --bigheap N        start N workers that grow the heap using calloc()
--bigheap-ops N    stop when N bogo bigheap operations completed
--bigheap-growth N grow heap by N bytes per iteration
--brk N            start N workers performing rapid brk calls
--brk-ops N        stop when N brk bogo operations completed
--brk-notouch      don't touch (page in) new data segment page
--bsearchstart N workers that exercise a binary search
--bsearch-opsstop when N binary search bogo operations completed
--bsearch-size     number of 32 bit integers to bsearch
-C N, --cache N          start N CPU cache thrashing workers
--cache-ops N      stop when N cache bogo operations completed (x86 only)
--cache-flush      flush cache after every memory write (x86 only)
--cache-fence      serialize stores
--class name       specify a class of stressors, use with --sequential
--chmod N          start N workers thrashing chmod file mode bits
--chmod-ops N      stopchmod workers after N bogo operations
-c N, --cpu N            start N workers spinning on sqrt(rand())
--cpu-ops N        stop when N cpu bogo operations completed
-l P, --cpu-load P       load CPU by P %%, 0=sleep, 100=full load (see -c)
--cpu-method m     specify stress cpu method m, default is all
-D N, --dentry N         start N dentry thrashing processes
--dentry-ops N     stop when N dentry bogo operations completed
--dentry-order O   specify dentry unlink order (reverse, forward, stride)
--dentries N       create N dentries per iteration
--dir N            start N directory thrashing processes
--dir-ops N        stop when N directory bogo operations completed
-n,   --dry-rundo not run
--dup N            start N workers exercising dup/close
--dup-ops N        stop when N dup/close bogo operations completed
--epoll N          start N workers doing epoll handled socket activity
--epoll-ops N      stop when N epoll bogo operations completed
--epoll-port P     use socket ports P upwards
--epoll-domain D   specify socket domain, default is unix
--eventfd N        start N workers stressing eventfd read/writes
--eventfd-ops N    stop eventfd workers after N bogo operations
--fault N          start N workers producing page faults
--fault-ops N      stop when N page fault bogo operations completed
--fifo N           start N workers exercising fifo I/O
--fifo-ops N       stop when N fifo bogo operations completed
--fifo-readers N   number of fifo reader processes to start
--flock N          start N workers locking a single file
--flock-ops N      stop when N flock bogo operations completed
-f N, --fork N           start N workers spinning on fork() and exit()
--fork-ops N       stop when N fork bogo operations completed
--fork-max P       create P processes per iteration, default is 1
--fstat N          start N workers exercising fstat on files
--fstat-ops N      stop when N fstat bogo operations completed
--fstat-dir path   fstat files in the specified directory
--futex N          start N workers exercising a fast mutex
--futex-ops N      stop when N fast mutex bogo operations completed
--get N            start N workers exercising the get*() system calls
--get-ops N        stop when N get bogo operations completed
-d N, --hdd N            start N workers spinning on write()/unlink()
--hdd-ops N        stop when N hdd bogo operations completed
--hdd-bytes N      write N bytes per hdd worker (default is 1GB)
--hdd-direct       minimize cache effects of the I/O
--hdd-dsync        equivalent to a write followed by fdatasync
--hdd-noatimedo not update the file last access time
--hdd-sync         equivalent to a write followed by fsync
--hdd-write-size N set the default write size to N bytes
  • --hsearch start N workers that exercise a hash table search --hsearch-ops stop when N hash search bogo operations completed --hsearch-size number of integers to insert into hash table --inotify N start N workers exercising inotify events
--inotify-ops N    stop inotify workers after N bogo operations
-i N, --io N             start N workers spinning on sync()
  • --io-ops N stop when N io bogo operations completed
--ionice-class C   specify ionice class (idle, besteffort, realtime)
  • --ionice-level L specify ionice level (0 max, 7 min)
-k,   --keep-name        keep stress process names to be 'stress-ng'
--kill N           start N workers killing with SIGUSR1
--kill-ops N       stop when N kill bogo operations completed
--lease N          start N workers holding and breaking a lease
--lease-ops N      stop when N lease bogo operations completed
--lease-breakers N number of lease breaking processes to start
--link N           start N workers creating hard links
--link-ops N       stop when N link bogo operations completed
--lsearchstart N workers that exercise a linear search
--lsearch-opsstop when N linear search bogo operations completed
--lsearch-size     number of 32 bit integers to lsearch
-M,   --metrics          print pseudo metrics of activity
--metrics-brief    enable metrics and only show non-zero results
--memcpy N         start N workers performing memory copies
--memcpy-ops N     stop when N memcpy bogo operations completed
--mmap N           start N workers stressing mmap and munmap
--mmap-ops N       stop when N mmap bogo operations completed
--mmap-async       using asynchronous msyncs for file based mmap
--mmap-bytes N     mmap and munmap N bytes for each stress iteration
--mmap-file        mmap onto a file using synchronous msyncs
--mmap-mprotect    enable mmap mprotect stressing
--msg N            start N workers passing messages using System V
messages
--msg-ops N        stop msg workers after N bogo messages completed
--mq N             start N workers passing messages using POSIX messages
--mq-ops N         stop mq workers after N bogo messages completed
--mq-size N        specify the size of the POSIX message queue
--nice N           start N workers that randomly re-adjust nice levels
--nice-ops N       stop when N nice bogo operations completed
--no-madvise       don't use random madvise options for each mmap
--null N           start N workers writing to /dev/null
--null-ops N       stop when N /dev/null bogo write operations completed
-o,   --open N           start N workers exercising open/close
--open-ops N       stop when N open/close bogo operations completed
-p N, --pipe N           start N workers exercising pipe I/O
--pipe-ops N       stop when N pipe I/O bogo operations completed
-P N, --poll N           start N workers exercising zero timeout polling
--poll-ops N       stop when N poll bogo operations completed
--procfs N         start N workers reading portions of /proc
--procfs-ops N     stop procfs workers after N bogo read operations
--pthread N        start N workers that create multiple threads
--pthread-ops N    stop pthread workers after N bogo threads created
--pthread-max P    create P threads at a time by each worker
-Q,   --qsort N          start N workers exercising qsort on 32 bit random
integers
--qsort-ops N      stop when N qsort bogo operations completed
--qsort-size N     number of 32 bit integers to sort
-q,   --quiet            quiet output
-r,   --random N         start N random workers
--rdrand N         start N workers exercising rdrand instruction (x86
only)
--rdrand-ops N     stop when N rdrand bogo operations completed
-R,   --rename N         start N workers exercising file renames
--rename-ops N     stop when N rename bogo operations completed
--sched type       set scheduler type
--sched-prio N     set scheduler priority level N
--seek N           start N workers performing random seek r/w IO
--seek-ops N       stop when N seek bogo operations completed
--seek-size N      length of file to do random I/O upon
--sem N            start N workers doing semaphore operations
--sem-ops N        stop when N semaphore bogo operations completed
--sem-procs N      number of processes to start per worker
--sendfile N       start N workers exercising sendfile
--sendfile-ops N   stop after N bogo sendfile operations
--sendfile-size N  size of data to be sent with sendfile
--sequential N     run all stressors one by one, invoking N of them
--sigfd N          start N workers reading signals via signalfd reads
--sigfd-ops N      stop when N bogo signalfd reads completed
--sigfpe N         start N workers generating floating point math faults
--sigfpe-ops N     stop when N bogo floating point math faults completed
--sigsegv N        start N workers generating segmentation faults
--sigsegv-ops N    stop when N bogo segmentation faults completed
-S N, --sock N           start N workers doing socket activity
--sock-ops N       stop when N socket bogo operations completed
--sock-port P      use socket ports P to P + number of workers -1
--sock-domain D    specify socket domain, default is ipv4
--stack N          start N workers generating stack overflows
--stack-ops N      stop when N bogo stack overflows completed
-s N, --switch N         start N workers doing rapid context switches
--switch-ops N     stop when N context switch bogo operations completed
--symlink N        start N workers creating symbolic links
--symlink-ops N    stop when N symbolic link bogo operations completed
--sysinfo N        start N workers reading system information
--sysinfo-ops N    stop when sysinfo bogo operations completed
-t N, --timeout N        timeout after N seconds
-T N, --timer N          start N workers producing timer events
--timer-ops N      stop when N timer bogo events completed
--timer-freq F     run timer(s) at F Hz, range 1000 to 1000000000
--tsearchstart N workers that exercise a tree search
--tsearch-opsstop when N tree search bogo operations completed
--tsearch-size     number of 32 bit integers to tsearch
--times            show run time summary at end of the run
-u N, --urandom N        start N workers reading /dev/urandom
--urandom-ops N    stop when N urandom bogo read operations completed
--utime N          start N workers updating file timestamps
--utime-ops N      stop after N utime bogo operations completed
--utime-fsync      force utime meta data sync to the file system
-v,   --verbose          verbose output
--verify           verify results (not available on all tests)
-V,   --version          show version
-m N, --vm N             start N workers spinning on anonymous mmap
--vm-bytes N       allocate N bytes per vm worker (default 256MB)
--vm-hang N        sleep N seconds before freeing memory
--vm-keep          redirty memory instead of reallocating
--vm-ops N         stop when N vm bogo operations completed
--vm-locked        lock the pages of the mapped region into memory
--vm-method m      specify stress vm method m, default is all
--vm-populate      populate (prefault) page tables for a mapping
--wait N           start N workers waiting on child being stop/resumed
--wait-ops N       stop when N bogo wait operations completed
--zero N           start N workers reading /dev/zero
--zero-ops N       stop when N /dev/zero bogo read operations completed
Example: stress-ng --cpu8--io4--vm2--vm-bytes 128M --fork4--timeout 10s
Note: Sizes can be suffixed with B,K,M,G and times with s,m,h,d,y

7.3 容器的内存限制

Docker 可以强制执行硬性内存限制,即只允许容器使用指定的内存大小。

Docker 也可以执行非硬性内存限制,即允许容器可以使用尽可能多的内存,除非内核检测到主机上的内存不够用

7.3.1 内存相关选项

官文文档: https://docs.docker.com/config/containers/resource_constraints/

以下设置大部分的选项为正整数,支持后面加单位 b , k , m , g ,分别表示字节,千字节,兆字节或千兆字节

选项 描述
-m ,
--memory=
容器可以使用的最大物理内存量,硬限制,此选项最小允许值为
4m(4
MB),此项较常用
--memory-swap 允许此容器交换到磁盘的内存量,必须先用-m对内存限制才可以使用,详细说明如下
--memory-swappiness 设置容器使用交换分区的倾向性,值越高表示越倾向于使用swap分区,范围为0-100,0为能不用就不用,100为能用就用,N表示内存使用率达到N%时,就会使用swap空间
--memory-
reservation
允许指定小于--memory的软限制 ,当Docker检测到主机上的争用或内存不足时会激活该限制,如果使用-- memory-reservation,则必须将其设置为低于--memory才能使其优先生效。 因为它是软限制,所以不能保证容器不超过限制
--kernel-memory 容器可以使用的最大内核内存量,最小为4m,由于内核内存与用户空间内存隔离,因此无法与用户空间内存直接交换,因此内核内存不足的容器可能会阻塞宿主机资源,这会对主机和其他容器或者其他服务进程产生影响,因此不建议设置内核内存大小
--oom-kill-disable 默认情况下,如果发生内存不足(OOM)错误,则内核将终止容器中的进程。要更改此行为,请使用该
--oom-kill-disable选项。建议仅在设置了该
-m/--memory选项的容器上禁用OOM。如果
-m未设置该标志,则主机可能会用完内存,内核可能需要终止主机系统的进程以释放内存

范例:

[root@ubuntu1804 ~]#docker run -e MYSQL_ROOT_PASSWORD=123456 -it --rm -m 1g --
oom-kill-disable mysql:5.7.30
2020-02-0413:11:54+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL
Server 5.7.29-1debian9 started.
2020-02-0413:11:54+00:00 [Note] [Entrypoint]: Switching to dedicated user
'mysql'
2020-02-0413:11:54+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL
Server 5.7.29-1debian9 started.
2020-02-0413:11:54+00:00 [Note] [Entrypoint]: Initializing database files
Version: '5.7.29'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL
Community Server (GPL)

范例:

[root@ubuntu1804 ~]#sysctl  -a |grep swappiness
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.docker0.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
vm.swappiness =60

7.3.2 swap 限制

kubernets 对swap的要求

K8s 1.8.3更新日志:

宿主机开启交换分区,会在安装之前的预检查环节提示相应错误信息: https://github.com/kubernete s/kubernetes/blob/release-1.8/CHANGELOG-1.8.md

docker run 命令可以使用--memory-swap 选项控制swap的使用

--memory-swap#只有在设置了 --memory 后才会有意义。使用 Swap,可以让容器将超出限制部分的内存
置换到磁盘上,WARNING:  经常将内存交换到磁盘的应用程序会降低性能

不同的--memory-swap 设置会产生不同的效果:

--memory-
swap
--
memory
功能
正数S 正数M 容器可用内存总空间为S,其中ram为M,swap为S-M,若S=M,则无可用swap资源
0 正数M 相当于未设置swap(unset)
unset 正数M 若主机(Docker Host)启用于swap ,则容器的可用swap为2*M
-1 正数M 若主机(Docker Host)启用了swap ,则容器可使用最大至主机上所有swap空间
-memory-swap#值为正数,那么--memory 和--memory-swap 都必须要设置,--memory-swap 表示
你能使用的内存和 swap 分区大小的总和,例如:   --memory=300m, --memory-swap=1g, 那么该容
器能够使用 300m 物理内存和 700m swap,即--memory 是实际物理内存大小值不变,而 swap 的实际大
小计算方式为(--memory-swap)-(--memory)=容器可用 swap
--memory-swap#如果设置为 0,则忽略该设置,并将该值视为未设置,即未设置交换分区
--memory-swap#如果等于--memory 的值,并且--memory 设置为正整数,容器无权访问 swap
-memory-swap#如果未设置,如果宿主机开启了 swap,则实际容器的swap 值最大为 2x( --
memory),即两倍于物理内存大小,例如,如果--memory="300m"与--memory-swap没有设置,该容器可
以使用300m总的内存和600m交撒空间,但是并不准确(在容器中使用free 命令所看到的 swap 空间并不精
确,毕竟每个容器都可以看到具体大小,宿主机的 swap 是有上限的,而且不是所有容器看到的累计大小)
--memory-swap#如果设置为-1,如果宿主机开启了 swap,则容器可以使用主机上 swap 的最大空间

注意: 在容器中执行free命令看到的是宿主机的内存和swap使用,而非容器自身的swap使用情况

范例: 在容器中查看内存

[root@ubuntu1804 ~]#free
              total        used        free      shared  buff/cache   available
Mem:        304948427848413529321038414180682598932
Swap:       195174001951740
[root@ubuntu1804 ~]#docker run -it --rm -m 2G centos:centos7.7.1908 bash
[root@f5d387b5022f /]# free
              total        used        free      shared  buff/cache   available
Mem:        304948431031213208841054414182882566872
Swap:       195174001951740
[root@f5d387b5022f /]#

7.3.3 使用stress-ng测试内存限制

假如一个容器未做内存使用限制,则该容器可以利用到系统内存最大空间,默认创建的容器没有做内存资源限制。

范例: 默认一个workers 分配256M内存,2个即占512M内存

[root@ubuntu1804 ~]#docker run --name c1 -it --rm lorel/docker-stress-ng --vm 2
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
#因上一个命令是前台执行,下面在另一个终端窗口中执行,可以看到占用512M左右内存
[root@ubuntu1804 ~]#docker stats
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
fd184869ff7e        c1                  91.00%              524.3MiB / 962MiB
54.50%              766B / 0B           860kB / 0B          5

范例: 指定内存最大值

[root@ubuntu1804 ~]#docker run --name c1 -it --rm -m 300m lorel/docker-stress-ng
--vm 2
WARNING: Your kernel does not support swap limit capabilities or the cgroup is
not mounted. Memory limited without swap.
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
[root@ubuntu1804 ~]#vim /etc/default/grub
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1  net.ifnames=0"
[root@ubuntu1804 ~]#update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.15.0-29-generic
Found initrd image: /boot/initrd.img-4.15.0-29-generic
done
[root@ubuntu1804 ~]#reboot
[root@ubuntu1804 ~]#docker run --name c1 -it --rm -m 300m lorel/docker-stress-ng
--vm 2
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
#在另一个终端窗口执行
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
6a93f6b22034        c1                  27.06%              297.2MiB / 300MiB
99.07%              1.45kB / 0B         4.98GB / 5.44GB     5

范例:

[root@ubuntu1804 ~]#docker run --name c2 -it --rm  lorel/docker-stress-ng --vm 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 vm
#一次性查看资源使用情况
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
fd5fff3c04f7        c2                  21.20%              591.1MiB / 962MiB
61.45%              1.31kB / 0B         1.07GB / 46.6MB     9
[root@ubuntu1804 ~]#

范例: 容器占用内存造成OOM

[root@ubuntu1804 ~]#docker run -it --rm --name c1  lorel/docker-stress-ng --vm 6
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 6 vm
#另一个终端窗中同时执行下面命令
[root@ubuntu1804 ~]#docker run  -it --rm  --name c2 lorel/docker-stress-ng --vm
6
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 6 vm
[root@ubuntu1804 ~]#docker stats
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
f33cebf5b55d        c2                  ---- / --
--------
b14b597c5a4f        cool_banach         ---- / --
--------
#观察日志出现OOM现象
[root@ubuntu1804 ~]#tail  /var/log/syslog
Feb  422:59:40 ubuntu1804 kernel: [  785.928835] [ 2575]     0257567104
39218544768229061000 stress-ng-vm
Feb  422:59:40 ubuntu1804 kernel: [  785.928836] [ 2594]     0259467104
3750340960077251000 stress-ng-vm
Feb  422:59:40 ubuntu1804 kernel: [  785.928837] [ 2601]     0260167104
3881543827297791000 stress-ng-vm
Feb  422:59:40 ubuntu1804 kernel: [  785.928838] [ 2602]     026021568
8614915201000 stress-ng-vm
Feb  422:59:40 ubuntu1804 kernel: [  785.928839] [ 2610]     026101568
8614915201000 stress-ng-vm
Feb  422:59:40 ubuntu1804 kernel: [  785.928840] [ 2614]     026141157
1745324800 update-motd-hwe
Feb  422:59:40 ubuntu1804 kernel: [  785.928841] [ 2615]     026153100
156144000 apt-config
Feb  422:59:40 ubuntu1804 kernel: [  785.928842] Out of memory: Kill process
2570 (stress-ng-vm) score 1090 or sacrifice child
Feb  422:59:40 ubuntu1804 kernel: [  785.929493] Killed process 2570 (stress-
ng-vm) total-vm:268416kB, anon-rss:170352kB, file-rss:632kB, shmem-rss:28kB
Feb  422:59:40 ubuntu1804 kernel: [  786.018319] oom_reaper: reaped process
2570 (stress-ng-vm), now anon-rss:0kB, file-rss:0kB, shmem-rss:28kB

范例: 查看内存限制

#启动两个工作进程,每个工作进程最大允许使用内存 256M,且宿主机不限制当前容器最大内存
[root@ubuntu1804 ~]#docker run  -it --name c1 --rm  lorel/docker-stress-ng --vm
2
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
[root@ubuntu1804 ~]#docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED
        STATUS              PORTS               NAMES
13e46172e1ae        lorel/docker-stress-ng   "/usr/bin/stress-ng …"24 seconds
ago      Up 22 seconds                           gallant_moore
[root@ubuntu1804 ~]#ls /sys/fs/cgroup/memory/docker/
13e46172e1ae8593569f05a3bebc7b41b7839da44369d43b29102661364ac2cd
memory.kmem.tcp.limit_in_bytes      memory.numa_stat
cgroup.clone_children
memory.kmem.tcp.max_usage_in_bytes  memory.oom_control
cgroup.event_control
memory.kmem.tcp.usage_in_bytes      memory.pressure_level
cgroup.procs
memory.kmem.usage_in_bytes          memory.soft_limit_in_bytes
memory.failcnt
memory.limit_in_bytes               memory.stat
memory.force_empty
memory.max_usage_in_bytes           memory.swappiness
memory.kmem.failcnt
memory.memsw.failcnt                memory.usage_in_bytes
memory.kmem.limit_in_bytes
memory.memsw.limit_in_bytes         memory.use_hierarchy
memory.kmem.max_usage_in_bytes
memory.memsw.max_usage_in_bytes     notify_on_release
memory.kmem.slabinfo
memory.memsw.usage_in_bytes         tasks
memory.kmem.tcp.failcnt
memory.move_charge_at_immigrate
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/13e46172e1ae8593569f05a3bebc7b41b7839da44369d43b291
02661364ac2cd/memory.limit_in_bytes
9223372036854771712
[root@ubuntu1804 ~]#echo 2^63|bc
9223372036854775808

范例: 内存限制200m

#宿主机限制容器最大内存使用:
[root@ubuntu1804 ~]#docker run  -it --rm  --name c1 -m 200M lorel/docker-stress-
ng --vm 2 --vm-bytes 256M
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
f69729b2acc1        sleepy_haibt        85.71%              198MiB / 200MiB
98.98%              1.05kB / 0B         697MB / 60.4GB      5
[root@ubuntu1804 ~]#
#查看宿主机基于 cgroup 对容器进行内存资源的大小限制
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/f69729b2acc16e032658a4efdab64d21ff97dcb6746d1cef451
ed82d5c98a81f/memory.limit_in_bytes
209715200
[root@ubuntu1804 ~]#echo 209715200/1024/1024|bc
200
#动态修改内存限制
[root@ubuntu1804 ~]#echo 300*1024*1024|bc
314572800
[root@ubuntu1804 ~]#echo 314572800 >
/sys/fs/cgroup/memory/docker/f69729b2acc16e032658a4efdab64d21ff97dcb6746d1cef451
ed82d5c98a81f/memory.limit_in_bytes
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/f69729b2acc16e032658a4efdab64d21ff97dcb6746d1cef451
ed82d5c98a81f/memory.limit_in_bytes
314572800
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
f69729b2acc1        sleepy_haibt        76.69%              297.9MiB / 300MiB
99.31%              1.05kB / 0B         1.11GB / 89.1GB     5
#通过echo 命令可以改内存限制的值,但是可以在原基础之上增大内存限制,缩小内存限制会报错write
error: Device or resource busy
[root@ubuntu1804 ~]#echo 209715200 >
/sys/fs/cgroup/memory/docker/f69729b2acc16e032658a4efdab64d21ff97dcb6746d1cef451
ed82d5c98a81f/memory.limit_in_bytes
-bash: echo: write error: Device or resource busy
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/f69729b2acc16e032658a4efdab64d21ff97dcb6746d1cef451
ed82d5c98a81f/memory.limit_in_bytes
314572800

范例: 内存大小软限制

[root@ubuntu1804 ~]#docker run -it --rm  -m 256m --memory-reservation 128m --
name c1 lorel/docker-stress-ng --vm 2 --vm-bytes 256M
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
aeb38acde581        c1           72.45%              253.9MiB / 256MiB   99.20%
             976B / 0B           9.47GB / 39.4GB     5

# 查看硬限制

[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/aeb38acde58155d421f998a54e9a99ab60635fe00c9070da050
cc49a2f62d274/memory.limit_in_bytes
268435456

# 查看软限制

[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/aeb38acde58155d421f998a54e9a99ab60635fe00c9070da050
cc49a2f62d274/memory.soft_limit_in_bytes
134217728

# 软限制不能高于硬限制

[root@ubuntu1804 ~]#docker run -it --rm  --name c1 -m 256m --memory-reservation
257m --name c1 lorel/docker-stress-ng --vm 2 --vm-bytes 256M
docker: Error response from daemon: Minimum memory limit can not be less than
memory reservation limit, see usage.
See 'docker run --help'.

关闭OOM 机制:

# docker run -it --rm  -m 256m --oom-kill-disable --name c1  lorel/docker-stress-
ng --vm 2 --vm-bytes 256M
# cat /sys/fs/cgroup/memory/docker/容器 ID/memory.oom_control
oom_kill_disable 1
under_oom 1
oom_kill 0

范例: 关闭OOM机制

#查看docker OOM机制默认值
[root@ubuntu1804 ~]#cat /sys/fs/cgroup/memory/docker/memory.oom_control
oom_kill_disable 0
under_oom 0
oom_kill 0
#启动容器时关闭OOM机制
[root@ubuntu1804 ~]#docker run -it --rm  -m 200m --name c1 --oom-kill-disable
lorel/docker-stress-ng --vm 2 --vm-bytes 256M
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
b655d88228c0        silly_borg          0.00%               197.2MiB / 200MiB
98.58%              1.31kB / 0B         1.84MB / 484MB      5
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/b655d88228c04d7db6a6ad833ed3d05d4cd596ef09834382e17
942db0295dc0c/memory.oom_control
oom_kill_disable 1
under_oom 1
oom_kill 0
[root@ubuntu1804 ~]#

交换分区限制:

# docker run -it --rm  -m 256m  --memory-swap 512m  --name c1  centos bash
# cat /sys/fs/cgroup/memory/docker/容器 ID/memory.memsw.limit_in_bytes 536870912
#返回值

范例:

[root@ubuntu1804 ~]#docker run -it --rm --name c1 -m 200m --memory-swap 512m
lorel/docker-stress-ng --vm 2
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 2 vm
#宿主机cgroup验证:
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/memory/docker/23733a0cafa21f3e94ca8c96110978b12e53076261f1b92fd20
52bafe659c8ab/memory.memsw.limit_in_bytes
536870912

7.4 容器的 CPU 限制

7.4.1 容器的 CPU 限制介绍

官方文档说明: https://docs.docker.com/config/containers/resource_constraints/

一个宿主机,有几十个核心的CPU,但是宿主机上可以同时运行成百上千个不同的进程用以处理不同的任务,多进程共用一个 CPU 的核心为可压缩资源,即一个核心的 CPU 可以通过调度而运行多个进程, 但是同一个单位时间内只能有一个进程在 CPU 上运行,那么这么多的进程怎么在 CPU 上执行和调度的呢?

Linux kernel 进程的调度基于CFS(Completely Fair Scheduler),完全公平调度

服务器资源密集型

  • CPU 密集型的场景: 计算密集型任务的特点是要进行大量的计算,消耗CPU 资源,比如计算圆周率、数据处理、对视频进行高清解码等等,全靠CPU 的运算能力。

  • IO 密集型的场景: 涉及到网络、磁盘IO 的任务都是IO 密集型任务,这类任务的特点是 CPU 消耗很少,任务的大部分时间都在等待 IO 操作完成(因为 IO 的速度远远低于 CPU 和内存的速度),比如 Web 应用,高并发,数据量大的动态网站来说,数据库应该为IO 密集型

CFS原理

cfs定义了进程调度的新模型,它给cfs_rq(cfs的run queue)中的每一个进程安排一个虚拟时钟 vruntime。如果一个进程得以执行,随着时间的增长,其vruntime将不断增大。没有得到执行的进程 vruntime不变, 而调度器总是选择vruntime跑得最慢的那个进程来执行。这就是所谓的“完全公平”。为了区别不同优先级的进程,优先级高的进程vruntime增长得慢,以至于它可能得到更多的运行机会。 CFS的意义在于, 在一个混杂着大量计算型进程和IO交互进程的系统中,CFS调度器相对其它调度器在对待IO交互进程要更加友善和公平。

7.4.2 配置默认的CFS调度程序

默认情况下,每个容器对主机的CPU周期的访问都是不受限制的。可以设置各种约束,以限制给定容器对主机CPU周期的访问。大多数用户使用并配置默认的CFS调度程序。在Docker 1.13及更高版本中,还可以配置 realtime scheduler。

CFS是用于常规Linux进程的Linux内核CPU调度程序。通过几个运行时标志,可以配置对容器拥有的CPU 资源的访问量。使用这些设置时,Docker会在主机上修改容器cgroup的设置。

选项 描述
--cpus= 指定一个容器可以使用多少个可用的CPU核心资源。例如,如果主机有两个
CPU,如果设置了
--cpus="1.5",则可以保证容器最多使用1.5个的CPU(如果是4核CPU,那么还可以是4核心上每核用一点,但是总计是1.5核心的CPU)。这相当于设置
--cpu-period="100000"和
--cpu-quota="150000"。此设置可在
Docker 1.13及更高版本中可用,目的是替代--cpu-period和--cpu-quota两个参数,从而使配置更简单,但是最大不能超出宿主机的CPU总核心数(在操作系统看到的CPU超线程后的数值),此项较常用
--cpu-
period=
过时选项,指定CPU CFS调度程序周期,必须与
--cpu-quota一起使用 。默认为
100微秒。大多数用户不会更改默认设置。如果使用Docker 1.13或更高版本,
请改用
--cpus
--cpu-quota= 过时选项,在容器上添加CPU CFS配额,计算方式为cpu-quota / cpu-period的结果值,docker1.13及以上版本通常使用--cpus设置此值
--cpuset-
cpus
用于指定容器运行的CPU编号,也就是所谓的CPU绑定。如果一个或多个
CPU,则容器可以使用逗号分隔的列表或用连字符分隔的CPU范围。第一个CPU
的编号为0。有效值可能是
0-3(使用第一,第二,第三和第四CPU)或
1,3(使用第二和第四CPU)
--cpu-shares 用于设置cfs中调度的相对最大比例权重,cpu-share的值越高的容器,将会分得更多的时间片(宿主机多核CPU总数为100%,假如容器A为1024,容器B为
2048,那么容器B将最大是容器A的可用CPU的两倍),默认的时间片
1024,最大262144。这是一个软限制。注意:进程数要多个CPU的核数才能看到效果,此值不能设置太小

7.4.3 使用 Stress-ng 测试 CPU 配置

范例: 查看 stress-n 关于cpu的帮助

[root@ubuntu1804 ~]#docker run -it --rm  --name c1  lorel/docker-stress-ng
|grep cpu
-c N, --cpu N            start N workers spinning on sqrt(rand())
--cpu-ops N        stop when N cpu bogo operations completed
-l P, --cpu-load P       load CPU by P %%, 0=sleep, 100=full load (see -c)
--cpu-method m     specify stress cpu method m, default is all
Example: stress-ng --cpu8--io4--vm2--vm-bytes 128M --fork4--timeout 10s
[root@ubuntu1804 ~]#

范例: 不限制容器CPU

[root@ubuntu1804 ~]#lscpu |grep CPU
CPU op-mode(s):      32-bit, 64-bit
CPU(s):              6
On-line CPU(s) list: 0-5
CPU family:          6
Model name:          Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz
CPU MHz:             2494.236
NUMA node0 CPU(s):   0-5
#占用4个CPU资源.但只是平均的使用CPU资源
[root@ubuntu1804 ~]#docker run -it --rm  --name c1 lorel/docker-stress-ng  --cpu
4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
818a85e1da2f        frosty_taussig      595.57%             1.037GiB / 2.908GiB
35.64%              1.12kB / 0B         0B / 0B             13
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/cpuset/docker/818a85e1da2f9a4ef297178a9dc09b338b2308108195ad8d419
7a1c47febcbff/cpuset.cpus
0-5
[root@ubuntu1804 ~]#top

范例: 限制使用CPU

[root@ubuntu1804 ~]#docker run -it --rm  --name c1 --cpus 1.5  lorel/docker-
stress-ng  --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
9f8b2e693113        busy_hodgkin        147.71%             786.8MiB / 2.908GiB
26.42%              836B / 0B           0B / 0B             13
[root@ubuntu1804 ~]#top

范例: 限制CPU

[root@ubuntu1804 ~]#docker run -it --rm  --name c1 --cpu-quota 2000 --cpu-period
1000  lorel/docker-stress-ng  --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                     CPU %               MEM USAGE /
LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
bd949bb6698e        affectionate_chebyshev   185.03%             1.037GiB /
2.908GiB   35.64%              836B / 0B           0B / 0B             13
[root@ubuntu1804 ~]#

范例: 绑定CPU

#一般不建议绑在0号CPU上,因0号CPU一般会较忙
[root@ubuntu1804 ~]#docker run -it --rm  --name c1 --cpus 1.5  --cpuset-cpus
2,4-5 lorel/docker-stress-ng  --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu1804 ~]#ps axo pid,cmd,psr |grep stress
1964 /usr/bin/stress-ng --cpu42
1996 /usr/bin/stress-ng --cpu45
1997 /usr/bin/stress-ng --cpu42
1998 /usr/bin/stress-ng --cpu44
1999 /usr/bin/stress-ng --cpu42
2002grep--color=auto stress      1
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
585879094e73        hungry_albattani    154.35%             1.099GiB / 2.908GiB
37.79%              906B / 0B           0B / 0B             13
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/cpuset/docker/585879094e7382d2ef700947b4454426eee7f943f8d1438fe42
ce34df789227b/cpuset.cpus
2,4-5
[root@ubuntu1804 ~]#top

范例: 多个容器的CPU利用率比例

#同时开两个容器
[root@ubuntu1804 ~]#docker run -it --rm  --name c1 --cpu-shares 1000
lorel/docker-stress-ng  --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu1804 ~]#docker run -it --rm  --name c2 --cpu-shares 500
lorel/docker-stress-ng  --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
#注意:进程数要多于CPU的核数才能看到效果,如果两个容器使用的CPU总数不超过CPU实际的核心数,两个容
器都显示400%
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
a1d4c6e6802d        c2                  195.88%             925.3MiB / 2.908GiB
31.07%              726B / 0B           0B / 0B             13
d5944104aff4        c1                  398.20%             1.036GiB / 2.908GiB
35.64%              906B / 0B           0B / 0B             13
[root@ubuntu1804 ~]#
#查看c1容器的cpu利用比例
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/cpu,cpuacct/docker/d5944104aff40b7b76f536c45a68cd4b98ce466a73416b
68819b9643e3f49da7/cpu.shares
1000
#查看c2容器的cpu利用比例
[root@ubuntu1804 ~]#cat
/sys/fs/cgroup/cpu,cpuacct/docker/a1d4c6e6802d1b846b33075f3c1e1696376009e85d9ff8
756f9a8d93d3da3ca6/cpu.shares
500
#再打开新的容器,cpu分配比例会动态调整
[root@ubuntu1804 ~]#docker run -it --rm  --name c3 --cpu-shares 2000
lorel/docker-stress-ng  --cpu 4
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
c2d54818e1fe        c3                  360.15%             664.5MiB / 2.908GiB
22.31%              726B / 0B           1.64GB / 150MB      13
a1d4c6e6802d        c2                  82.94%              845.2MiB / 2.908GiB
28.38%              936B / 0B           103MB / 4.54MB      13
d5944104aff4        c1                  181.18%             930.1MiB / 2.908GiB
31.23%              1.12kB / 0B         303MB / 19.8MB      13

范例: 动态调整cpu shares值

[root@ubuntu1804 ~]#echo 2000 >
/sys/fs/cgroup/cpu,cpuacct/docker/a1d4c6e6802d1b846b33075f3c1e1696376009e85d9ff8
756f9a8d93d3da3ca6/cpu.shares
[root@ubuntu1804 ~]#docker stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT
MEM %               NET I/O             BLOCK I/O           PIDS
a1d4c6e6802d        c2                  389.31%             1.037GiB / 2.908GiB
35.64%              1.01kB / 0B         1.16GB / 14MB       13
d5944104aff4        c1                  200.28%             1.036GiB / 2.908GiB
35.63%              1.19kB / 0B         2.66GB / 26.7MB     13
[root@ubuntu1804 ~]#

8 常见面试题

  • Docker 打镜像时需不需要对容器内操作系统进行内核参数优化?

  • docker 运行容器之后,报如图所示错误,使用docker ps命令查看该容器的状态为Created,请分析原因并给出解决办法?

  • Dockerfile有哪些指令?

  • Docker 有哪些常用指令?

  • 两个服务器装了 Docker,双方的容器之间如何实现通信,有几种方式,不同主机的两个容器之间能够通信吗,怎么实现?

  • Docker 的网络模式有几种?

  • Dockerfile LNMP要求nginx,php-fpm编译安装的镜像