Docker笔记(一):Docker简介与使用

1、Docker简介

1.虚拟化技术简介

虚拟化(Virtualization)技术是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。这些资源的新虚拟部份不受现有资源的架设方式,地域或物理组态所限制,一般所指的虚拟化资源包括计算能力和资料存储。

在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用,透明化底层物理硬件,从而最大化的利用物理硬件对资源充分利用虚拟化技术种类很多,例如:软件虚拟化、硬件虚拟化、内存虚拟化、网络虚拟化(vip)、桌面虚拟化、服务虚拟化、虚拟机等等。

从大类上分,虚拟化技术可分为基于硬件的虚拟化和基于软件的虚拟化,真正意义上的基于硬件的虚拟化技术不多见。基于软件的虚拟化从对象所在的层次,又可以分为应用虚拟化和平台虚拟化。Docker以及其他容器技术都属于平台虚拟化中操作系统虚拟化这个范畴,操作系统虚拟化最大的特点就是不需要额外的supervisor支持。

2.Docker的特性与优点

Docker的三大特性为BUILD(构建)、SHIP(运输)、RUN(运行)。

(1)上手快

只需要几分钟,就可以把自己的程序“Docker化”。Docker依赖于“写时复制”(copy-on-write)模型,使修改应用程序也非常迅速,大多数Docker容器只需要不到1秒中即可启动。由于去除了管理程序的开销,Docker容器拥有很高的性能,同时同一台宿主机中也可以运行更多的容器,使用户尽可能的充分利用系统资源。

(2)职责的逻辑分类

使用Docker,开发人员只需要关心容器中运行的应用程序,而运维人员只需要关心如何管理容器。Docker设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署的生产环境一致性,避免开发环境与生产环境不一致。

(3)快速高效的开发生命周期

Docker的目标之一就是缩短代码从开发、测试到部署、上线运行的周期,让你的应用程序具备可移植性,易于构建,并易于协作。(通俗一点说,Docker就像一个盒子,里面可以装很多物件,如果需要这些物件的可以直接将该大盒子拿走,而不需要从该盒子中一件件的取。)

(4)鼓励使用面向服务的架构

Docker还鼓励面向服务的体系结构和微服务架构。Docker推荐单个容器只运行一个应用程序或进程,这样就形成了一个分布式的应用程序模型,在这种模型下,应用程序或者服务都可以表示为一系列内部互联的容器,从而使分布式部署应用程序,扩展或调试应用程序都变得非常简单,同时也提高了程序的内省性。

番外篇: 中间件服务器是Docker容器应用的最佳实践,原因如下:

  1. 中间件服务器是除数据库服务器外的主要计算节点,很容易成为性能瓶颈,所以通常需要大批量部署,而Docker对于批量部署有着许多先天的优势。
  2. 中间件服务器结构清晰,在剥离了配置文件、日志、代码目录之后,容器几乎可以处于零增长状态,这使得容器的迁移和批量部署更加方便。
  3. 中间件服务器很容易实现集群,在使用硬件的F5,软件的 Nginx等负载均衡后,中间件服务器集群变得非常容易。

值得注意的是,由于目前 Docker暂不支持修改运行中的容器的一些配置,比如无法为运行中的容器映射更多的宿主机目录、网络,在使用中间件容器的
时候,需要事先规划好容器的用途和可能开放的网络端口等资源。

3.容器与虚拟机比较

Docker 和传统虚拟化方式的不同之处:容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,虚拟出一个新的操作系统,而传统方式则是在硬件层面实现,虚拟出一个新的硬件环境,在硬件环境上,再安装完整的操作系统。

在这里插入图片描述

docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要额外的虚拟化管理程序(VMM(VirtualMachine Monitor),以及hyperisor)支持,**他是内核级虚拟化,可以实现更高的性能,同时对资源的额外需求很低,docker应用获得的是接近原生的运行性能。**最本质特征docker是通过隔离来创建容器,而KVM等均为通过模拟方式创建虚拟机。

4.Docker服务器与客户端

