小白也能读懂的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):容器是从镜像生成对外提供服务的一个或一组服务
3、Dcoker和虚拟机主要区别
虚拟化技术是一个通用的概念,在不同领域有着不同的理解。所以就拿维基百科上的定义来说吧:
在计算机技术中,虚拟化是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以用比原来的组态更好的方式来应用这些资源。
可见,虚拟化的核心是对资源进行抽象,目标往往是为了在同一个主机上运行多个系统或应用,从而提高系统资源的利用率,同时带来降低成本、方便管理和容错容灾等好处
以下是虚拟化的一些种类:
- 完全虚拟化。虚拟机模拟完整的底层硬件环境和特权指令的执行过程,客户操作系统无需进行修改。例如著名的
VMware workstation
等 - 硬件辅助虚拟化。利用硬件(主要是CPU)辅助支持(目前是
X86
体系结构上可用的硬件辅助虚拟化技术包括Intel-VT和AMD-V
)处理敏感指令来实现完全虚拟化的功能,客户操作系统无需修改。 - 部分虚拟化。只针对部分硬件资源进行虚拟化,客户操作系统需要进行修改。现在有些虚拟化技术的早期版本支持部分虚拟化
- 超虚拟化。部分硬件接口以软件的形式提供给客户机操作系统,客户操作系统需要进行修改
- 操作系统级虚拟化。内核通过创建多个虚拟的操作系统实列(内核和库)来隔离不同的进程。Docker属于这个范畴。
下图是Docker虚拟化和传统虚拟化的区别:
但是,如上图一个宿主机运行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
启用容器验证过程:
[root@docker-100 ~]# docker pull nginx
[root@docker-100 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 16 hours ago 133MB
[root@docker-100 ~]# docker run -it -d -p 80:80 nginx
验证容器的根文件系统:
3.1.2 IPC Namespace
一个容器内的进程间通信,允许一个容器内的不同进程的(内存、缓存等)数据访问,但是不能跨容器访问其他容器的数据。
3.1.3 UTS Namespace
UTS namespace (UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识,其中包含了hostname和域名
domainname ,它使得一个容器拥有属于自己hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器。
3.1.4 PID Namespace
Linux系统中,有一个PID为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其下属的子进程,那么多个容器的进程通PID namespace进程隔离(比如PID编号重复、器内的主进程生成与回收子进程等)。
例如:下图是在一个容器内使用top命令看到的PID为1的进程是nginx:
容器内的Nginx主进程与工作进程:
3.1.5 Net Namespace
每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用network namespace启动一个vethX接口,这样你的容器将拥有它自己的桥接ip地址,通常是docker0,而 docker0实质就是Linux的虚拟网桥,网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。
3.1.5.1 查看宿主机的网卡信息
[root@docker-100 ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:d1ff:fe43:1822 prefixlen 64 scopeid 0x20<link>
ether 02:42:d1:43:18:22 txqueuelen 0 (Ethernet)
RX packets 2987 bytes 124443 (121.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4567 bytes 8665267 (8.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: 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::bf9e:f0b7:5511:fe88 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:10:7b:d3 txqueuelen 1000 (Ethernet)
RX packets 168900 bytes 242033949 (230.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 45362 bytes 3605046 (3.4 MiB)
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 1 (Local Loopback)
RX packets 72 bytes 5744 (5.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 72 bytes 5744 (5.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth5176cd1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::c881:90ff:fe60:50b5 prefixlen 64 scopeid 0x20<link>
ether ca:81:90:60:50:b5 txqueuelen 0 (Ethernet)
RX packets 2987 bytes 166261 (162.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4575 bytes 8665915 (8.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
3.1.5.2 查看容器内的网卡信息
[root@docker-100 ~]# docker exec -it 6055d5c1fc42 bash
root@6055d5c1fc42:/# 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 4710 bytes 8922175 (8.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3086 bytes 171795 (167.7 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 1 (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
3.1.5.3 逻辑网络图
3.1.5.4 宿主机iptables规则
3.1.6 USER Namespace
各个容器内可能会出现重名的用户和用户组名称,或重复的用户UID或者GID,那么怎么隔离各个容器内的用户空间呢?
User Namespace允许在各个宿主机的各个容器空间内创建相同的用户名以及相同的用户UID和GID,只是会把用户的作用范围限制在每个容器内,即A容器和B容器可以有相同的用户名称和ID的账户,但是此用户的有效范围仅是当前容器内,不能访问另外一个容器内的文件系统,即相互隔离、互补影响、永不相见。
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容器就处于运行状态,该容器拥有独立的文件系统,独立并且安全的运行环境等。
总结:即使第一层镜像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
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源安装
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo systemctl restart docker
sudo systemctl enable docker
# Step 5:验证docker版本
sudo docker version
# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# 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)
# 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 镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层也不需要知道里面有几层,结构如下:
一个典型的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。
8.1、docker镜像加速配置
国内下载国外的镜像有时候会很慢,因此可以更改docker配置文件添加一个加速器,可以通过加速器达到加速下载镜像的目的。
#获取加速地址
浏览器打开http://cr.console.aliyun.com,注册或登录阿里云账号,点击左侧的镜像加速器,将会得到一个专属的加速地址,而且下面有使用配置说明:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://djz7vjm0.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
8.2、搜索镜像
列如搜索centos
的镜像
[root@docker-100 ~]# docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 6370 [OK]
ansible/centos7-ansible Ansible on Centos7 132 [OK]
consol/centos-xfce-vnc Centos container with "headless" VNC session… 125 [OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 117 [OK]
centos/systemd systemd enabled base container. 92 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 87
imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 58 [OK]
注释:
NAME 镜像名称
DESCRIPTION 描述
STARS 星级
OFFICIAL 是否官方创建
AUTPMATED 是否主动创建
默认的输出结果会按照星级评价进行排序,表示该镜像受欢迎程度
8.3、下载镜像
从docker仓库将镜像下载到本地,命令格式如下:
#docker pull 仓库服务器:端口/项目名称/镜像名称:tag(版本)号
[root@docker-100 ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
7a0437f04f83: Pull complete
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
8.4、查看镜像信息
[root@docker-100 ~]# docker images
镜像属于的仓库 镜像的标签信息 镜像的唯一ID号 镜像创建时间 镜像的大小
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 2 days ago 133MB
centos latest 300e315adb2f 5 weeks ago 209MB
8.5、保存镜像到本地
当需要把一台机器上的镜像迁移到另一台机器上的时候,需要将镜像保存成本地文件,这一过程叫作导出镜像,可以使用docker save命令进行存出操作。之后就可以拷贝该文件到其他机器
[root@docker-100 ~]# docker save -o /usr/local/src/centos.tar centos
[root@docker-100 ~]# ls -l /usr/local/src/centos.tar
-rw------- 1 root root 216535040 1月 15 14:58 /usr/local/src/centos.tar
8.6、载入镜像
将存出的镜像从A机器拷贝到B机器,需要在B机器上使用该镜像,就可以将该导出文件导入到B机器的镜像库中,这一过程叫作载入镜像。
[root@docker-100 ~]# docker load < /usr/local/src/centos.tar
e15afa4858b6: Loading layer 215.8 MB/215.8 MB
Loaded image: docker.io/centos:latest215.8 MB
[root@docker-100 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest 300e315adb2f 5 weeks ago 209MB
8.7、删除镜像
[root@docker-100 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 2 days ago 133MB
centos latest 300e315adb2f 5 weeks ago 209MB
[root@docker-100 ~]# docker rmi 300e315adb2f #通过镜像的ID删除
Untagged: centos:latest
Untagged: centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Deleted: sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55
Deleted: sha256:2653d992f4ef2bfd27f94db643815aa567240c37732cae1405ad1c1309ee9859
[root@docker-100 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 2 days ago 133MB
8.8、常用镜像命令
9、Docker容器操作
9.1 Docker容器常用选项
--restart=always #重启docker-server之后,容器不会因此还停止,还会继续运行
9.2、容器的启动
[root@docker-100 ~]# docker run -it -d centos bash
8d1bfecc1da7ca83202e1d3e3008a23928fd14778e542f209fe9368a78aa0323
注释:
docker run #启动容器
--name #指定容器的名称
-t #让Docker分配一个伪终端
-i #让容器的输入保存打开
-d #以后台的方式运行容器
--rm #退出后即删除容器
-e #指定环境变量,容器中可以使用该环境变量
-p #指定端口
-P #随机端口
-v #给容器挂载存储卷,挂载到容器的某个目录
--net #指定容器网络设置
centos #指定运行的docker镜像
bash #指定运行的进程
注意:如果指定的镜像(centos)没有,docker run也会自动的从docker仓库中下载下来,并启动。其实docker run就是docker create和docker start的结合体
当利用docker run来创建并启动容器时,docker在后台运行的标准操作包括:
1)检查本地是否存在指定的镜像,不存在就从公有仓库下载
2)利用镜像创建并启动一个容器
3)分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
4)从宿主机配置的网桥接口中桥接一个虚拟接口到容器中去
5)从地址池配置一个IP地址给容器
6)执行用户指定的应用程序
7)执行完毕后容器被终止
#显示正在运行的容器:
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d1bfecc1da7 centos "bash" 13 seconds ago Up 11 seconds determined_lewin
9.3、容器的进入
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d1bfecc1da7 centos "bash" 13 seconds ago Up 11 seconds determined_lewin
[root@docker-100 ~]# docker exec -it 8d1bfecc1da7 bash
[root@8d1bfecc1da7 /]# cat /etc/redhat-release #可以看到操作系统的版本都不一样
CentOS Linux release 8.3.2011
[root@8d1bfecc1da7 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:09 pts/0 00:00:00 bash
root 13 0 0 07:12 pts/1 00:00:00 bash
root 27 13 0 07:12 pts/1 00:00:00 ps -ef
用docker exec -it mycentos /bin/bash相当于开启了-bash,当我们每次退出的时候,只是退出-bash这个进程还不是上面的/bin/bash,所以才能一直保持UP状态
9.4、查看容器所有的进程
#查看容器所有的进程,包括停止的,如果只想查看运行中的,docker ps即可
[root@docker-100 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d1bfecc1da7 centos "bash" 8 minutes ago Up 8 minutes determined_lewin
9.5、不进入容器操作命令
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d1bfecc1da7 centos "bash" 8 minutes ago Up 8 minutes determined_lewin
[root@docker-100 ~]# docker exec 8d1bfecc1da7 ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 12012 1936 pts/0 Ss+ 07:09 0:00 bash
root 28 0.0 0.1 44620 1772 ? Rs 07:18 0:00 ps aux
[root@docker-100 ~]# docker exec -it 8d1bfecc1da7 bash
[root@8d1bfecc1da7 /]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 12012 1936 pts/0 Ss+ 07:09 0:00 bash
root 32 0.3 0.2 12012 2160 pts/1 Ss 07:18 0:00 bash
root 43 0.0 0.1 44620 1780 pts/1 R+ 07:18 0:00 ps aux
9.6、容器的删除
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d1bfecc1da7 centos "bash" 11 minutes ago Up 11 minutes determined_lewin
[root@docker-100 ~]# docker rm 8d1bfecc1da7 #docker rm是无法删除一个正在运行中的容器,这时候就需要使用docker rm -f
Error response from daemon: You cannot remove a running container 8d1bfecc1da7ca83202e1d3e3008a23928fd14778e542f209fe9368a78aa0323. Stop the container before attempting removal or force remove
[root@docker-100 ~]# docker rm -f 8d1bfecc1da7 #强制删除正在运行的容器
8d1bfecc1da7
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
注意:docker rm -f 这条命令很危险,生产场景不要轻易使用
9.7、容器的停止和开启
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8aee395cd97a centos "bash" 3 seconds ago Up 2 seconds jolly_kirch
[root@docker-100 ~]# docker stop 8aee395cd97a
8aee395cd97a
[root@docker-100 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8aee395cd97a centos "bash" 18 seconds ago Exited (0) 6 seconds ago jolly_kirch
[root@docker-100 ~]# docker start 8aee395cd97a
8aee395cd97a
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8aee395cd97a centos "bash" About a minute ago Up 1 second jolly_kirch
9.8、容器的重启
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8aee395cd97a centos "bash" About a minute ago Up 44 seconds jolly_kirch
[root@docker-100 ~]# docker restart 8aee395cd97a
8aee395cd97a
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8aee395cd97a centos "bash" About a minute ago Up 5 seconds jolly_kirch
9.9、查看docker日志
[root@docker-100 ~]# docker logs 82108336fa38
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" "-"
#参数详解
-f:跟踪日志输出
--since:显示某个开始时间的所有日志
-t:显示时间戳
--tail:仅列出最新N条容器日志
9.10、查看端口映射关系
[root@docker-100 ~]# docker port nginx
80/tcp -> 10.0.0.11:81
9.11、自定义容器名称
[root@docker-100 ~]# docker run -it -d --name centos7-v1 centos bash
c7b87fedab3be13dec62381ff4cd1d99cfe8b8c1e36478af3a8a483824e80232
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c7b87fedab3b centos "bash" 10 seconds ago Up 10 seconds centos7-v1
8aee395cd97a centos "bash" 4 hours ago Up 4 hours jolly_kirch
9.12 单次运行容器
[root@docker-100 ~]# docker run -it --rm centos bash
9.13 传递运行命令
容器需要有一个前台运行的进程才能保持容器的运行,通过传递运行参数是一种方式,另外也可以在构建镜像的时候指定容器启动时运行的前台命令。
注意:容器里面必须有一个可以长久执行的进程
- 以服务类型的命令
- 需要镜像有相关的服务,且服务支持前台运行,比如Nginx
- shell命令:如tail命令等
- 执行脚本:主要是可以在容器启动的时候执行比较多操作,可以修改配置文件或者启动其他服务
[root@docker-100 ~]# docker run -it -d centos tail -f /etc/passwd
92161631a4c4256d7567f939e171174318ff97a4fa6492e3c4a39b304da54dc9
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
92161631a4c4 centos "tail -f /etc/passwd" 3 seconds ago Up 2 seconds brave_shirley
9.14 批量关闭、强制关闭或者删除正在运行的容器
#批量关闭正在运行的容器
[root@docker-100 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
92161631a4c4 centos "tail -f /etc/passwd" About a minute ago Up About a minute brave_shirley
c7b87fedab3b centos "bash" 10 minutes ago Up 10 minutes centos7-v1
8aee395cd97a centos "bash" 4 hours ago Up 4 hours jolly_kirch
[root@docker-100 ~]# docker ps -a -q
92161631a4c4
c7b87fedab3b
8aee395cd97a
[root@docker-100 ~]# docker stop `docker ps -a -q`
92161631a4c4
c7b87fedab3b
8aee395cd97a
#批量强制关闭正在运行的容器
[root@docker-100 ~]# docker kill `docker ps -a -q`
92161631a4c4
c7b87fedab3b
8aee395cd97a
#批量删除已退出容器
[root@docker-100 ~]# docker rm -f `docker ps -aq -f status=exited`
92161631a4c4
c7b87fedab3b
8aee395cd97a
#批量删除所有容器
[root@docker-100 ~]# docker rm -f `docker ps -a -q`
92161631a4c4
c7b87fedab3b
8aee395cd97a
9.15 指定容器DNS
DNS服务,默认采用宿主机的DNS地址
- 是将DNS地址配置在宿主机
- 是将参数配置在docker启动脚本里面 -dns=1.1.1.1
[root@docker-100 ~]# docker run -it --rm --dns 114.114.114.114 centos bash
[root@4cb6fc8b1978 /]# cat /etc/resolv.conf
nameserver 114.114.114.114