[TOC]
##什么是Docker
- Docker最初是dotCloud公司创始人Solomon Hykes在法国期间发起的一个公司内部项目,于2013年3月以Apache 2.0授权协议开源,主要项目代码在GitHub上进行维护。Docker使用Google公司推出的Go语言进行开发实现。
- Docker项目的目标是实现轻量化的操作系统虚拟化解决方案。Docker是基础是Linux容器(LXC)等技术。在LXC的基础上Docker进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便,用户操作Docker的容器就像操作一个快速轻量级的虚拟机一样简单。
- Docker和传统虚拟化的最大不同点是在操作系统层面上实现的虚拟化,直接复用本地主机的操作系统。而传统虚拟化方式则是在硬件层面上实现的。
- Docker的接口相当简单,用户可以方便的创建、销毁容器.
- Docker将应用程序与程序的依赖,打包在一个文件里面.运行这个文件就会生成一个虚拟容器。程序运行在虚拟容器里,如同在真实物理机上运行一样,有了docker,就不用担心环境问题了.
- web应用的自动化打包和发布
- 自动化测试和持续集成、发布
- 在服务型环境中部署和调整数据库或其他应用
物理机部署方式 1. 部署速度慢 2. 部署成本高 3. 资源浪费 4. 难于迁移和扩展 5. 可能会被限定硬件厂商
虚拟机部署方式 1. 一个物理机部署多个APP 2. 每个APP独立运行在一个VM里面
不管是物理机还是虚拟化都存在局限性,每一个虚拟机都是一个完整的操作系统,要分配系统资源,虚拟机数量到一定程度时,操作系统本身资源也就消耗殆尽或者说必须扩容;
Docker VS 传统虚拟机
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
让开发/运维人员最头痛的麻烦事之一就是环境配置了,每台计算机的环境都不相同,用户必须确保的是:
操作系统的相同
各种平台库和组件的安装
解决方案一:虚拟机
虚拟机可以制作模板,基于模板创建虚拟机,保证环境一致性;虚拟机就是个带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机就是一个普通文件不需要了就删掉,对其他部分毫无影响。
-
缺点 **资源占用:**虚拟机会独占一部分内存和磁盘空间,它运行的时候其他程序就不能再使用这部分资源了; **冗余步骤多:**虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录; **启动慢:**启动操作系统需要多久,启动虚拟机就需要多久,可能要多等几分钟应用程序才能真正运行;
-
优点 **资源化:**一个物理机的资源分配到不同的虚拟机里 **易扩展:**加物理机或加虚拟机 **易云化:**阿里云、亚马逊AWS等
解决方案二:Linux容器
用docker容器后,可以实现开发、测试、生产环境的统一和标准化。镜像作为标准的交付软件,可在开发、测试和生产环境上以容器来运行,最终实现三套环境上的应用以及运行所依赖内容的完全一致。
由于虚拟机的诸多问题,Linux发展处了另一种虚拟化技术:Linux容器(Linux containers,缩写LXC)。
Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离,在正常进程的外面套了一个保护层,对于容器里面进程来说,它接触的资源都是虚拟的,从而实现和底层系统的隔离。
**启动快:**容器里面的应用,直接就是底层系统的一个进程而不是虚拟机内部的进程。所以,启动容器相当于启动本机的一个进程而不是启动一个操作系统速度就快很多。
**资源占用少:**容器只占用需要的资源,不占用那些没有用到的资源。虚拟机由于是完整的操作系统,不可避免要占用所有资源。另外多个容器可以共享资源,虚拟机都是独享资源。
**体积小:**容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所有容器文件比虚拟机文件要小很多。
总之,容器有点像轻量级的虚拟机,能够提供虚拟化的环境,但是成本开销小很多。
##Docker容器的优势
- 一致的运行环境 开发过程中一个常见的问题是环境一致性问题。
由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
- 持续交付和部署 对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行.
使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) 系统进行自动部署。 而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
-
更快速的启动时间 传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
-
更轻松的迁移 由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。
Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
-
更轻松的维护和扩展 Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
-
更高效的利用系统资源 由于容器不需要进行硬件虚拟以及运行完整的操作系统文件等额外开销,docker对系统资源的利用率更高;无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
镜像 image
容器 container
仓库 repository
- docker镜像
Docker镜像就是一个只读的模板。
例如:一个镜像可以包含一个完整的CentOS操作系统环境,里面仅安装了Apache或用户需要的其他应用程序。镜像可以用来创建Docker容器。Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用.
-
image的分层存储 因为镜像包含完整的root文件系统,体积是非常庞大的,因此docker在设计时按照Union FS的技术,将其设计为==分层存储的架构==。镜像不是ISO那种完整的打包文件,镜像只是一个虚拟的概念,他不是一个完整的文件,而是由一组文件组成,或者多组文件系统联合组成。
-
docker容器
image和container的关系,就像面向对象程序设计中的类和实例一样,镜像是静态的定义(class),容器是镜像运行时的实体(object)。
Docker利用容器来运行应用。容器是从镜像创建的运行实例.它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
注意:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
-
docker仓库
- 仓库是集中存放镜像文件的场所。有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
- 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
- 最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供**用户更稳定快读的访问。
- 当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下载在另外一台机器上使用这个镜像时候,只需需要从仓库上pull下来就可以了。
注意:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。
-
docker registry
- Docker Registry公开服务是开放给用户使用、允许用户管理镜像的Registry服务。
- 一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
- 最常使用的Registry公开服务是官方的Docker Hub,这也是默认的Registry,并拥有大量的高质量的官方镜像。
- 除此以外,还有CoreOS的Quay.io,CoreOS相关的镜像存储在这里。
- Google的Google Container Registry,Kubernetes的镜像使用的就是这个服务。
==由于某些原因,在国内访问这些服务可能会比较慢。==
- 国内的一些云服务商提供了针对Docker Hub的镜像服务(Registry Mirror),这些镜像服务被称为加速器。
- 常见的有阿里云加速器、DaoCloud 加速器、灵雀云加速器等.
- 使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从官方网站下载速度会提高很多。
- 国内也有一些云服务商提供类似于Docker Hub的公开服务。比如时速云镜像仓库、网易云镜像服务、DaoCloud镜像市场、阿里云镜像库等。
-
Docker 客户端
最左边是 Docker 的客户端,类似我们操作 MySQL 的工具 Navcat,只不过我们这里的是没有图形化界面的命令终端。
Docker 客户端是用户与 Docker 服务交互的窗口!我们能看到图中就是各种操作的命令!
-
Docker 服务
中间的是 Docker 后台运行的服务,一个称为 Docker Daemon 的守护进程。可以理解为我们 MySQL 的服务,我们的操作命令都是在这部分进行处理!
Docker Deamon 监听着客户端的请求,并且管理着 Docker 的镜像、容器、网络、磁盘(图中只列出了镜像与容器)等对象。
同样,Docker 的客户端与服务可以运行在同一机器上,也可以用某台机器上的客户端远程连接另一台机器上的 Docker 服务,这跟我们的 MySQL 一样的。
-
仓库
右边部分是注册仓库,在远古时代做开发的都知道,我们以前需要一个第三方包的时候需要去网上下载对应的 Jar 包,很麻烦不说,还容易下的包是不稳定的版本。
有了 Maven 之后,我们只要在 Maven 配置文件中引入对应的依赖,就可以直接从远程仓库中下载对应版本的 Jar 包了。
Docker 中的仓库与 Maven 的仓库是一个概念,可以远程下载常用的镜像,也可以 Push 包到远程仓库(如图中的 Redis、Nginx 等镜像),同一个镜像又可以有多个版本,在 Docker 中称为 Tag!
-
镜像&容器
前面我们有多次提到镜像和容器,这是 Docker 里面很核心的两个概念。那镜像和容器分别是什么呢?镜像和容器的关系是什么呢?
-
镜像
**官方给出的定义是:**Docker 镜像是一个只读模板,可以用来创建 Docker 容器。
镜像是一种轻量级的、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。
它包含运行某个软件所需要的所有的内容,包括代码、运行时库、环境变量、配置文件等。
我们开发的 Web 应用需要 JDK 环境、需要 Tomcat 容器、需要 Linux 操作系统,那我们可以把我们所需要的一切都进行打包成一个整体(包括自己开发的 Web 应用+JDK+Tomcat+CentOS/Ubuntu+各种配置文件)。
打包后的镜像在某台机器上能运行,那它就能够在任何装有 Docker 的机器上运行。
任何镜像的创建会基于其他的父镜像,也就是说镜像是一层套一层,比如一个 Tomcat 镜像,需要运行在 CentOS/Ubuntu 上。
那我们的 Tomcat 镜像就会基于 CentOS/Ubuntu 镜像创建(在后面的操作部分我们可以通过命令查看)。
-
容器
**官方给出的定义是:**Docker 的容器是用镜像创建的运行实例,Docker 可以利用容器独立运行一个或一组应用。
我们可以使用客户端或者 API 控制容器的启动、开始、停止、删除。每个容器之间是相互隔离的。
上一步我们构建的镜像只是一个静态的文件,这个文件需要运行就需要变为容器,我们可以把容器看做是一个简易版的 Linux 系统和运行在其中的应用程序!
就是前面看到的鲸鱼背上的一个一个的集装箱,每个集装箱都是独立的!
-
-
镜像与容器关系
上面的概念很抽象,可以理解为容器就是镜像的一个实例,相信大家都写过类似下面的代码:
public void Dog extends Animal{
......
}
......
Dog dog = new Dog()
我们在代码中定义了一个 Dog 类,这个类就相当于一个镜像,可以根据这个类 New 出很多的实例,New 出来的实例就相当于一个个的容器。镜像是静态的文件,而容器就是有生命的个体!
Dog 类可以继承父类 Animal,如果不显式的指定继承关系,Dog 类就默认继承 Object 类。
同样上面也说到过 Docker 中的镜像也有继承关系,一个镜像可以继承其他的镜像创建,添加新的功能!
看到这里的你是不是对 Docker 有了更多的了解了呢?我们再回头看看百度百科对 Docker 的描述,可能你又会有更深的印象:
>Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux 或 Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
上面说到容器是一个简易版的 Linux 系统和运行在其中的应用程序,那我们的应用程序产生的数据(比如操作日志、异常日志、数据)也是在容器内的系统中存放的,默认不会做持久化,我们可以进入到容器中查看。
但是万一有一天,Docker 这条鲸鱼不满人类的压迫,反抗了...老子打烂你的集装箱!
随着容器的关闭,容器内的数据也会丢失,重新开启的容器不会加载原来的数据(简单说就是容器重新启动又是另外一个实例了)。
那对容器内的数据需要持久化到宿主机上就很有必要了,这就需要了解我们的容器数据卷。
容器数据卷的设计目的就是做数据的持久化和容器间的数据共享,数据卷完全独立于容器的生命周期,也就是说就算容器关闭或者删除,数据也不会丢失。
简单点说就将宿主机的目录挂载到容器,应用在容器内的数据可以同步到宿主机磁盘上,这样容器内产生的数据就可以持久化了。关于容器卷的命令,我们后面会有操作实例!
##命令操作 上面说了那么多,下面就到了咱们的实操环节啦!这一节的内容会通过一些常用的命令让大家更进一步的了解 Docker。注意!这里只是一些常用的命令来加深理解,而不是命令大全!
-
帮助命令
-
docker version:查看 Docker 客户端和服务的版本。
-
docker info:查看 Docker 的基本信息,如有多少容器、多少镜像、Docker 根目录等等。
-
docker --help:查看 Docker 的帮助信息,这个命令可以查看所有 Docker 支持的命令~
这几个命令非常简单,有过一点 Linux 基础的小伙伴应该很容易理解!
-
-
镜像命令
-
docker images:查看本地主机上所有的镜像。注意是本地主机的!这里能看到镜像的名称、版本、id、大小等基本信息,注意这里的 imageID 是镜像的唯一标识!
还可以通过 docker images tomcat 指定某个具体的镜像查看对应信息。
这里还要注意的是 CentOS 的镜像才 200MB 的大小,比我们物理机器上装的 CentOS 要小得多的多,这是因为 CentOS 的镜像只保留了 Linux 核心部分,这也是为什么 Docker 虚拟化技术比虚拟机运行效率更高的原因!
那为什么 Tomcat 的镜像这么大呢?那是因为我们之前说过我们的镜像就像一个洋葱一样,是一层套一层的!
-
docker rmi:删除本地的镜像,如下图所示,可以加上 -f 参数进行强制删除。
这里的 rmi 命令跟 Linux 中的删除命令就很像,只是这里加了一个 i 代表 image!
-
docker pull:搜索到某个镜像之后就可以从远程拉取镜像啦,有点类似咱们 Git 中的 Pull 命令,当然对应的还有个 docker push 的命令。
如上图,如果我们没有指定 Tag,默认就会拉取 Latest 版本,也可以通过 docker pull tomcat:1.7 的方式拉取指定版本!
注意这里在拉取镜像的时候打印出来的信息有很多,这也是前面说到的镜像是一层套一层,拉取一个镜像也是一层一层的拉取!
-
-
容器命令
通过镜像命令我们就能获取镜像、删除镜像等操作啦!镜像有了下面自然就需要通过镜像创建对应的实例啦,也就是我们的容器。下面我们以 Tomcat 为例:
-
**docker run [OPTIONS] IMAGE [COMMAND] [ARG...]:**可以基于某个镜像运行一个容器,如果本地有指定的镜像则使用本地镜像,如果没有则从远程拉取对应的镜像然后启动!
==由于这个命令非常重要,所以下面列出几个比较重要的参数:==
-
-d:启动容器,并且后台运行(Docker 容器后台运行,就必须要有一个前台进程,容器运行的命令如果不是一直挂起的命令,容器启动后就会自动退出)。
-i:以交互模式运行容器,通常与 -t 同时使用。
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用(容器启动后进入到容器内部的命令窗口)。
-P:随机端口映射,容器内部端口随机映射到主机的高端口。
-p:指定端口映射,格式为:主机(宿主)端口:容器端口。
-v:建立宿主机与容器目录的同步。
--name="myTomcat":为容器指定一个名称(如果不指定,则有个随机的名字)。
上面我通过命令启动了一个 Tomcat 的容器,由于使用了 -t 的参数,所以容器启动后就进入到了容器的内部的命令窗口,打印了很多 Tomcat 启动的日志。
并且使用 -p 参数指定了端口映射,也就是容器内 Tomcat 运行的端口是 8080,并且映射到了宿主机上的 8888 端口,这样我们在外部就可以通过服务器的 ip+8888 端口访问到我们容器内部 Tomcat 部署的服务了。
前面我们提到过容器内的数据会随着容器的关闭而丢失。那我们就需要有容器数据卷的技术能将容器内的数据持久化到宿主机。这里需要用到 -v 参数!
第一个要注意的是我们用的 -d 参数,启动后没有进入到容器内部,还是在宿主机。(可以对比一下与上面 -it 参数的区别)
第二个要注意的是 -v /宿主机:/容器内目录实现了宿主机与容器内指定目录的数据同步!
容器启动后就可以使用 Linux 的 ll 命令查看宿主机上已经同步到了容器内的文件。
第三个要注意的是这里的同步是双向的,也就是说在宿主机上对文件的修改也会同步到容器内部!
多个不同的容器映射到宿主机的同一个目录,就可以实现不同容器间的==数据共享==!
- **进入到容器后可以通过 exit 命令退出容器**,也可以通过 Ctrl+P+Q 快捷键退出容器,这两种方式的不同之处是 exit 会退出并且关闭容器,而 Ctrl+P+Q 快捷键只是单纯的退出,容器还在运行,并且还能再次进入!
- **docker ps:**我们可以通过该命令查看正在运行的容器的信息,这里能看到容器的唯一 id,启动时间等等...
这里跟 Linux 的 ps 命令类似,所以也可以把容器理解为一个运行在 Docker 上的进程!
docker ps -a 可以查看运行中与停止的所有容器:
![](images.czwxyy.top/mweb/2019081315641218008203.jpg)
- **docker attach [OPTIONS] CONTAINER:**上面说过通过 Ctrl+P+Q 快捷键退出容器后容器还在后台运行,那如果想再次进入容器怎么办呢?我们就可以通过 attach 命令+容器的 id 再次进入容器!
- **docker exec [OPTIONS] CONTAINER:**这个命令与 attach 一样都可以再次进入后台运行的容器,但是该命令可以不进入容器而在运行的容器中执行命令!比 attach 更加强大!
- **docker stop、docker kill、docker restart:**这三个命令分别用来停止容器、强制停止容器和重启容器,就跟我们在 Linux 上停止、强制停止和重启某个进程一样的。
- docker rm:使用这个命令就可以删除某个容器,这里跟删除镜像的区别是这里少了一个 i 。
==需要注意的是通过 Stop 和 Kill 停止的容器还存在于 Docker 中,而使用 rm 命令操作后的容器将不再存在!==
- **docker inspect:**查看容器的详情(也能查看镜像详情)。
前面我们对 Docker 以及相关概念、常用命令有了基本的了解,我们也知道了可以从远程 Pull 一个镜像,那远程的镜像是怎么来的呢?如果我们想自己创建一个镜像又该怎么做呢?
对,Dockerfile!Dockerfile 是一个包含用户能够构建镜像的所有命令的文本文档,它有自己的语法以及命令,Docker 能够从 Dockerfile 中读取指令自动的构建镜像!
我们要想编写自己的 Dockerfiler 并构建镜像,那对 Dockerfile 的语法和命令的了解就是必须的,了解规则才好办事嘛!
-
相关指令
FROM
FROM [AS]
FROM
[:][AS ]
FROM
[@] [AS ]
```
指定基础镜像,当前镜像是基于哪个镜像创建的,有点类似 Java 中的类继承。FROM 指令必是 Dockerfile 文件中的首条命令。
>MAINTAINER
MAINTAINER <name>
镜像维护者的信息,该命令已经被标记为不推荐使用了。
> LABEL
```
LABEL=== ... ```
给镜像添加元数据,可以用 LABEL 命令替换 MAINTAINER 命令。指定一些作者、邮箱等信息。
> ENV
```
ENV ENV = ... ```
设置环境变量,设置的变量可供后面指令使用。跟 Java 中定义变量差不多的意思!
> WORKDIR
```
WORKDIR /path/to/workdir ``` 设置工作目录,在该指令后的 RUN、CMD、ENTRYPOINT, COPY、ADD 指令都会在该目录执行。如果该目录不存在,则会创建!
> RUN
```
RUN RUN ["executable","param1", "param2"] ``` RUN 会在当前镜像的最上面创建一个新层,并且能执行任何的命令,然后对执行的结果进行提交。提交后的结果镜像在 Dockerfile 的后续步骤中可以使用。
> ADD
```
ADD[--chown=:] ... ADD[--chown=:] ["",...""] ```
从宿主机拷贝文件或者文件夹到镜像,也可以复制一个网络文件!如果拷贝的文件是一个压缩包,会自动解压缩!
> VOLUME
```
VOLUME ["/data"] ``` VOLUME 用于创建挂载点,一般配合 run 命令的 -v 参数使用。
> EXPOSE
```
EXPOSE [/...] ``` 指定容器运行时对外暴露的端口,但是该指定实际上不会发布该端口,它的功能是镜像构建者和容器运行者之间的记录文件。
回到容器命令中的 run 命令部分,run 命令有 -p 和 -P 两个参数。
如果是 -P 就是随机端口映射,容器内会随机映射到 EXPOSE 指定的端口;如果是 -p 就是指定端口映射,告诉运维人员容器内需要映射的端口号。
> CMD
```
CMD["executable","param1","param2"] CMD["param1","param2"] CMD command param1 param2 ``` 指定容器启动时默认运行的命令,在一个 Dockerfile 文件中,如果有多个 CMD 命令,只有一个最后一个会生效!
同样是可以执行命令,可能你会觉得跟上面的 RUN 指令很相似,RUN 指令是在构建镜像时候执行的,而 CMD 指令是在每次容器运行的时候执行的!docker run 命令会覆盖 CMD 的命令!
ENTRYPOINT
ENTRYPOINT["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
这个指令与 CMD 指令类似,都是指定启动容器时要运行的命令,如果指定了 ENTRYPOINT,则 CMD 指定的命令不会执行!
在一个 Dockerfile 文件中,如果有多个 ENTRYPOINT 命令,也只有一个最后一个会生效!不同的是通过 docker run command 命令会覆盖 CMD 的命令!
执行的命令不会覆盖 ENTRYPOINT,docker run 命令中指定的任何参数都会被当做参数传递给 ENTRYPOINT!
==RUN、CMD、ENTRYPOINT 区别:==
- RUN 指令是在镜像构建时运行,而后两个是在容器启动时执行!
- CMD 指令设置的命令是容器启动时默认运行的命令,如果 docker run 没有指定任何的命令,并且 Dockerfile 中没有指定 ENTRYPOINT,那容器启动的时候就会执行 CMD 指定的命令!有点类似代码中的缺省参数!
- 如果设置了 ENTRYPOINT 指令,则优先使用!并且可以通过 docker run 给该指令设置的命令传参!
- CMD 有点类似代码中的缺省参数。
> USER
```
USER [:] USER [:] ``` 用于指定运行镜像所使用的用户。
> ARG
```
ARG [=] ``` 指定在镜像构建时可传递的变量,定义的变量可以通过 dockerbuild --build-arg = 的方式在构建时设置。
> ONBUILD
```
ONBUILD [INSTRUCTION] ``` 当所构建的镜像被当做其他镜像的基础镜像时,ONBUILD 指定的命令会被触发!
> STOPSIGNAL
```
STOPSIGNAL signal ``` 设置当容器停止时所要发送的系统调用信号!
HEALTHCHECK
HEALTHCHECK [OPTIONS] CMD command (在容器内运行运行命令检测容器的运行情况)
HEALTHCHECK NONE (禁止从父镜像继承检查)
SHELL
SHELL ["executable","parameters"]
用于设置执行命令所使用的默认的 Shell 类型!该指令在 Windows 操作系统下比较有用,因为 Windows 下通常会有 CMD 和 Powershell 两种 Shell,甚至还有 SH。
-
构建
Dockerfile 执行顺序是从上到下,顺序执行!每条指令都会创建一个新的镜像层,并对镜像进行提交。
编写好 Dockerfile 文件后,就需要使用 docker build 命令对镜像进行构建了。
docker build 的格式:
docker build [OPTIONS] PATH | URL | -
-f:指定要使用的 Dockerfile 路径,如果不指定,则在当前工作目录寻找 Dockerfile 文件!
-t:镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
例如我们可以 docker build -t myApp:1.0.1 . 这样来构建自己的镜像,注意后面的 . , 用于指定镜像构建过程中的上下文环境的目录。
如果大家想了解那些官方镜像的 Dockerfile 文件都是怎么样写的,可以上 https://hub.docker.com/ 进行搜索。