Docker采用Go语言编写,是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务端(守护进程)发出请求,服务器将完成所有工作并返回结果。Docker提供了一个命令行工具、一整套RESTful API,你可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程。

5.Docker的镜像、容器、仓库

镜像: 一个镜像可以包含一个基本的操作系统环境,如果里面仅安装了Apache应用程序,可以把它称为一个Apache镜像 。

容器: Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。镜像自身是只读的。容器从镜像启动的时候,会在镜像的最上层创建一个可写层。

仓库: Docker仓库类似于代码仓库,是集中存放镜像文件的场所。仓库注册服务器(Registry)是存放仓库的地方,其上往往存放着多个仓库。每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签( tag)来进行区分。目前,最大的公开仓库是官方提供的 Docker Hub。在使用 Docker一段时间后,往往会发现手头积累了大量的自定义镜像文件,这些文件通过公有仓库进行管理并不十分方便;另外有时候只是希望内部用户之间进行分享。在这种情况下,就有必要搭建一个本地的私有仓库服务器。可以使用 docker-registry镜像搭建一个私有仓库。

2、Docker安装与配置

1.安装Docker

Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的,很多CentOS版本中是不支持更新最新的一些补丁包的。此外,docker不支持32位的CPU架构;首次在新主机上安装Docker CE(Community Edition)之前,需要设置Docker存储库。之后才可以从存储库安装和更新Docker。推荐使用离线安装,避免下载超时。

在线安装教程如下,亲测可用:https://blog.csdn.net/jinking01/article/details/82490688

离线下载地址:https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/

离线安装教程:https://www.cnblogs.com/atuotuo/p/9272368.html

给当前用户授予docker操作的权限:https://www.cnblogs.com/hutao722/p/10036387.html

2.设置国内镜像地址

执行如下命令,创建或修改文件:

sudo vim /etc/docker/daemon.json

在文件中输入内容:

{
    "registry-mirrors":["https://docker.mirrors.ustc.edu.cn",
    	"http://hub-mirror.c.163.com","https://registry.docker-cn.com"]
}

配置完成后,重启docker服务

service docker restart
3.Docker的启动与停止
systemctl start docker    #启动docker
systemctl stop docker     #停止docker
systemctl restart docker  #重启docker
systemctl status docker   #查看docker状态
systemctl enable docker   #开机启动
docker info               #查看docker概要信息
docker --help             #查看docker帮助文档
4.Docker守护进程

Docker守护进程需要以root权限来运行,以便它有足够的权限去管理所需要的资源,来处理普通用户无法完成的操作(如挂载文件系统)。当Docker软件包安装完毕后,默认会立即启动Docker守护进程。**守护进程监听/var/run/docker.sock这个Unⅸ套接字文件,来获取来自客户端的Docker请求。**如果系统中存在名为docker的用户组,Docker则会将该套接字文件的所有者设置为该用户组。这样,docker用户组的所有用户都可以直接运行 Docker,而无需再使用sudo命令了,无需root权限。docker用户组对 Docker具有与root用户相同的权限。

虽然docker用户组使我们的工作变得更轻松,但它依旧是一个值得注意的安全隐患。可以认为 docker用户组和root具有相当的权限,应该确保只有那些需要此权限的用户和应用程序才能使用该用户组。

配置守护进程监听

运行 Docker守护进程时,可以用-H标志调整守护进程绑定监听接口的方式,Docker客户端不会自动监测到网络的变化,我们需要通过-H选项来指定服务器的地址。

sudo docker -d -H tcp://0.0.0.0:2375

该命令将Docker守护进程绑定到宿主机上的(0.0.0.0),也能通过-H标志指定一个Unix套接字路径,守护进程可以同时绑定到多个地址。

sudo docker -d -H tcp://0.0.0.0: 2375 -H unix://home/docker/docker.sock

3、镜像、容器的相关命令

1.镜像相关命令

(1)镜像查找

docker search NAME

(2)镜像拉取

用docker run命令从镜像启动一个容器时,如果该镜像不在本地,Docker会先从Docker hub下载该镜像。Registry默认为registry.hub.docker.com,TAG默认为latest。

