第二口docker的感觉 —— Dockerfile
前言
首先我们来思考这样一个问题:如果将改变了一些配置的Container在生成一个镜像?
正文
就前言的问题,我做一下解答:
通过docker commit命令,这个命令的目的是将我们的最新修改作为镜像的一层进行构建,命令详情参考:
https://docs.docker.com/engine/reference/commandline/commit/
❌但是这种方式方式我们并不提倡,因为这种构建方式相当于一个黑盒的构建,别人也不知道你具体做了那些操作,这个时候就需要引出我们的"构建好助手"——DockerFile
dockerfile是把你所有想要需要的地方都表现在了纸面上,这样我们可以明确知道所有的修改内容。
dockerfile的具体写法我们在后面进行详细的讨论。 但是在这里我们要明确一个问题,Dockerfile其实并不是向镜像里直接写入的,因为镜像是只读的。docker在这个时候创建了一个临时的容器,然后写入内容之后,再把临时容器删除。
DockerFile使用说明
我们创建自己需要的镜像的时候,可以通过commit和dockerfile的形式进行构建,但是前面也说了,官方推荐的还是dockerfile的形式。我们其实很容易的把它理解为一个构建脚本,docker为我们提供了很多可以使用的命令,下面我会一一说明。
基本指令说明
-
ARG指令**
定义创建镜像过程中使用的变量,相当于我们为docker build - -build-arg赋值。镜像编译结束后,这个变量将不会被保存ARG version=1.0
-
FROM指令
指定我们要在哪个image之上再进行构建,尽量使用官方image进行base image,为了安全。并且一个Dockerfile,必须要以From指令作为开头(ARG是唯一一个可以先于From命令的)FROM debian:latest
-
LABLE指令
像是代码里的注释一样,一些概括的维护者信息。LABLE author=harry
-
ENV指令
定义变量,可以在dockerfile下方进行使用,例如我们定义了 ENV USER harry,那么下面可以这样使用 "${USER}"ENV FILE_LOCATION /usr/local/file
- USER指令
指定运行容器时的用户是谁 -
WORKDIR指令
进入到我们指定的目录中,如果没有这个目录会自动进行创建,用WORKDIR,代替 RUN cd。尽量使用绝对目录,不要使用相对目录。WORKDIR /usr/local WORKDIR tomcat/config # 可以连续指定路径,如果像上述一样,指定的路径为/usr/local/tomcat/configs
-
RUN指令
每执行一次RUN就是就会产生镜像的一层,使用 "&&" 将多个命令串联起来,如果需要换行在最后需要使用" " 反斜杠。环境的运行与搭建,大多数情况下需要这个命令RUN yum update \ && yum install -y nginx #上述操作先更新yum,然后下载nginx
-
CMD指令
设置启动后默认执行的命令和参数。如果docker run 进行了指定了命令,例如 docker run -it … /bin/bash。则不会运行CMD中的命令,而且CMD定义多个,后面会覆盖之前的。启动tomcat命令 CMD ['catalina.sh', 'run']
-
ENTRYPOINT指令
设置容器启动时默认执行的命令和参数,该命令会在启动容器后作为根命令执行,通过名称可以看出来是入口。让容器以应用程序或者服务去执行。并且ENTRYPOINT一定会执行将一个shell脚本作为docker启动的入口。 ENTRYPOINT ['/entry.sh']
-
COPY指令
把本地文件拷贝到docker里去,COPY指令优于ADD指令,如果需要添加远程文件可以使用 curl或者wgetCOPY . /temp
-
ADD指令
是把本地的文件复制到docker里去,不过不光如此,还会对压缩文件自动进行解压缩ADD . /temp
-
VOLUME指令
启动容器时,可以在本地或者是其他容器创建数据卷挂载点,用于存放数据库和持久化数据#指定挂载点为 /temp/mount VOLUME /temp/mount
-
EXPOSE指令
声明镜像内部服务监听的端口,一次可以暴露多个端口#暴露22端口,和8888端口 EXPOSE 22 8888
-
ONBUILD指令
指定自己的子镜像都会执行哪些命令#把当前目录下的所有东西拷贝到/app/src目录下 ONBUILD COPY . /app/src
DockerFile的写法的关键在于:环境 + 工程代码 + 运行
DockerFile的最佳实践,请看官网:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
ARG和ENV的区别
两个看起来都是生命变量用的,他们之间的区别在于ARG时创建镜像过程中使用的变量,在启动后的容器中不能使用。而ENV在容器中可以使用
RUN,CMD以及ENTRYPOINT的相同点以及区别
这里要着重说一下RUN 和 CMD和ENTRYPOINT,他们都可以使用exec格式和shell格式
exec格式举例:
CMD ['/bin/echo', 'hello world']
shell格式举例:
CMD echo 'hello world'
但是要注意:如果使用exec格式,打印一个环境变量
CMD['/bin/echo', 'hello world $name'],打印的会是 hello world name的。
这个时候可以考虑使用shell格式,或者说把exec格式进行改造一下,改成如下格式:
CMD['/bin/bash','-c','echo hello world $name ']
另外值得注意的是,RUN命令用于构建镜像,CMD和ENTRYPOINT用于指定容器启动时的一些默认指令和参数。
CMD与ENTRYPOINT的共同点
两者在dockerfile中各自都只能声明一次,声明多次,不会报错,但是只有最后一条命令会生效。
CMD与ENTRYPOINT的区别
二者既然都是作为容器启动时的命令,那么他们的区别在哪里呢?
通过我去查阅官网,官网的意思是说ENTRYPOINT是docker容器的主命令,而默认的一些参数会在CMD中进行指定。
请看下方代码:
ENTRYPOINT ['/bin/echo', 'hello'] CMD ['world']
如果我们运行
docker run -it < image > 会输出 hello world
而如果我们运行
docker run -it < image > harry 会输出 hello harry
这就是因为我上面说过的,如果run的时候没有指定CMD会执行,如果指定了命令就不会执行CMD了。
所以总结起来他们两者的关键区别在于:
CMD会被作为命令或者参数在ENTRYPOINT 参数后追加。
CMD可被覆盖,ENTRYPOINT不会被覆盖
CMD结合ENTRYPOINT的使用
想象一下这样一个简单的场景,我们只希望我们的docker,不作为一个应用程序启动,而是用做一个工具。假设为一个压力测试的工具,这个工具需要被指定一些参数例如说 --vm 之类的我们可以通过 ->
CMD["/usr/bin/strees",'--vm 1']这种形式进行启动。但是有没有想过,这样的话变量值就被限制死了,有什么好办法做到docker启动的时候动态传入吗?我都这么说了,当然是有的:
FROM ubuntu RUN apt-get update && apt-install -y stress ENTRYPOINT ["/usr/bin/stress"] CMD[]
这样在启动的使用就可以动态的将变量传入:
docker run -it dockerImage名称 --vm 1
最后总结一下,其实如果CMD和ENTRYPOINT结合的来,那么ENTRYPOINT是用来指定命令的,而CMD中的则是用来指定参数的。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
第一口docker的感觉——基本知识
前言 前一阵的工作,大多数是与部署相关的,通过将项目打包,然后利用docker,部署在AWS上去。就在这一段时间里面我便对docker产生了浓厚的兴趣,这也就激发我去深入研究的一个动力。Docker的出现是一种历史趋势,因为微服务的出现,导致了使用的技术更加多元化,所以在部署上的难度也变得更大。而docker可以减轻我们在部署上面的复杂性。 docker相当于起到了承上启下的桥梁作用:将App连带环境一同打包直接部署到服务器上。 如果是使用Mac或者windows系统使用docker的话,建议使用Vagrant,它是不需要使用iso镜像就可以创建虚拟机的,这样的好处是方便我们的使用以及删除。那么下面开始我们的docker之旅。 虚拟机与docker之间的区别 我们可以看到,传统的虚拟机是在宿主机之上,又添加了一个新的操作系统,这就直接导致了虚拟机的臃肿,与 不适合迁移。而docker这是直接寄存在宿主机上,完全就会避免大部分虚拟机带来的困扰。 另外Docker其实是一个黑盒的进程,为什么说是黑盒的,区别于传统的进程,Docker可以独立出一个自己的空间,不会使得在docker中的行为以...
- 下一篇
数据卷挂载问题快速恢复
Pod挂载、卸载数据卷出现问题的原因很多,有存储卷设计的缺陷、有相关组件实现的bug、有使用方式不当的可能,面对复杂的应用、存储交互系统,我们需要从两个方面对待数据卷问题: 尽量别出问题:减少存储组件的自身稳定性 && 规范的使用方式。 如何面对问题:首要是快速恢复业务,然后分析问题。 本文阐述的是业务快速恢复方案:当Pod因为数据卷挂载重启失败时,暂不去解决节点挂载的问题,而是让pod先在其他节点启动成功,快速恢复业务,待业务恢复后再去分析出问题的节点。 更新一个Pod,卡在了 ContainerCreating 状态: 例如:你在Deployment类型应用中挂载NAS数据卷,Pod在启动的时候报错为挂载失败: Warning FailedMount 18s kubelet, cn-shenzhen.192.168.1.24 Unable to mount volumes for pod "nas-static-796b49b5f8-svbvh_default(2d483078-1400-11ea-a9b7-00163e084110)": timeout expir...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Hadoop3单机部署,实现最简伪集群