写给后端的Docker初级入门教程:DockerFile 命令详解

在上一篇文章写给后端的Docker初级入门教程:实战篇最后咱们有提到用DockerFile来构建和定制属于咱们本身的镜像,由于时间和篇幅问题,上一篇文章对DockerFile只作了一个简单的介绍和使用,并无对DockerFile具体的指令进行详细的介绍和解释,本篇,做为上一篇实战篇的额外补充篇,咱们将从DockerFile基础的命令入手,一步一步的去构建一个属于咱们本身的镜像出来。java

DockerFile介绍:

Dockerfile是由一系列命令和参数构成的脚本,一个Dockerfile里面包含了构建整个image的完整命令。Docker经过docker build执行Dockerfile中的一系列命令自动构建image。python

实例:

这里咱们仍然选择咱们上一篇使用的在centos基础上定制咱们本身的镜像为本章的代码实例,代码以下:linux

FROM centos  //继承至centos
ENV mypath /tmp  //设置环境变量
WORKDIR $mypath //指定工做目录

RUN yum -y install vim //执行yum命令安装vim
RUN yum -y install net-tools //执行yum命令安装net-tools

EXPOSE 80 //对外默认暴露的端口是80
CMD /bin/bash //CMD 容器启动命令,在运行容器的时候会自动执行这行命令,好比当咱们 docker run -it centos 的时候,就会直接进入bash
复制代码

以后再经过docker build 命令编译该DockerFile即可以获得一个属于本身的镜像了。nginx

而后编译该镜像
docker build -f ./DockerFile -t mycentos:1.3.
-t 新镜像名字:版本
-f 文件 -d 文件夹
复制代码

运行该镜像会发现vim和net-tools在咱们新的容器中已经能够正常使用了。git

接下来呢,咱们将从FROM命令开始逐行介绍,最终完成对DockerFile经常使用命令的了解和掌握。程序员

经常使用命令:

FROM命令:

既然咱们是在原有的centos镜像的基础上作定制,那么咱们的新镜像也必定是须要以centos这个镜像为基础的,而FROM命令则表明了这个意思,在DockerFile中,基础镜像是必须指定的,FROM指令的做用就是指定基础镜像,所以一个DockerFile中,FROM是必备的指令,并且就像java,python的import关键字同样,在DockerFile中,FROM指令必须放在第一条指令的位置github

固然,这个时候可能有朋友会问了,我要是不想在其余的镜像上定制镜像怎么办呢,没问题啊,Docker 提供了scratch 这个虚拟镜像,若是你选择 FROM scratch 的话,则意味着你不以任何镜像为基础,接下来所写的指令将做为镜像的第一层开始存在,固然,在某些状况下,好比linux下静态编译的程序,运行的时候不须要操做系统提供运行时的支持,这个时候FROM scratch 是没有问题的,反而会大幅下降咱们的镜像体积。sql

ENV指令

功能:设置环境变量docker

一样的,DockerFile也提供了两种格式:shell

  • ENV key value
  • ENV key1=value1 key2=value2

这个指令很简单,就是设置环境变量而已,不管是后面的其它指令,如 RUN, 仍是运行时的应用,均可以直接使用这里定义的环境变量。

能够看到咱们示例中使用ENV设置mypath变量以后,在下一行WORKDIR则使用到了mypath这个变量

ENV mypath /tmp  //设置环境变量
WORKDIR $mypath //指定工做目录
复制代码

WORKDIR 指令:

功能,指定工做目录

格式为:WORKDIR 工做目录路径,若是这个目录不存在的话,WORKDIR则会帮助咱们建立这个目录。

设置过工做目录以后,当咱们启动容器,会直接进入该工做目录

[root@8081304919c9 tmp]#
复制代码

RUN命令:

RUN 指令是用来执行命令行命令的。因为命令行的强大能力,RUN 指令也是在定制镜像时是较为经常使用的指令之一。

RUN命令的格式一共有两种,分别是:

  • Shell 格式

    RUN 命令,就像直接在命令行中输入命令同样,好比RUN yum -y install vim就是使用的这种格式

  • exec 格式

    RUN["可执行文件","参数1","参数2"],感受就像调用函数同样

就像咱们在上一篇文章中说过的那样,DockerFile中每一条指令都会创建一层,好比咱们上面执行过下面这条命令

RUN yum -y install vim 
复制代码

执行结束以后,则调用commit提交这一层的修改,使之构成一个新的镜像,怎么样,是否是豁然开朗了呢。

并无

那好吧

一样的,Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以 及行首 # 进行注释的格式。良好的格式,好比换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。

提示:

若是使用apt方式安装的话,最后不要忘记清理掉额外产生的apt缓存文件,若是不清理的话会让咱们的镜像显得很是臃肿。由于DockerFile生成一层新的镜像的时候,并不会删除上一层镜像所残留的文件。

EXPOSE指令:

功能:声明端口

格式: EXPOSE 端口1 端口2

EXPOSE 指令是声明运行时容器提供服务端口,这固然只是一个声明,在运行时并不会由于这个声明应用就会开启这个端口的服务。这样声明主要是为了方便后期咱们配置端口映射。

CMD指令:

以前介绍容器的时候曾经说过,Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,须要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的。

一样的,DockerFile也为咱们提供了两种格式来使用CMD命令:

  • shell 格式:CMD 命令
  • exec 格式:CMD ["可执行文件", "参数 1", "参数 2"...]