docker pull [Registry]/NAME:TAG
docker pull ubuntu:16.04

(3)镜像信息查看

# 查看已经拉取的镜像,存储在宿主机的/var/lib/docker目录下
docker images
# 查看镜像的详细信息,返回一个Json字符
docker inspect imageID
# 可以使用-f指定要查看的信息
docker inspect -f {{".Config.ExposedPorts"}} tomcat

(4)镜像删除

当同一个镜像拥有多个标签的时候,docker rmi命令只是删除了该镜像多个标签中的指定标签而已,并不影响镜像文件,当镜像只剩一个标签的时候,执行docker rmi命令会删除该镜像。

当有容器是基于该镜像创建的时候,docker rmi命令是无法删除该镜像的。不推荐使用 -f 参数强制删除镜像,被强制删除的镜像会换了一个新的ID继续存在于系统中。正确的做法是先删除容器,然后删除镜像。

docker rmi imageID
# 删除全部docker镜像
docker rmi `docker images -q`

(5)镜像导出导入

使用docker save命令,用来将一个或多个image打包成tar文件。

docker save -o <保存路径> <镜像名称:标签>
docker save -o tomcat.tar tomcat:v1.0

将tomcat.tar文件移植到其他的计算机上,可以使用docker load命令加载镜像。如果本地镜像库已经存在该镜像,将会被覆盖。

docker load --input tomcat.tar

docker save的应用场景是,如果你的应用是使用docker-compose.yml编排的多个镜像组合,但你要部署的服务器并不能连外网。这时,你可以使用docker save将用到的镜像打个包,然后拷贝到客户服务器上使用docker load载入。

(6)镜像的上传

使用docker push命令将自己的镜像上传到registry.hub.docker.com,需要注册账户。

2.容器相关命令

(1)创建交互式容器

docker run命令,等价于docker create + docker start 命令,容器启动后进入容器。

docker run -it ubuntu --name myName /bin/bash

-i 参数是让容器的标准输入STDIN保持打开。使用Ctrl+D或exit命令退出容器。

-t 参数表示创建交互式容器,让docker为容器分配一个伪tty终端,并绑定在标准输入STDIN上。

-t和-i标志为我们执行的进程创建了伪tty终端并捕捉STDIN,若要在命令行下创建一个能与之进行交互的容器,则这两个参数已经是最基本的参数了。

docker run命令的执行过程如下:

img

(2)创建守护式容器

守护式容器启动后会进入后台,用户无法进入容器,看到容器里面的信息。

docker run --name deamon_ubuntu -d ubuntu /bin/sh -c "while true;do echo hello world;sleep 1; done"

通过如下命令查看容器打印的日志:

# 使用-f表示持续不断的打印日志,通过Ctrl+C退出追踪日志
docker logs -f deamon_ubuntu

查看容器内的进程:

docker top deamon_ubuntu

(3)进入容器命令行

1)attach方式: 容器处于运行状态,可以通过attach命令重新进入容器的命令行,退出命令行后,容器也会停止运行。当多个窗口同时attach到同一个容器的时候,所有窗口都会同步显示,当某个窗口因命令阻塞时,其他窗口也无法执行操作了。

docker attach deamon_ubuntu

2)exec方式: docker1.3之后,可以通过docker exec命令在容器内部额外启动新进程,新的进程有两种类型:后台任务和交互式任务。后台任务在容器内运行且没有交互需求,而交互式任务则保持在前台运行。交互式任务,如打开容器的命令行:

docker exec -it deamon_ubuntu bash

3)attach与exec主要区别如下:

  • attach直接进入容器启动命令的终端,不会启动新的进程。
  • exec则是在容器中打开新的终端,并且可以启动新的进程。
  • 如果想直接在终端中査看启动命令的输出,用attach;其他情况使用exec。

如果某容器中只启动了一个命令行,用户通过exit命令或ctrl+d来退出终端时,所创建的容器立刻终止。

(4)暂停容器

有时我们只是希望让容器暂停工作一段时间,比如要对容器的文件系统打个快照,或宿主机需要使用CPU,这时可以执行docker pause。处于暂停状态的容器不会占用CPU资源,直到通过 docker unpause恢复运行。

