小白也能读懂的Docker入门教程(上)

2013年发布至今,Docker已经成为了炙手可热的一门容器技术,一直广受瞩目,被认为可能会改变软件行业。我相信只要身处于IT行业的人,一定会对Docker感兴趣,想学学Docker,毕竟技多不压身。但是许多人并不清楚Docker到底是什么,要解决什么问题,好处又在哪里?接下来,就让笔者好好详细介绍一下,帮助大家去理解它,还有一些简单的日常实列,可以快速的帮助大家真正的使用它。

1、Docker是什么?

首先Docker是一个在2013年开源的应用程序并且是一个基于go语言编写是一个开源的PAAS服务(Platform as a Service,平台即服务的缩写),go语言是由google开发,docker公司最早叫dotCloud后由于Docker开源后大受欢迎就将公司改名为Docker Inc,总部位于美国加州的旧金山,Docker是基于linux内核实现,Docker最早采用LXC技术(Linux Container 的简写,LXC是Linux原生支持的容器技术,可以提供轻量级的虚拟化,可以说 docker 就是基于LXC发展起来的,提供LXC 的高级封装,发展标准的配置方法),而虚拟化技术KVM(Kernel-based Virtual Machine)基于模块实现,Docker后改为自己研发并开源的runc技术运行容器。

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

2、Docker的组成

Docker主机(Host):一个物理机或虚拟机,用于运行Docker服务进程和容器。

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

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

Docker仓库(Registry):保存镜像的仓库,类似于git或SVN这样的版本控制系统

Docker镜像(Images):镜像可以理解为创建实例使用的模板。

Docker容器(Container):容器是从镜像生成对外提供服务的一个或一组服务

image.png

3、Dcoker和虚拟机主要区别

3253626c-f3a6-4873-b0fd-a294b868f233.png

虚拟化技术是一个通用的概念,在不同领域有着不同的理解。所以就拿维基百科上的定义来说吧:

在计算机技术中,虚拟化是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以用比原来的组态更好的方式来应用这些资源。

可见,虚拟化的核心是对资源进行抽象,目标往往是为了在同一个主机上运行多个系统或应用,从而提高系统资源的利用率,同时带来降低成本、方便管理和容错容灾等好处

以下是虚拟化的一些种类:

  • 完全虚拟化。虚拟机模拟完整的底层硬件环境和特权指令的执行过程,客户操作系统无需进行修改。例如著名的VMware workstation
  • 硬件辅助虚拟化。利用硬件(主要是CPU)辅助支持(目前是X86体系结构上可用的硬件辅助虚拟化技术包括Intel-VT和AMD-V)处理敏感指令来实现完全虚拟化的功能,客户操作系统无需修改。
  • 部分虚拟化。只针对部分硬件资源进行虚拟化,客户操作系统需要进行修改。现在有些虚拟化技术的早期版本支持部分虚拟化
  • 超虚拟化。部分硬件接口以软件的形式提供给客户机操作系统,客户操作系统需要进行修改
  • 操作系统级虚拟化。内核通过创建多个虚拟的操作系统实列(内核和库)来隔离不同的进程。Docker属于这个范畴。


下图是Docker虚拟化和传统虚拟化的区别:

21a0c158-cc00-4be2-a32f-ad921c7a541c.jpg

但是,如上图一个宿主机运行N个容器,多个容器带来的以下问题是怎么解决的呢?

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

2.一个docker主进程内的各个容器都是其子进程,那么实现同一个主进程下不同类型的子进程?各个进程间通信能相互访问吗?

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

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

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

以上这些问题如何解决?

3.1 Linux Namespace技术

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

隔离类型 功能 系统调用参数 内核版本
MNT Namespace 提供磁盘挂载点和文件系统的隔离能力 CLONE_NEWNS Linux 2.4.19
IPC Namespace 提供进程间通信的隔离能力 CLONE_NEWIPC Linux 2.6.19
UTS Namespace 提供主机名隔离能力 CLONE_NEWUTS Linux 2.6.19
PID Namespace 提供进程隔离能力 CLONE_NEWPID Linux 2.6.24
NET Namespace 提供网络隔离能力 CLONE_NEWNET Linux 2.6.29
USER Namespace 提供用户隔离能力 CLONE_NEWUSER Linux 3.8

3.1.1 MNT Namespace