示例中,咱们使用的是第一种:

CMD /bin/bash
复制代码

这条指令带来的效果就是,当咱们经过run -it 启动命令的时候,容器会自动执行/bin/bash,centos默认也是CMD /bin/bash,因此当咱们运行centos镜像的时候,会自动进入bash环境里面。

固然,咱们也能够经过运行时指定命令的方式来体换默认的命令,好比:

docker run -it centos cat /etc/os-release
复制代码

这样当咱们运行镜像的时候,cat /etc/os-release就会替代默认的CMD /bin/bash 输出系统的版本信息了。

若是使用 shell 格式的话, 实际的命令会被包装为 sh -c 的参数的形式进行执行。

好比:

CMD echo $HOME
复制代码

在实际执行中,会将其变动为

CMD [ "sh", "-c", "echo $HOME" ]
复制代码

固然还有不少初学者特别容易犯的问题,就是去启动后台服务,好比:

CMD service nginx start
复制代码

这样子去用,会发现容器运行了一会就自动退出了。

因此,?????

咱们以前不止一次的提醒过,容器不是虚拟机,容器就是进程,容器内的应用都应该之前台运行,而不是像虚拟机,物理机那样去运行后台服务,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它须要关心的东西。

怎么理解呢?想一想偶像剧,容器是女主角,主进程是男主角

你走了,我也不活了(撕心裂肺大哭),大概就是这么个意思。

正如咱们前面所提出的,实际上CMD service nginx start 最终会被理解为:

CMD [ "sh", "-c", "service nginx start"]
复制代码

在这里,咱们主进程实际就是sh,当咱们service nginx start执行完毕以后,那么sh天然就会退出了,主进程退出,容器天然就会相应的中止。争取的作法是直接执行nginx可执行文件,而且声明之前台的形式运行:

CMD ["nginx", "-g", "daemon off;"]
复制代码

到这里,咱们示例中所涉及到的命令已经讲完了,固然,这并不够,Docker中仍然有不少命令是咱们使用比较频繁的,下面咱们的部分做为补充,讲一下其余经常使用的DockerFile命令。

COPY 命令:

功能:复制文件

Docker依旧提供了两种格式供咱们选择:

  • COPY [--chown=:] <源路径>... <目标路径>
  • COPY [--chown=:] ["<源路径 1>",... "<目标路径>"]

到这里你们其实会发现,Docker提供的两种格式其实都是差很少的用法,一种相似于命令行,一种则相似于函数调用。

第一种例如(将package.json拷贝到/usr/src/app/目录下):

COPY package.json /usr/src/app/
复制代码

其次,目标路径 能够是容器内的绝对路径,也能够是相对于工做目录的相对路径 ,工做目录能够用 WORKDIR 指令来指定,若是须要改变文件所属的用户或者用户组,能够加上--chown 选项。

须要注意的是,使用 COPY 指 令,源文件的各类元数据都会保留。好比读、写、执行权限、文件变动时间等。这 个特性对于镜像定制颇有用。

ADD命令:

ADD命令能够理解为COPY命令的高级版,格式和用法与COPY几乎一致,ADD在COPY的基础上增长了一些功能,好比源路径能够是一个URL连接,当你这么用的时候,Docker会尝试着先将该URL表明的文件下载下来,而后复制到目标目录上去,其余的则是在COPY的基础上增长了解压缩之类的操做,码字码的手疼,须要了解的朋友能够去官网查看相关的文档,这里我就不延申了。

VOLUME 定义匿名卷:

在上一篇中,咱们有讲容器卷这个概念,为了防止运行时用户忘记 将动态文件所保存目录挂载为卷,在 Dockerfile 中,咱们能够事先指定某些 目录挂载为匿名卷,这样在运行时若是用户不指定挂载,其应用也能够正常运 行,不会向容器存储层写入大量数据。

例如:

VOLUME /data
复制代码

运行时经过-v参数便可以覆盖默认的匿名卷设置。

USER 命令:

功能:指定当前用户

格式:USER 用户名:用户组

USER 指令和 WORKDIR 类似,都是改变环境状态并影响之后的层。WORKDIR 是改变工做目录,USER 则是改变以后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份。固然,和 WORKDIR 同样,USER 只是帮助你切换到指定用户。

固然这个大前提是,你的User用户是事先存在好的。

完结撒花?

不知不觉间,Docker系列初级入门教程已经发到了第四篇,篇幅也到了一万多字,前三篇文章加起来在掘金上慢慢有了大概1500左右的阅读量,我知道这点对于不少掘金大佬来讲只是微不足道的一点,但对于现阶段的我来讲已经很是知足了,历来没有想到过有一天本身也能够经过分享去帮助到别人,正如我以前经过别人的技术博客学习那样。

这个系列完结了吗?我想初级篇应该是完结了,可是Nginx的初级入门教程,即将到来的Mysql,Netty等等并无,因为目前还没有毕业,尚未接受过工做的毒打(滑稽),因此只能尽本身的能力去写一些基础的入门教程,因此完结了吗?并无,技术之路永无止境,只要咱们一直在坚持学习,我想,咱们能够一直继续下去。

感谢掘金,你们好,我是韩数,咱们下期文章再见!

最后,相关笔记已经同步开源至Github(欢迎star): github.com/hanshuaikan…

必定要记得给个star哦。

提早祝你们1024程序员节快乐!

相关文章
相关标签/搜索