(5)自动重启容器

如果因为某种错误而导致容器停止运行,默认情况下docker不会重启容器,可以通过–restart参数让Docker自动重新启动该容器。–restart会检查容器的退出代码,并据此决定是否要重启容器。restart的参数值包括always、on-failure;

# 无论容器因何种原因退出(包括正常退出),都立即重启
--restart = always
# 当容器退出代码为非0时,Docker会尝试自动重启该容器,最多重启5次
--restart = on-failure:5

(6)终止容器运行

docker stop命令终止一个运行中的容器,它会首先向容器发送SIGTERM信号,等待一段时间后(默认为10秒),再发送 SIGKILL信号终止容器。如果想快速停止容器,可使用docker kill命令,其作用是直接向容器进程发送SIGKILL信号。

docker stop ubuntu

Docker容器中指定的应用终结时,容器也自动终止。例如某容器只启动了一个命令行,用户通过exit命令或ctrl+d来退出命令行时,该容器会立刻终止。

(7)导出导入容器

docker export是用来将container的文件系统打包成tar文件,不管此时这个容器是否处于运行状态。可将这个文件传输到其他机器上,在其他机器上通过导入命令实现容器的迁移。然后使用docker import命令导入,导入成为镜像,加入本地库。

docker export container > container.tar
docker import container.tar imagename:version

docker export的应用场景主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后,把这个镜像分发给其他人使用,比如作为基础的开发环境。

docker save/load和docker export/import的区别:

  • docker save保存的是镜像(image),docker export保存的是容器(container);
  • docker save
  • docker load用来载入镜像包,docker import用来载入容器包,但两者都会恢复为镜像;
  • docker load不能对载入的镜像重命名,而docker import可以为镜像指定新名称。
  • docker save将保存完整记录,内部包含重复文件,体积较大,docker export丢弃了所有的历史记录和元数据信息,无重复文件,仅保存容器当时的快照状态。

详细的区别见文章:https://blog.csdn.net/liukuan73/article/details/78089138。

(8)容器直接保存为镜像

有时候需要在基础镜像里面安装某些依赖,如果把命令写在Dockerfile里,部分依赖软件下载很慢,构建镜像的时候又会花很长的时间,所以最好是封装一个包含依赖库的新镜像。commit方式可以用于构建自定义的容器,但并不推荐使用该方式,仍推荐Dockerfile。

docker commit mynginx mynginx_i

(9)容器的批量操作

停用全部运行中的容器:

docker stop $(docker ps -q)

删除全部容器:

docker rm $(docker ps -aq)

一条命令实现停用并删除容器:

docker stop $(docker ps -q) & docker rm $(docker ps -aq)

(10)查看容器运行数据

通过以下命令查看容器运行的各种数据

docker inspect 容器名称(容器ID)

通过如下命令直接输出IP地址

docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称(容器ID)

4、容器数据管理