每个容器都要有独立的根文件系统有独立的用户空间,以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是ubuntu 的服务器,可以在里面启动一个centos运行环境的容器并且在容器里面启动一个Nginx服务,此 Nginx运行时使用的运行环境就是centos系统目录的运行环境,但是在容器里面是不能访问宿主机的资源,宿主机是使用了chroot技术把容器锁定到一个指定的运行目录里面。

例如:/var/lib/containerd/io.containerd.runtime.v1.linux/moby/容器ID

启用容器验证过程:

  1. [root@docker-100 ~]# docker pull nginx
  2. [root@docker-100 ~]# docker images
  3. REPOSITORY TAG IMAGE ID CREATED SIZE
  4. nginx latest f6d0b4767a6c 16 hours ago 133MB
  5. [root@docker-100 ~]# docker run -it -d -p 80:80 nginx

验证容器的根文件系统:

image-20210113104313943.png

3.1.2 IPC Namespace

一个容器内的进程间通信,允许一个容器内的不同进程的(内存、缓存等)数据访问,但是不能跨容器访问其他容器的数据。

3.1.3 UTS Namespace

UTS namespace (UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识,其中包含了hostname和域名

domainname ,它使得一个容器拥有属于自己hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器。

image-20210113105010999.png

3.1.4 PID Namespace

Linux系统中,有一个PID为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其下属的子进程,那么多个容器的进程通PID namespace进程隔离(比如PID编号重复、器内的主进程生成与回收子进程等)。

例如:下图是在一个容器内使用top命令看到的PID为1的进程是nginx:

image-20210113105313225.png

容器内的Nginx主进程与工作进程:

image-20210113105356365.png

3.1.5 Net Namespace

每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用network namespace启动一个vethX接口,这样你的容器将拥有它自己的桥接ip地址,通常是docker0,而 docker0实质就是Linux的虚拟网桥,网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。

3.1.5.1 查看宿主机的网卡信息
  1. [root@docker-100 ~]# ifconfig
  2. docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  3. inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
  4. inet6 fe80::42:d1ff:fe43:1822 prefixlen 64 scopeid 0x20<link>
  5. ether 02:42:d1:43:18:22 txqueuelen 0 (Ethernet)
  6. RX packets 2987 bytes 124443 (121.5 KiB)
  7. RX errors 0 dropped 0 overruns 0 frame 0
  8. TX packets 4567 bytes 8665267 (8.2 MiB)
  9. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  10. ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  11. inet 10.0.0.100 netmask 255.255.255.0 broadcast 10.0.0.255
  12. inet6 fe80::bf9e:f0b7:5511:fe88 prefixlen 64 scopeid 0x20<link>
  13. ether 00:0c:29:10:7b:d3 txqueuelen 1000 (Ethernet)
  14. RX packets 168900 bytes 242033949 (230.8 MiB)
  15. RX errors 0 dropped 0 overruns 0 frame 0
  16. TX packets 45362 bytes 3605046 (3.4 MiB)
  17. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  18. lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
  19. inet 127.0.0.1 netmask 255.0.0.0
  20. inet6 ::1 prefixlen 128 scopeid 0x10<host>
  21. loop txqueuelen 1 (Local Loopback)
  22. RX packets 72 bytes 5744 (5.6 KiB)
  23. RX errors 0 dropped 0 overruns 0 frame 0
  24. TX packets 72 bytes 5744 (5.6 KiB)
  25. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  26. veth5176cd1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  27. inet6 fe80::c881:90ff:fe60:50b5 prefixlen 64 scopeid 0x20<link>
  28. ether ca:81:90:60:50:b5 txqueuelen 0 (Ethernet)
  29. RX packets 2987 bytes 166261 (162.3 KiB)
  30. RX errors 0 dropped 0 overruns 0 frame 0
  31. TX packets 4575 bytes 8665915 (8.2 MiB)
  32. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

3.1.5.2 查看容器内的网卡信息
  1. [root@docker-100 ~]# docker exec -it 6055d5c1fc42 bash
  2. root@6055d5c1fc42:/# ifconfig
  3. eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  4. inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
  5. ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
  6. RX packets 4710 bytes 8922175 (8.5 MiB)
  7. RX errors 0 dropped 0 overruns 0 frame 0
  8. TX packets 3086 bytes 171795 (167.7 KiB)
  9. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  10. lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
  11. inet 127.0.0.1 netmask 255.0.0.0
  12. loop txqueuelen 1 (Local Loopback)
  13. RX packets 0 bytes 0 (0.0 B)
  14. RX errors 0 dropped 0 overruns 0 frame 0
  15. TX packets 0 bytes 0 (0.0 B)
  16. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

3.1.5.3 逻辑网络图

image.png

3.1.5.4 宿主机iptables规则

image-20210113110552650.png

image-20210113110716252.png

3.1.6 USER Namespace

各个容器内可能会出现重名的用户和用户组名称,或重复的用户UID或者GID,那么怎么隔离各个容器内的用户空间呢?

User Namespace允许在各个宿主机的各个容器空间内创建相同的用户名以及相同的用户UID和GID,只是会把用户的作用范围限制在每个容器内,即A容器和B容器可以有相同的用户名称和ID的账户,但是此用户的有效范围仅是当前容器内,不能访问另外一个容器内的文件系统,即相互隔离、互补影响、永不相见。

image-20210113110955878.png

3.2 Linux control groups

在一个容器,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如CPU、内存等,Linux Cgroups的全称是Linux Control Groups,它最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,以及将进程挂起和恢复等操作。

4、Docker的工作模式

Docker是一个C/S模式的架构,而Docker的后端是一个非常松耦合的架构,模块各司其职,并有机组合,支撑Docker的运行。

用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者。

而Docker Daemon作为Docker架构中的主体部分,首先提供Server的功能使其可以接受Docker Client的请求。而后Engine执行Docker内部的一系列工作,每一项工作都是以一个Job的形式存在。

Job的运行过程中,当需要容器镜像时,从Docker仓库中下载,并通过镜像管理驱动将下载镜像以Graph的形式存储。当需要为Docker创建网络环境时,通过网络管理驱动networkdriver创建并配置Docker容器网络环境。当需要限制Docker容器运行资源或执行用户指令等操作时,则通过execdrive来完成,而libcontainer是一项独立的容器管理包,networkdriver以及execdriver都是通过libcontainer来实现具体对容器进行的操作,当执行完运行容器的命令后,一个实际的Docker容器就处于运行状态,该容器拥有独立的文件系统,独立并且安全的运行环境等。

3c759d3d-f4c4-4854-ba81-0914dcef4ba8.jpg

总结:即使第一层镜像Base Image很大,比如1个G。但是每次增量的镜像层都控制在几十M,那启动速度也是秒级的

5、Docker的核心概念

  • 镜像(lmage)
    Docker的镜像是创建容器的基础,类似虚拟机的快照。可以理解为是一个面向Docker容器引擎的只读模板,比如:一个镜像可以是一个完整的centos操作系统环境,称为一个centos镜像。可以是一个安装mysql的应用程序,称之为一个mysql镜像等等。
    Docker提供了简单的机制来创建和更新现有的镜像,用户也可以从网上下载已经做好的应用镜像来直接使用
  • 容器(container)
    Docker的容器是从镜像创建的运行实例,它可以被启动、停止和删除。所创建的每一个容器都是相互隔离、互不可见的,可以保证平台的安全性。还可以把容器看作是一个简易版的linux环境,docker利用容器来运行和隔离应用。
  • 仓库(repository)
    Docker仓库是用来集中保存镜像的地方,当创建了自己的镜像之后,可以使用push命令将它上传到公共仓库或者私用仓库,这样一来当下次要在另一台机器上使用这个镜像的时候,只需要从仓库上下载下来就可以了
    仓库注册服务器是存放仓库的地方,其中包含了多个仓库,每个仓库集中存放某一类镜像,并且使用不同的标签来区分它们。目前最大的公共仓库是Docker hub,其中存放了数量庞大的镜像供用户下载使用。

6、为什么要用Docker

  • 快速部署:短时间内可以部署成百上千个应用,更快速交付到线上。
  • 高效虚拟化:不需要额外的hypervisor支持,直接基于linux实现应用虚拟化,相比虚拟机大幅提高性能和效率
  • 节省开支:提高服务器利用率,降低IT支出
  • 简化配置:将允许环境打包保存至容器,使用时直接启动即可
  • 快速迁移和扩展:可跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台。

7、安装docker

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

7.1 系统版本选择

Docker目前已经支持多种操作系统的安装运行,比如Ubuntu、CentOs、Redhat、Debian、Fedora,甚至是还支持了Mac 和 Windows,在linux系统上需要内核版本在3.10或以上,docker版本号之前一直是0.x版本或1.X版本,但是从2017年3月1号开始改为每个季度发布一次稳版,其版本号规则也统一变更为YY.MM,例如17.09表示是2017年9月份发布的,本次演示的操作系统使用Centos 7.4为例。

7.2 Dcoker版本选择

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

7.3 通过yum源安装

  1. # step 1: 安装必要的一些系统工具
  2. sudo yum install -y yum-utils device-mapper-persistent-data lvm2
  3. # Step 2: 添加软件源信息
  4. sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  5. # Step 3: 更新并安装Docker-CE
  6. sudo yum makecache fast
  7. sudo yum -y install docker-ce
  8. # Step 4: 开启Docker服务
  9. sudo systemctl restart docker
  10. sudo systemctl enable docker
  11. # Step 5:验证docker版本
  12. sudo docker version
  13. # 注意:
  14. # 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
  15. # vim /etc/yum.repos.d/docker-ee.repo
  16. # 将[docker-ce-test]下方的enabled=0修改为enabled=1
  17. #
  18. # 安装指定版本的Docker-CE:
  19. # Step 1: 查找Docker-CE的版本:
  20. # yum list docker-ce.x86_64 --showduplicates | sort -r
  21. # Loading mirror speeds from cached hostfile
  22. # Loaded plugins: branch, fastestmirror, langpacks
  23. # docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
  24. # docker-ce.x86_64 17.03.1.ce-1.el7.centos @docker-ce-stable
  25. # docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
  26. # Available Packages
  27. # Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
  28. # sudo yum -y install docker-ce-[VERSION]

安装好的docker系统有两个程序:docker服务端和docker客户端。其中docker服务端是一个服务进程,管理着所有的容器。Docker客户端则扮演着docker服务端的远程控制器,可以用来控制docker的服务端进程。大部分情况下docker服务端和客户端运行在一台机器上。

8、Docker镜像管理

Docker镜像含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于创建并启动docker容器。

Docker镜像里面是一层层文件系统,叫做Union File System (Union FS联合文件系统),2004年由纽约州立大学石溪分校开发,联合文件系统可以将多个目录挂载到一起从而形成一整个虚拟文件系统,该虚拟文件系统的目录结构就像普通linux 的目录结构一样,docker 通过这些文件再加上宿主机的内核提供了一个linux 的虚拟环境,每一层文件系统我们叫做一层layer, 联合文件系统可以对每一层文件系统设置三种权限,只读(readonly)、 读写(readwrite) 和写出(whiteout-able), 但是docker 镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层也不需要知道里面有几层,结构如下:

image.png

一个典型的Linux 文件系统由bootfs和rootfs两部分组成,bootfs(boot file system)主要包含bootloader和kernel, bootloader 主要用于引导加载kernel,当kernel 被加载到内存中后bootfs 会被umount掉,rootfs (root file system)包含的就是典型Linux 系统中的/dev,/proc, /bin, /etc 等标准目录和文件,下图就是docker image中最基础的两层结构,不同的linux 发行版(如ubuntu和CentOS)在rootfs 这一层会有所区别。但是对于docker镜像通常都比较小,官方提供的centos基础镜像在200MB左右,一些其他版本的镜像甚至只有几MB,docker镜像直接调用宿主机的内核,镜像中只提供rootfs,也就是只需要包括最基本的命令、工具和程序库就可以了,比如alpine镜像,在5M左右。下图就是有两个不同的镜像在一个宿主机内核上实现不同的rootfs。

image.png

8.1、docker镜像加速配置

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

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

image-20210113123754335.png

  1. sudo mkdir -p /etc/docker
  2. sudo tee /etc/docker/daemon.json <<-'EOF'
  3. {
  4. "registry-mirrors": ["https://djz7vjm0.mirror.aliyuncs.com"]
  5. }
  6. EOF
  7. sudo systemctl daemon-reload
  8. sudo systemctl restart docker

8.2、搜索镜像

列如搜索centos的镜像

  1. [root@docker-100 ~]# docker search centos
  2. NAME DESCRIPTION STARS OFFICIAL AUTOMATED
  3. centos The official build of CentOS. 6370 [OK]
  4. ansible/centos7-ansible Ansible on Centos7 132 [OK]
  5. consol/centos-xfce-vnc Centos container with "headless" VNC session 125 [OK]
  6. jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - 117 [OK]
  7. centos/systemd systemd enabled base container. 92 [OK]
  8. centos/mysql-57-centos7 MySQL 5.7 SQL database server 87
  9. imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 58 [OK]
  10. 注释:
  11. NAME 镜像名称
  12. DESCRIPTION 描述
  13. STARS 星级
  14. OFFICIAL 是否官方创建
  15. AUTPMATED 是否主动创建
  16. 默认的输出结果会按照星级评价进行排序,表示该镜像受欢迎程度

8.3、下载镜像

  1. docker仓库将镜像下载到本地,命令格式如下:
  2. #docker pull 仓库服务器:端口/项目名称/镜像名称:tag(版本)号
  3. [root@docker-100 ~]# docker pull centos
  4. Using default tag: latest
  5. latest: Pulling from library/centos
  6. 7a0437f04f83: Pull complete
  7. Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
  8. Status: Downloaded newer image for centos:latest

8.4、查看镜像信息

  1. [root@docker-100 ~]# docker images
  2. 镜像属于的仓库 镜像的标签信息 镜像的唯一ID 镜像创建时间 镜像的大小
  3. REPOSITORY TAG IMAGE ID CREATED SIZE
  4. nginx latest f6d0b4767a6c 2 days ago 133MB
  5. centos latest 300e315adb2f 5 weeks ago 209MB

8.5、保存镜像到本地

当需要把一台机器上的镜像迁移到另一台机器上的时候,需要将镜像保存成本地文件,这一过程叫作导出镜像,可以使用docker save命令进行存出操作。之后就可以拷贝该文件到其他机器

  1. [root@docker-100 ~]# docker save -o /usr/local/src/centos.tar centos
  2. [root@docker-100 ~]# ls -l /usr/local/src/centos.tar
  3. -rw------- 1 root root 216535040 1 15 14:58 /usr/local/src/centos.tar

8.6、载入镜像

将存出的镜像从A机器拷贝到B机器,需要在B机器上使用该镜像,就可以将该导出文件导入到B机器的镜像库中,这一过程叫作载入镜像。

  1. [root@docker-100 ~]# docker load < /usr/local/src/centos.tar
  2. e15afa4858b6: Loading layer 215.8 MB/215.8 MB
  3. Loaded image: docker.io/centos:latest215.8 MB
  4. [root@docker-100 ~]# docker images
  5. REPOSITORY TAG IMAGE ID CREATED SIZE
  6. centos latest 300e315adb2f 5 weeks ago 209MB

8.7、删除镜像

  1. [root@docker-100 ~]# docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. nginx latest f6d0b4767a6c 2 days ago 133MB
  4. centos latest 300e315adb2f 5 weeks ago 209MB
  5. [root@docker-100 ~]# docker rmi 300e315adb2f #通过镜像的ID删除
  6. Untagged: centos:latest
  7. Untagged: centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
  8. Deleted: sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55
  9. Deleted: sha256:2653d992f4ef2bfd27f94db643815aa567240c37732cae1405ad1c1309ee9859
  10. [root@docker-100 ~]# docker images
  11. REPOSITORY TAG IMAGE ID CREATED SIZE
  12. nginx latest f6d0b4767a6c 2 days ago 133MB

8.8、常用镜像命令

e2023b3f-0261-4ec0-80ac-8b3f335d0b73.png

9、Docker容器操作

9.1 Docker容器常用选项

e31aada3-a692-408e-87da-6744a23fb12e.png

  1. --restart=always #重启docker-server之后,容器不会因此还停止,还会继续运行

9.2、容器的启动

  1. [root@docker-100 ~]# docker run -it -d centos bash
  2. 8d1bfecc1da7ca83202e1d3e3008a23928fd14778e542f209fe9368a78aa0323
  3. 注释:
  4. docker run #启动容器
  5. --name #指定容器的名称
  6. -t #让Docker分配一个伪终端
  7. -i #让容器的输入保存打开
  8. -d #以后台的方式运行容器
  9. --rm #退出后即删除容器
  10. -e #指定环境变量,容器中可以使用该环境变量
  11. -p #指定端口
  12. -P #随机端口
  13. -v #给容器挂载存储卷,挂载到容器的某个目录
  14. --net #指定容器网络设置
  15. centos #指定运行的docker镜像
  16. bash #指定运行的进程
  17. 注意:如果指定的镜像(centos)没有,docker run也会自动的从docker仓库中下载下来,并启动。其实docker run就是docker createdocker start的结合体
  18. 当利用docker run来创建并启动容器时,docker在后台运行的标准操作包括:
  19. 1)检查本地是否存在指定的镜像,不存在就从公有仓库下载
  20. 2)利用镜像创建并启动一个容器
  21. 3)分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  22. 4)从宿主机配置的网桥接口中桥接一个虚拟接口到容器中去
  23. 5)从地址池配置一个IP地址给容器
  24. 6)执行用户指定的应用程序
  25. 7)执行完毕后容器被终止
  26. #显示正在运行的容器:
  27. [root@docker-100 ~]# docker ps
  28. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  29. 8d1bfecc1da7 centos "bash" 13 seconds ago Up 11 seconds determined_lewin

