Docker的镜像和容器
我们在理解 docker
之前,首先我们得先区分清楚两个概念,容器和虚拟机。
可能很多读者朋友都用过虚拟机,而对容器这个概念比较的陌生。
我们用的传统虚拟机如 VMware
, VisualBox
之类的需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。
而容器技术是和我们的宿主机共享硬件资源及操作系统,可以实现资源的动态分配。容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。
容器技术是实现操作系统虚拟化的一种途径,可以让您在资源受到隔离的进程中运行应用程序及其依赖关系。通过使用容器,我们可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响。容器还赋予我们对资源更多的精细化控制能力,让我们的基础设施效率更高。通过下面这幅图我们可以很直观的反映出这两者的区别所在。
imageDocker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux
容器解决方案。
而 Linux
容器是 Linux
发展出了另一种虚拟化技术,简单来讲, Linux
容器不是模拟一个完整的操作系统,而是对进程进行隔离,相当于是在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。
Docker
将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker
,就不用担心环境问题。
总体来说, Docker
的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
Docker的优势
Docker相比于传统虚拟化方式具有更多的优势:
-
docker
启动快速属于秒级别。虚拟机通常需要几分钟去启动 -
docker
需要的资源更少,docker
在操作系统级别进行虚拟化,docker
容器和内核交互,几乎没有性能损耗,性能优于通过Hypervisor
层与内核层的虚拟化 -
docker
更轻量,docker
的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境,Docker
运行的镜像数远多于虚拟机数量,对系统的利用率非常高 - 与虚拟机相比,
docker
隔离性更弱,docker
属于进程之间的隔离,虚拟机可实现系统级别隔离 - 安全性:
docker
的安全性也更弱。Docker
的租户root
和宿主机root
等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户root
权限和宿主机的root
虚拟机权限是分离的,并且虚拟机利用如Intel
的VT-d
和VT-x
的ring-1
硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击 - 可管理性:
docker
的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如VMware vCenter
提供完备的虚拟机管理能力 - 高可用和可恢复性:
docker
对业务的高可用支持是通过快速重新部署实现的。虚拟化具备负载均衡,高可用,容错,迁移和数据保护等经过生产实践检验的成熟保障机制,VMware
可承诺虚拟机99.999%
高可用,保证业务连续性 - 快速创建、删除:虚拟化创建是分钟级别的,
Docker
容器创建是秒级别的,Docker
的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间 - 交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化。
Docker
在Dockerfile
中记录了容器构建过程,可在集群中实现快速分发和快速部署
我们可以从下面这张表格很清楚地看到容器相比于传统虚拟机的特性的优势所在:
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般是几十个 |
Docker的三个基本概念
image.png从上图我们可以看到,Docker 中包括三个基本的概念:
- Image(镜像)
- Container(容器)
- Repository(仓库)
镜像是 Docker 运行容器的前提,仓库是存放镜像的场所,可见镜像更是 Docker 的核心。
Image (镜像)
那么镜像到底是什么呢?
Docker
镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
镜像(Image)
就是一堆只读层(read-only layer)
的统一视角,也许这个定义有些难以理解,下面的这张图能够帮助读者理解镜像的定义。
从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker
内部的实现细节,并且能够在主机的文件系统上访问到。统一文件系统 (union file system)
技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。
Container (容器)
容器 (container)
的定义和镜像 (image)
几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
由于容器的定义并没有提及是否要运行容器,所以实际上,容器 = 镜像 + 读写层。
Repository (仓库)
Docker
仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry
(仓库注册服务器)就是这样的服务。有时候会把仓库 (Repository)
和仓库注册服务器 (Registry)
混为一谈,并不严格区分。Docker
仓库的概念跟 Git
类似,注册服务器可以理解为 GitHub
这样的托管服务。实际上,一个 Docker Registry
中可以包含多个仓库 (Repository)
,每个仓库可以包含多个标签 (Tag)
,每个标签对应着一个镜像。所以说,镜像仓库是 Docker
用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>
的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest
作为默认标签.。
仓库又可以分为两种形式:
-
public
(公有仓库) -
private
(私有仓库)
Docker Registry
公有仓库是开放给用户使用、允许用户管理镜像的 Registry
服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry
。Docker
官方提供了 Docker Registry
镜像,可以直接使用做为私有 Registry
服务。当用户创建了自己的镜像之后就可以使用 push
命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull
下来就可以了。
我们主要把 Docker
的一些常见概念如 Image
, Container
, Repository
做了详细的阐述,也从传统虚拟化方式的角度阐述了 docker
的优势,我们从下图可以直观地看到 Docker
的架构:
Docker
使用 C/S
结构,即客户端/服务器体系结构。 Docker
客户端与 Docker
服务器进行交互,Docker服务端负责构建、运行和分发 Docker
镜像。 Docker
客户端和服务端可以运行在一台机器上,也可以通过 RESTful
、 stock
或网络接口与远程 Docker
服务端进行通信。
这张图展示了 Docker
客户端、服务端和 Docker
仓库(即 Docker Hub
和 Docker Cloud
),默认情况下Docker
会在 Docker
中央仓库寻找镜像文件,这种利用仓库管理镜像的设计理念类似于 Git
,当然这个仓库是可以通过修改配置来指定的,甚至我们可以创建我们自己的私有仓库。
Docker的安装
Docker Platform
- Docker提供了一个开发、打包、运行app的平台
-
Docker把app和底层infrastructure隔离开来
image.png
Docker Engine
Docker Engine是一个C/S架构的应用程序,主要包含下面几个组件;
- 常驻后台进程Dockerd
- 一个用来和Dockerd交互的REST API Server
-
命令行CLI接口,通过和REST API进行交互
image.png
Docker架构
image.pngDocker 的核心组件包括:
- Docker Client
- Docker daemon
- Docker Image
- Docker Registry
- Docker Container
Docker Damon
Docker Damon来监听Docker API的请求和管理Docker对象,比如镜像、容器、网络和Volume。
Docker Client
docker client是我们和Docker进行交互的最主要的方式方法,比如可以通过docker run来运行一个容器,然后我们的这个client会把命令发送给上面的Docker。
Docker Registry
Docker Registry 用来存储Docker镜像的仓库,Docker Hub是Docker官方提供的一个公共仓库,而且Docker默认也是从Docker Hub上查找镜像的,当然你也可以很方便的运行一个私有仓库,当我们使用docker pull或者docker run命令时,就会从我们配置的Docker镜像仓库中去拉取镜像,使用docker push命令时,会将我们构建的镜像推送到对应的镜像仓库中。
Images 镜像
镜像是一个制度模板,带有Docker容器的说明。一般来说的,镜像会基于另外的一些基础镜像上面安装一个Nginx服务器,这样就可以构建一个属于我们自己的镜像了。
Containers 容器
容器是一个镜像的可运行的实例,可以使用Docker REST API或者CLI来操作容器,容器的实质是进程,但与直接在宿主执行的实例进程不同,容器进程属于自己的独立的命名空间。因此容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间、甚至自己的用户ID。容器内的经常是运行在一个隔离的环境里,使用起来,就好像在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
Docker底层的技术支持
Namespaces:做隔离pid、net、ipc、mnt、uts
Control groups:做资源限制
Union file systems:Container和image的分层
Docker Image概述
- 文件和meta data的集合(root filesystem)
- 分层的,并且每一层都可以添加、改变和删除文件,成为一个新的image
- 不同的image可以共享相同的layer
-
Image本身是read-only的
Docker技术里最为基础的两大概念:镜像和容器。
镜像的获取方式:
- 从registry拉取
- 从Dockerfile构建
搜索镜像
docker search <image> # 在docker index中搜索image
--automated=false 仅显示自动创建的镜像
--no-trunc=false 输出信息不截断显示
-s 0 指定仅显示评价为指定星级的镜像
下载镜像
docker pull <image> # 从docker registry server 中下拉image
还可通过指定标签下载某镜像
docker pull [:TAG]
docker pull centos:7
查看镜像/删除
docker images: # 列出images
docker images -a # 列出所有的images(包含历史)
docker ps -a #列出本机所有容器
docker rmi <image ID>: # 删除一个或多个image
存出和载入镜像
存出本地镜像文件为.tar
docker save -o ubuntu_14.04.tar ubuntu:14.04
导入镜像到本地镜像库
docker load --input ubuntu_14.04.tar或者
docker load < ubuntu_14.04.tar
上传镜像
用户在dockerhub网站注册后,即可上传自制的镜像。
docker push NAME[:TAG]
Container容器
- 通过Image创建(copy)
- 在Image layer之上建立一个container layer(可读写)
- 类比Java面向对象:类和实例
-
Image负责app的存储和分发,Container负责运行app
image.png
创建(使用镜像创建容器):
首先得查看镜像的REPOSITORY和TAG
docker run -i -t REPOSITORY:TAG (等价于先执行docker create 再执行docker start 命令)
其中-t选项让docker分配一个伪终端并绑定到容器的标准输入上, -i则让容器的标准输入保持打开。若要在后台以守护态(daemonized)形式运行,可加参数-d
在执行docker run来创建并启动容器时,后台运行的标准包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读可写层
- 从宿主机配置的网桥接口中桥接一个虚拟接口到容器
- 从地址池配置一个ip地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
docker start/stop/restart <container> #:开启/停止/重启container
进入容器:
docker attach [container_id] #连接一个正在运行的container实例(即实例须为start状态,可以多个 窗口同时attach 一个container实例),但当某个窗口因命令阻塞时,其它窗口也无法执行了。
exec可直接在容器内运行的命令。docker exec -ti [container_id] /bin/bash
删除容器:
docker rm <container...> #:删除一个或多个container
docker rm `docker ps -a -q` #:删除所有的container
docker ps -a -q | xargs docker rm #:同上, 删除所有的container
docker -rm
-f 强制中止并运行的容器
-l 删除容器的连接,但保留容器
-v 删除容器挂载的数据卷
修改容器:
docker commit <container> [repo:tag] # 将一个container固化为一个新的image,后面的repo:tag可选。
导入和导出容器:
导出到一个文件,不管是否处于运行状态。
docker export CONTAINER > test.tar
导入为镜像:
cat test.tar | docker import - centos:latest
Dockerfile语法梳理及最佳实践
一、 FROM
Syntax:
FROM <image>[:<tag> | @<digest>] [AS <name>]
-
FROM指定一个基础镜像,且必须为Dockerfile文件开篇的每个非注释行,至于image则可以是任何合理存在的image镜像
-
FROM可以在一个Dockerfile中出现多次,以便于创建混合的images。如果没有指定tag,latest将会被指定为要使用的基础镜像版本。
-
AS name,可以给新的构建阶段赋予名称。该名称可用于后续FROM 和 COPY --from=<name | index>说明可以引用此阶段中构建的镜像
- 为了安全,尽量使用官方的image作为base image
二、LABEL
为镜像生成元数据标签信息
Syntax:
LABEL <KEY>=<VALUE> \
<KEY>="XXXX"
多个标签写成一行,避免在镜像中额外增加layer
image.png
三、MAINTAINER
作者信息,写在FROM后
Syntax:
MAINTAINER "auth <email>"
四、COPY
当复制一个目录时,并不会复制目录本身,而是会递归复制其下子目录 至目标目录下
image.png
Syntax:
COPY data /data/
文件复制准则
- <src>必须是build上下言文中的路径,不能是其父目录中的文件
- 如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
- 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾
- 如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径。
五、ADD
ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径
image.png
Syntax:
ADD <src>...<dest>
ADD ["<src>",..."<dest>"]
操作准则:
- 如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>
- 如果<src>是一个本地文件系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于"tar -x"命令;然而,通过URL获取到的tar文件将不会自动展开。
- 如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>内容将被直接写入到<dest>
- 为了让镜像尽量小,最好不要使用 ADD 指令从远程 URL 获取包,而是使用 curl 和 wget。这样你可以在文件提取完之后删掉不再需要的文件来避免在镜像中额外添加一层。
示例:
额外操作:
ADD http://example.com/1.tar.gz /apps/
RUN tar xf /apps/1.tar.gz -C /apps/ && \
/bin/sh -c /apps/***.sh
简单操作:
RUN mkdir -p /iyunwen/server/ && \
curl -SL http://example.com/1.tar.gz \
| tar -xzC /iyunwen/server/ && \
/bin/sh -c /apps/***.sh
注意:
大部分情况下,COPY由于ADD
ADD除了COPY外还有额外解压缩功能
添加远程文件 / 目录,请使用curl或者wget
六、WORKDIR
用于为Dockerfile中所有RUN、CMD、ENTRYPOINT、COPY和ADD指令设定工作目录
image.png
注意:
- 用WORKDIR,不要用RUN cd
- 尽量使用绝对目录
Syntax:
WORKDIR <dirpath>
在Dockerfile文件中,WORKDIR指令可以出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径
另外,WORKDIR也可调用由ENV指定定义的变量
ex:
WORKDIR /var/log
WORKDIR $STATEPATH
七、RUN
接受命令作为参数并用于创建镜像,在之前的commit层上形成新的层。
image.png
注意:
- 为了美观,复杂的RUN请用反斜线换行
- 避免无用分层,合并多条命令成一行
Syntax:
RUN \<command\>(如同执行shell命令 /bin/sh -c)
RUN ["executable","param1","param2"]
- RUN 指令将在当前image中执行任意合法命令并提交执行结果。命令执行提交后,就会自动执行Dockerfile中的下一个指令。
- 分层RUN指令和生成提交符合Docker的核心概念,其中提交很轻量,可以从image将用于Dockerfile中的下一步。
- exec形式使得可以避免shell字符串变化,以及使用不包含指定的shell可执行文件的基本image来运行RUN命令。
- 在shell形式中,可以使用\(反斜杠)将单个RUN指令继续到下一行。例如:
RUN yum install -y \ openssl \ pcre-devel \ zlib
- 第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或对数;然而,此种格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
RUN ["/bin/bash","-c","<executable>","<param1>"]
RUN 指令的缓存在下一次构建期间不会自动失效。用于诸如:yum repolist 之类的指令的缓存将在下一次构建期间被重用。可以通过--no-cache 参数来使RUN指令的缓存无效,例如: docker build --no-cache
管理命令
某些RUN 命令依赖于使用管道字符( | )将管道输出到另一个命令功能
RUN wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html
Docker使用 /bin/sh -c 解释执行这些命令,解释器只评估管道中最后一个操作的退出代码以确定成功。在上面的例子中,只要wc -l 命令成功,即使wget 命令失败,该构建步骤也会成功并生成新的镜像。
由于管道中任何阶段的错误而导致命令失败,请预先 set -o pipefail && 确保意外错误可防止构建无意中成功。例如:
set -o pipefail : 表示在管道连接的命令序列中,只要有任何一个命令返回非0值,则整个管道返回非0值,即使最后一个命令返回0.
RUN set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html
注意:
并非所有的shell都支持 -o pipefail 选项。在这种情况下(例如 dash shell,这是基于Debian的映像上的默认shell),请考虑使用exec形式RUN来明确选择一个支持该pipefail选项的shell。如:
RUN ["/bin/bash","-c","set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html"]
八、CMD
类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
- RUN 指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新镜像文件启动一个容器时。
- CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
- 在Dockerfile中可以存在多个CMD指令,但仅最后一个生效
Syntax:
CMD <command> //支持命令展开,但是不支持传递信号
CMD ["<executable>","<param1>","<param2>"] //相当于容器的第一个命令,可以接受信号
CMD ["param1","param2"]
前两种语法格式的意义同RUN
第三种则用于为ENTRYPOINT指令提供默认参数
CMD会在启动容器的时候执行,build时不执行,而RUN只是在构建镜像的时候执行,后续镜像构建完成之后,启动容器就与RUN无关了。这个命令就相当于在/etc/rc.d/rc.local中写命令
九、ENTRYPOINT
类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一具单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序。不过,docker run 命令的--entrypoint 选项的参数可覆盖ENTRYPOINT指令指定的程序
Syntax:
ENTRYPOINT <command> //这种方式能接受shell命令行展开
ENTRYPOINT ["<executable>","param1"] //展开不了,但能接收到信号
image.pngdocker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用。Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
十、EXPOSE
用来指定端口,使容器内的应用可以通过端口和外界交互。
Syntax:
EXPOSE <port> [<port>...]
告诉Docker服务端容器对外映射的本地端口,需要在docker run 的时候使用-p 或者 -P 选项生效。
EXPOSE 80/tcp
十一、ENV
ENV指令可以用于docker容器设置环境变量
Syntax:
ENV <key> <value>
ENV <key>=<value> ...
指定一个环境变量,会被后续RUN指令使用,并在容器运行时保留。
ENV设置的环境变量,可以使用 docker inspect 命令来查看。同时还可以使用 docker run --env <key>=<value>来修改环境变量
尽量使用ENV增加可维护性
image.png
十二、USER
用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID
默认情况下,container的运行身份为root用户
Syntax:
USER <UID>|<UserName>
需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败
十三、ONBUILD
用于在Dockerfile中定义一个触发器
Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件
在后的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器
Syntax:
ONBUILD <INSTRUCTION>
注意:
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程和上下文在缺少指定的源文件时会失败。
十四、HEALTHCHECK
Docker 1.12版本后引入的判断容器状态是否正常
Syntax:
HEALTHCHECK [OPTION] CMD <command> //设置检查容器健康状况的命令
HEALTHCHECK NONE //如果基础镜像有健康检查指令,使用这行可屏蔽掉其健康检查指令
在没HEALTHCHECK指令前,Docker只能通过容器内主进程是否退出来判断容器是否状态异常。很多情况下这没问题,但是如果程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了。虽然后端的程序可以通过前端的检测工具来检查状态信息。但是最前端的服务就需要本身的检测机制加上监控,就可以做到出现问题解决问题。
当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,如果连续一定次数失败,则会变为 unhealthy。
HEALTHCHECK支持下列选项:
- --interval=<间隔> : 两次健康检查间隔,默认30秒
- --timeout=<时长> : 健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认为30秒
- --retries=<次数> :当连续失败指定次数后,则将容器状态视为unhealthy,默认3次。
和CMD、ENTRYPOINT一样,HEALTHCHECK只可以出现一次,如果写了多个,只有最后一个生效。CMD 后面的命令也分为shell和exec格式。命令的返回值决定了该次检查的成功与否: 0表示成功;1表示失败;2保留。
ex:
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
命令收集:
容器生命周期管理 — docker [run|start|stop|restart|kill|rm|pause|unpause]
容器操作运维 — docker [ps|inspect|top|attach|exec|events|logs|wait|export|import|port]
容器rootfs命令 — docker [commit|cp|diff]
镜像仓库 — docker [login|pull|push|search]
本地镜像管理 — docker [images|rmi|tag|build|history|save|import]
其他命令 — docker [info|version]
查看docker信息:
$ docker version
# 或者
$ docker info</pre>
Docker 需要用户具有 sudo 权限,为了避免每次命令都输入sudo
,可以把用户加入 Docker 用户组(官方文档)
$ sudo usermod -aG docker $USER
服务启动,重启,状态
[hongdada@localhost home]$ systemctl stop docker.service
[hongdada@localhost home]$ systemctl restart docker.service
[hongdada@localhost home]$ systemctl status docker.service</pre>
images相关命令:
以镜像centos为例
登录仓库 docker login
查找镜像docker search centos
下载镜像docker pull centos
上传镜像docker push centos
删除镜像docker rmi centos 说明:如果有多个tag,则指定tag只会删除tag,而不会删除镜像本身。
查看镜像docker images
查看具体某一个镜像的详细信息:docker inspect centos
更改tag: docker tag docker.io/centos 21yunwei:latest
创建镜像docker commit 容器ID 镜像名称 注:创建镜像有三种方式,基于容器创建,基于本地模板创建,基于dockerfile创建
保存镜像docker save -o testcentos.tar 21yunwei:latest
载入镜像docker load < tesetcentos.tar
# 列出本机的所有 image 文件。
$ docker image ls
# 删除 image 文件
$ docker image rm [imageName]
# 搜索镜像
$ docker search mysql (输出信息包括镜像名字、描述、星级、是否为官方创建、是否自动创建)
# image 文件从仓库抓取到本地。
$ docker image pull library/hello-world
# 运行image文件
$ docker container run hello-world
container相关命令:
列出本机正在运行的容器:docker container ls
列出本机所有容器,包括终止运行的容器:docker container ls --all
创建容器docker create -ti image 容器ID:cid
启动容器docker start cid
运行容器docker run -dit cid 等同于docker create+docker start
停止容器服务 docker container kill cid
关闭容器docker stop cid
重启容器docker restart cid
删除容器docker rm cid #注意数据卷
删除所有容器docker rm `docker ps -a -q` docker kill `docker ps -q`
阻塞对容器的其他调用方法,直到容器停止后退出 docker wait cid
查看容器docker ps 或者docker ps -a
列出容器ID docker ps -q (docker ps -q -a)
容器文件拷贝 docker cp cid:路径 宿主机路径或docker cp 宿主机路径你 cid:路径
查看容器进程docker top cid
查看容器日志docker logs cid
查看容器变化 docker diff cid
进入容器docker exec -ti cid /bin/bash或者 docker attach cid(不推荐,终端显示相同,显示不安全且容易卡住)
查看容器详细信息 docker inspect cid 包括配置信息,名称,命令、网路配置以及很多有用数据
查看容器端口 docker port cid
导出容器docker export 3ad>21yunwei.tar
导入容器cat 21yunwei.tar | docker import -test/centos:latest
参考:
https://www.cnblogs.com/dance-walter/p/9581508.html
https://www.cnblogs.com/edisonchou/p/dockerfile_inside_introduction.html
https://www.cnblogs.com/hongdada/p/8906967.html
https://baijiahao.baidu.com/s?id=1641433332828402192&wfr=spider&for=pc