在Docker中,要想实现数据的持久化(即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。容器中管理数据主要有两种方式:

  • 数据卷(Data Volumes)
  • 数据卷容器(Data Volume Containers)
1.数据卷

数据卷是一个可供容器使用的特殊目录,数据卷的使用,类似于 Linux下对目录或文件进行 mount操作。它绕过文件系统,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用。
  • 对数据卷的修改会立马生效。
  • 对数据卷的更新,不会影响镜像。
  • 卷会一直存在,直到没有容器使用。

Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上位置有所不同:

Bind mount volume(绑定挂载卷): 需要在宿主机和容器内各指定一个特定的路径作为挂载点,两个挂载点建立关联关系;

Docker-managed volume(docker管理卷): 只需要在容器内指定容器的挂载点,宿主机上的挂载点固定在/var/lib/docker/volumes目录下,这种方式极大解脱用户在使用卷时的耦合关系,当容器内挂载点包含数据的时候,可以将容器挂载点的数据复制到宿主机的挂载点。

(1)Bind mount volume

可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样就可以通过修改宿主机某个目录的文件从而去影响容器。 这个功能在进行测试的时候十分方便,比如用户可以放置一些程序或数据到本地目录中,然后在容器内运行和使用。

另外,目录的路径必须是绝对路径,如果目录不存在,Docker会自动创建。Docker挂载数据卷的默认权限是读写(rw),用户也可以通过ro指定为只读,在容器中无法对bind mount volume数据进行修改,只有宿主机有权修改数据,提高了安全性。创建容器时,-v参数后边为宿主机目录:容器目录。例如:

# 加了:ro之后,容器内挂载的数据卷的数据就无法修改了。 
docker run -d -v /src/webapp:/opt/webapp:ro ubuntu

如果共享的是多级的目录,可能会出现权限不足的提示,需要添加参数 –privileged=true 来解决挂载的目录没有权限的问题。

(2)Docker-managed volume

在用 docker run命令的时候,使用-v标记可以在容器内创建一个数据卷,不需要指定宿主机目录,使容器与宿主机解耦合,多次使用-v标记可以创建多个数据卷。

docker run -d -v /usr/local/ --name=mycentos3 centos
2.数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器其实就是一个普通的容器,专门用它提供数据卷供其他容器挂载使用方法如下。

首先,创建一个数据卷容器dbdata ,并在其中创建一个数据卷挂载到/dbdata。

docker run -it -v /dbdata --name dbdata ubuntu

然后,可以在其他容器中使用–volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷。容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何方在该目录下的写人,其他容器都可以看到。

docker run -it --volumes-from dbdata --name db1 ubuntu
docker run -it --volumes-from dbdata --name db2 ubuntu
docker run --volumes-from dbdata -v /cxj --name db3 ubuntu
docker run -d --volumes-from dbl --name db4 ubuntu

可以多次使用–volumes-from参数来从多个容器挂载多个数据卷,还可以从其他已经挂载了容器卷的容器来挂载数据卷。使用–volumes-from参数被挂载的数据卷容器(dbdata)自身并不需要保持在运行状态。如果删除了挂载的容器(db1、db2、db3),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用 docker rm -v命令来指定同时删除关联的容器。

3.容器文件拷贝
# 宿主机 to 容器
docker cp 宿主文件或目录 容器名称:容器目录
docker cp /host/aaa containerName:/container/aaa
# 容器 to 宿主机
docker cp 容器名称:容器目录 宿主机文件或目录

5、网络的基本配置

1.端口映射实现访问容器

在启动容器的时候,如果不指定对应参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。可以通过-P或-p参数来指定端口映射。当使用-P标记时,Docker会随机映射一个4900-49900的端口至容器内部开放的网络端口;使用-p参数可以指定需映射的端口,多次使用-p标记可以绑定多个端口。默认为tcp端口,也可指定映射udp端口。

docker run -d -p hostPort:containerPort/udp --name=tomcat tomcat

查看容器的端口映射配置,可以查询容器指定的端口。

docker port container [port]
2.容器互联

docker连接系统允许将多个容器连接在一起,共享连接信息。docker连接会创建一个父子关系,其中父容器可以看到子容器的信息。使用–link参数可以让容器之间安全的进行交互。

Docker在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动db容器的时候并没有使用-p和-P标记,从而避免了暴露数据库端口到外部网络上。

docker run -it --name linktest --link redis:db ubuntu

–link标志创建了两个容器间的父子连接。这个标志需要两个参数:一个是要连接的容器名字,另一个是连接后容器的别名。别名让我们可以访问公开的信息,而无须关注底层容器的名字。连接让父容器有能力访问子容器,并且把子容器的一些连接细节分享给父容器,这些细节有助于配置应用程序并使用这个连接。

–link连接在安全方面也有好处,启动Redis容器时,不需要使用-p标志公开Redis的端口。通过把容器连接在一起,可以让父容器直接访问任意子容器的公开端口,并且只有使用–link标志才能连接到redis端口。redis容器的端口不需要对本地宿主机公开,通过这个安全模型,就可以限制容器化应用程序的被攻击面,减少应用暴露的网络。

出于安全原因(或者其他原因),可以强制 Docker只允许有连接的容器之间互相通信。需要在启动Docker守护进程时加上–ic= false标志,关闭所有没有连接的容器间的通信。被连接的容器必须运行在同一个 Docker宿主机上。不同 Docker宿主机上运行的容器无法连接。

Docker在父容器里的以下两个地方写入了连接信息:

  • /etc/hosts文件中: Docker容器重新启动后,容器的IP地址可能会发生变化,从Docker1.3开始,如果被连接的容器重启了,/etc/host文件中的IP地址会更新为新的IP地址。
  • 包含连接信息的环境变量中: 环境变量中包含一些以DB开头的环境变量,Docker在连接webapp和redis容器时,自动创建了这些以DB开头的环境变量。这些环境变量会随容器的变化而变化,取决于容器是如何配置的(如容器的Dockerfile中里由ENV和EXPOSE指令定义的内容)。更重要的是,这些连接信息可以让容器内的应用程序使用相同的方法与别的容器进行连接,而不用关心被连接的容器的具体细节。
3.自定义网络创建

(1)新建网络

下面先创建一个新的 Docker 网络。-d:参数指定 Docker 网络类型,有 bridge、overlay。其中 overlay 网络类型用于 Swarm mode,

docker network create -d bridge test-net

(2)连接容器

运行新的容器并连接到新建的 test-net 网络:

docker run -it --name test1 --network test-net ubuntu /bin/bash docker run -it --name test2 --network test-net ubuntu /bin/bash

(3)连接验证

通过ping来证明test1容器和test2容器建立了互联关系。如果test1、test2容器内中无ping命令,则在容器内执行以下命令安装 ping。

apt-get update
apt install iputils-ping

如果有多个容器之间需要互相连接,推荐使用Docker Compose。

6、Dockerfile

1.什么是Dockerfile

Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。Dockerfile的作用包括:

1、对于开发人员:可以为开发团队提供一个完全一致的开发环境;

2、对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了; 3、对于运维人员:在部署时,可以实现应用的无缝移植。

2.Dockerfile基本结构

Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

# Base images 基础镜像
FROM centos
# MAINTAINER 维护者信息
MAINTAINER tianfeiyu
# 镜像操作指令
RUN <command> 或 RUN ["executable", "param1", "param2"]
# 容器启动时执行的指令
CMD ["executable","param1","param2"]
3.常用命令解析

FROM:第一条指令必须为 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令(每个镜像一次)。格式为:

 FROM <image> 或 FROM <image>:<tag>

MAINTAINER:指定维护者信息,可以不写。格式为

 MAINTAINER <name>

ENV: 指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。格式为

ENV <key> <value> 
ENV VERSION 9.3

ADD:将本地文件添加到容器的指定位置, 可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件(自动解压为目录)。格式为

# ?替代一个单字符,例如:"home.txt"
ADD <src> <dest> 例如:ADD hom?.txt /mydir/      

COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源。当使用本地目录为源目录时,推荐使用 COPY。格式为

 COPY <src> <dest>

WORKDIR:为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录。格式为

WORKDIR /path/to/workdir

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

WORKDIR /a
WORKDIR b
RUN pwd

则最终路径为 /a/b/c。

RUN:构建镜像时执行的命令,每条 RUN 指令将在当前镜像基础上执行指定命令,并创建新的中间镜像,新创建的中间镜像,会被缓存起来,可以通过配置–no-cache参数,取消中间镜像的缓存。当命令较长时可以使用 \ 来换行。格式为

RUN <command> 或 RUN ["executable", "param1", "param2"]

前者将在 shell 终端中运行命令,即 /bin/sh -c;后者则使用 exec 执行。可以通过第二种方式指定使用其它终端,例如 RUN ["/bin/bash", “-c”, “echo hello”]。

CMD:启动容器时执行的命令,**每个 Dockerfile 只能有一条 CMD 命令。**如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。支持三种格式

CMD ["executable","param1","param2"]  # 使用 exec 执行,推荐方式;
CMD command param1 param2   # 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"]  # 提供给 ENTRYPOINT 的默认参数;

CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

ENTRYPOINT :配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效。两种格式:

ENTRYPOINT ["executable", "param1", "param2"] 
ENTRYPOINT command param1 param2

ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。

EXPOSE:告诉 Docker 服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过 -P,Docker 主机会自动分配一个端口转发到指定的端口。格式为

 EXPOSE <port> [<port>...]

VOLUME:创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。格式为

VOLUME ["/data"]

ONBUILD:当所构建的镜像被用做其它镜像的基础镜像时,所触发执行的操作指令。格式为:

ONBUILD [INSTRUCTION]

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

ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

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

FROM image-A
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

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

LABEL: 用于为镜像添加元数据,格式为

LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"

使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

Dockerfile示例:

# This my first nginx Dockerfile
# Version 1.0

# Base images 基础镜像
FROM centos

# MAINTAINER 维护者信息
MAINTAINER tianfeiyu

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  文件放在当前目录下,拷过去会自动解压
ADD nginx-1.8.0.tar.gz /usr/local/
ADD epel-release-latest-7.noarch.rpm /usr/local/

#RUN 执行以下命令  
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.8.0
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install
RUN echo "daemon off;" >> /etc/nginx.conf

#EXPOSE 映射端口
EXPOSE 80

#CMD 启动容器时执行以下命令
CMD ["nginx"]
4.Dockerfile中执行命令的方式

(1)RUN:执行命令并创建新的镜像层,RUN经常用于安装软件包。

(2)CMD:设置容器启动后默认执行的命令及其参数,但CMD能够被docker run后面跟的命令行参数替换。

(3)ENTRYPOINT:配置容器启动时运行的命令。

执行命令的形式有两种,Shell和Exec格式,格式如下:

# Shell格式
RUN apt-get install python3
# Exec格式:
RUN ["apt-get", "install","python3"]
5.构建镜像的步骤与原理

(1)创建构建上下文

创建一个目录用来保存 Dockerfile文件,这个目录就是我们的构建环境,也称此环境为上下文或构建上下文。Docker会在构建镜像时将构建上下文和该上下文中的文件和目录上传到 Docker守护进程,这样Docker守护进程就能直接访问你想在镜像中存储的任何代码、文件或者其他数据。

(2)编辑Dockerfile

创建一个Dockerfile文件,写入构建镜像的指令与参数。每条指令都会创建一个新的镜像层并对镜像进行提交。Docker大体上按照如下流程执行 Dockerfile中的指令。

  • Docker从基础镜像运行一个容器;
  • 执行一条指令,对容器做出修改;
  • 执行类似 docker commit的操作,提交一个新的镜像层;
  • Docker再基于刚提交的镜像运行一个新容器;
  • 执行 Dockerfile中的下一条指令,直到所有指令都执行完毕。

即使因为某条指令执行出错,导致Dockerfile构建容器失败,也会得到一个可以使用的镜像。

(3)构建镜像

准备好Docerfile后,使用当前目录的 Dockerfile 创建镜像的命令:

docker build -t myApp_nginx:v1.0 .

-t myApp_nginx:v1.0 ,给新构建的镜像取名为 myApp_nginx:v1.0, 并设定版本为 v1.0 。

-f 可以显式指定构建镜像的Dockerfile 文件,如果不使用 -f,则默认将上下文中的名为Dockerfile的文件认为是构建镜像的 “Dockerfile文件” 。命令中最后 . (点)的告诉Docker到本地目录中去找Dockerfile文件。也可以指定个Git仓库的源地址来指定 Dockerfile的位置。

构建完成后,会将上下文中的文件传送到Docker守护进程。命令执行完毕后,如果可见“Successfully built xxx”字样,则说明镜像创建成功。

如果在构建上下文的根目录下存在以dockerignore文件,那么该文件内容会被按行进行分割,每一行都是一条文件过滤匹配模式。这非常像gitignore文件,该文件用来设置哪些文件不会被上传到构建上下文中去。

由于每一步的构建过程都会将结果提交为镜像,过程中构建的镜像都会被缓存起来。

https://www.runoob.com/docker/docker-compose.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值