9.3、容器的进入

  1. [root@docker-100 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 8d1bfecc1da7 centos "bash" 13 seconds ago Up 11 seconds determined_lewin
  4. [root@docker-100 ~]# docker exec -it 8d1bfecc1da7 bash
  5. [root@8d1bfecc1da7 /]# cat /etc/redhat-release #可以看到操作系统的版本都不一样
  6. CentOS Linux release 8.3.2011
  7. [root@8d1bfecc1da7 /]# ps -ef
  8. UID PID PPID C STIME TTY TIME CMD
  9. root 1 0 0 07:09 pts/0 00:00:00 bash
  10. root 13 0 0 07:12 pts/1 00:00:00 bash
  11. root 27 13 0 07:12 pts/1 00:00:00 ps -ef
  12. docker exec -it mycentos /bin/bash相当于开启了-bash,当我们每次退出的时候,只是退出-bash这个进程还不是上面的/bin/bash,所以才能一直保持UP状态

9.4、查看容器所有的进程

  1. #查看容器所有的进程,包括停止的,如果只想查看运行中的,docker ps即可
  2. [root@docker-100 ~]# docker ps -a
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. 8d1bfecc1da7 centos "bash" 8 minutes ago Up 8 minutes determined_lewin

9.5、不进入容器操作命令

  1. [root@docker-100 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 8d1bfecc1da7 centos "bash" 8 minutes ago Up 8 minutes determined_lewin
  4. [root@docker-100 ~]# docker exec 8d1bfecc1da7 ps aux
  5. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  6. root 1 0.0 0.1 12012 1936 pts/0 Ss+ 07:09 0:00 bash
  7. root 28 0.0 0.1 44620 1772 ? Rs 07:18 0:00 ps aux
  8. [root@docker-100 ~]# docker exec -it 8d1bfecc1da7 bash
  9. [root@8d1bfecc1da7 /]# ps aux
  10. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  11. root 1 0.0 0.1 12012 1936 pts/0 Ss+ 07:09 0:00 bash
  12. root 32 0.3 0.2 12012 2160 pts/1 Ss 07:18 0:00 bash
  13. root 43 0.0 0.1 44620 1780 pts/1 R+ 07:18 0:00 ps aux

9.6、容器的删除

  1. [root@docker-100 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 8d1bfecc1da7 centos "bash" 11 minutes ago Up 11 minutes determined_lewin
  4. [root@docker-100 ~]# docker rm 8d1bfecc1da7 #docker rm是无法删除一个正在运行中的容器,这时候就需要使用docker rm -f
  5. Error response from daemon: You cannot remove a running container 8d1bfecc1da7ca83202e1d3e3008a23928fd14778e542f209fe9368a78aa0323. Stop the container before attempting removal or force remove
  6. [root@docker-100 ~]# docker rm -f 8d1bfecc1da7 #强制删除正在运行的容器
  7. 8d1bfecc1da7
  8. [root@docker-100 ~]# docker ps
  9. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  10. 注意:docker rm -f 这条命令很危险,生产场景不要轻易使用

9.7、容器的停止和开启

  1. [root@docker-100 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 8aee395cd97a centos "bash" 3 seconds ago Up 2 seconds jolly_kirch
  4. [root@docker-100 ~]# docker stop 8aee395cd97a
  5. 8aee395cd97a
  6. [root@docker-100 ~]# docker ps -a
  7. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  8. 8aee395cd97a centos "bash" 18 seconds ago Exited (0) 6 seconds ago jolly_kirch
  9. [root@docker-100 ~]# docker start 8aee395cd97a
  10. 8aee395cd97a
  11. [root@docker-100 ~]# docker ps
  12. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  13. 8aee395cd97a centos "bash" About a minute ago Up 1 second jolly_kirch

9.8、容器的重启

  1. [root@docker-100 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 8aee395cd97a centos "bash" About a minute ago Up 44 seconds jolly_kirch
  4. [root@docker-100 ~]# docker restart 8aee395cd97a
  5. 8aee395cd97a
  6. [root@docker-100 ~]# docker ps
  7. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  8. 8aee395cd97a centos "bash" About a minute ago Up 5 seconds jolly_kirch

9.9、查看docker日志

  1. [root@docker-100 ~]# docker logs 82108336fa38
  2. 192.168.2.75 - - [10/Jan/2018:07:22:50 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" "-"
  3. #参数详解
  4. -f:跟踪日志输出
  5. --since:显示某个开始时间的所有日志
  6. -t:显示时间戳
  7. --tail:仅列出最新N条容器日志

9.10、查看端口映射关系

  1. [root@docker-100 ~]# docker port nginx
  2. 80/tcp -> 10.0.0.11:81

9.11、自定义容器名称

  1. [root@docker-100 ~]# docker run -it -d --name centos7-v1 centos bash
  2. c7b87fedab3be13dec62381ff4cd1d99cfe8b8c1e36478af3a8a483824e80232
  3. [root@docker-100 ~]# docker ps
  4. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  5. c7b87fedab3b centos "bash" 10 seconds ago Up 10 seconds centos7-v1
  6. 8aee395cd97a centos "bash" 4 hours ago Up 4 hours jolly_kirch

9.12 单次运行容器

  1. [root@docker-100 ~]# docker run -it --rm centos bash

9.13 传递运行命令

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

注意:容器里面必须有一个可以长久执行的进程

  • 以服务类型的命令
    • 需要镜像有相关的服务,且服务支持前台运行,比如Nginx
  • shell命令:如tail命令等
  • 执行脚本:主要是可以在容器启动的时候执行比较多操作,可以修改配置文件或者启动其他服务
  1. [root@docker-100 ~]# docker run -it -d centos tail -f /etc/passwd
  2. 92161631a4c4256d7567f939e171174318ff97a4fa6492e3c4a39b304da54dc9
  3. [root@docker-100 ~]# docker ps
  4. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  5. 92161631a4c4 centos "tail -f /etc/passwd" 3 seconds ago Up 2 seconds brave_shirley

9.14 批量关闭、强制关闭或者删除正在运行的容器

  1. #批量关闭正在运行的容器
  2. [root@docker-100 ~]# docker ps
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. 92161631a4c4 centos "tail -f /etc/passwd" About a minute ago Up About a minute brave_shirley
  5. c7b87fedab3b centos "bash" 10 minutes ago Up 10 minutes centos7-v1
  6. 8aee395cd97a centos "bash" 4 hours ago Up 4 hours jolly_kirch
  7. [root@docker-100 ~]# docker ps -a -q
  8. 92161631a4c4
  9. c7b87fedab3b
  10. 8aee395cd97a
  11. [root@docker-100 ~]# docker stop `docker ps -a -q`
  12. 92161631a4c4
  13. c7b87fedab3b
  14. 8aee395cd97a
  15. #批量强制关闭正在运行的容器
  16. [root@docker-100 ~]# docker kill `docker ps -a -q`
  17. 92161631a4c4
  18. c7b87fedab3b
  19. 8aee395cd97a
  20. #批量删除已退出容器
  21. [root@docker-100 ~]# docker rm -f `docker ps -aq -f status=exited`
  22. 92161631a4c4
  23. c7b87fedab3b
  24. 8aee395cd97a
  25. #批量删除所有容器
  26. [root@docker-100 ~]# docker rm -f `docker ps -a -q`
  27. 92161631a4c4
  28. c7b87fedab3b
  29. 8aee395cd97a

9.15 指定容器DNS

DNS服务,默认采用宿主机的DNS地址

  • 是将DNS地址配置在宿主机
  • 是将参数配置在docker启动脚本里面 -dns=1.1.1.1
  1. [root@docker-100 ~]# docker run -it --rm --dns 114.114.114.114 centos bash
  2. [root@4cb6fc8b1978 /]# cat /etc/resolv.conf
  3. nameserver 114.114.114.114