linux怎么查看本机内存大小
233
2022-10-19
DockerFile使用与自定义镜像详解
【1】DockerFile是什么
简单来说,Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建的三个步骤:
编写Dockerfile文件docker build 生成镜像docker run 创建容器运行
这里以我们熟悉的Centos为例 ,查看DockerFile大致文件结构
FROM scratchADD CentOS-8-Container-8.1.1911-20200113.3-layer.x86_64.tar.xz /LABEL org.label-schema.schema-version="1.0" \ org.label-schema.name="CentOS Base Image" \ org.label-schema.vendor="CentOS" \ org.label-schema.license="GPLv2" \ org.label-schema.build-date="20200114" \ org.opencontainers.image.title="CentOS Base Image" \ org.opencontainers.image.vendor="CentOS" \ org.opencontainers.image.licenses="GPL-2.0-only" \ org.opencontainers.image.created="2020-01-14 00:00:00-08:00"CMD ["/bin/bash"]
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料Docker镜像是软件的交付品Docker容器则可以认为是软件的运行态
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像。当运行 Docker镜像时,会创建Docker容器,容器是直接提供服务的。
【2】DockerFile构建过程解析
① Dockerfile内容基础知识
每条保留字指令都必须为大写字母且后面要跟随至少一个参数指令按照从上到下,顺序执行#表示注释每条指令都会创建一个新的镜像层,并对镜像进行提交
② Docker执行Dockerfile的大致流程
docker从基础镜像运行一个容器执行一条指令并对容器作出修改执行类似docker commit的操作提交一个新的镜像层docker再基于刚提交的镜像运行一个新容器执行dockerfile中的下一条指令直到所有指令都执行完成
③ DockerFile体系结构(保留字指令)
FROM:基础镜像,当前新镜像是基于哪个镜像的MAINTAINER:镜像维护者的姓名和邮箱地址RUN:容器构建时需要运行的命令EXPOSE:当前容器对外暴露出的端口WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点ENV:用来在构建镜像过程中设置环境变量
ENV MY_PATH /usr/mytest 这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量,比如:WORKDIR $MY_PATH
ADD:将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包COPY:类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。实例如COPY src dest 或者 COPY ["src", "dest"]
//src dest均为目录,表示把src下的文件拷贝到dest目录下 COPY server /usr/local/server/ //src为文件,dest为目录,表示把src这个文件拷贝到dest目录下 COPY run.sh /usr/local/sbin/
VOLUME:容器数据卷,用于数据保存和持久化工作CMD:指定一个容器启动时要运行的命令。Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。
CMD ["/usr/local/apache-tomcat-8.5.42/bin/catalina.sh",“run”] CMD /usr/local/apache-tomcat-8.5.42/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.42/logs/catalina.out
cmc命令的三种格式
CMD ["executable","param1","param2"] (exec格式)CMD ["param1","param2"] (参数列表格式,作为ENTRYPOINT的默认参数)CMD command param1 param2 (shell格式)#实例CMD echo "hello cmd!"CMD ["/bin/bash", "-c", "echo 'hello cmd!'"]
ENTRYPOINT :指定一个容器启动时要运行的命令。ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。
ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)ENTRYPOINT command param1 param2 (shell form)
ONBUILD:子镜像继承父镜像,子镜像运行时,父镜像ONBUILD被触发。
BUILD | BOTH | RUN |
FROM | WORKDIR | CMD |
MAINTAINER | USER | ENV |
COPY | EXPOSE | |
ADD | VOLUME | |
RUN | ENTRYPOINT | |
ONBUILD |
④ ONBUILD测试
两个DockerFile文件:DockerFile3与DockerFile4。
DockerFile3内容如下:
FROM centosRUN yum install -y curlENTRYPOINT [ "curl", "-s", "]ONBUILD RUN echo "now ,dockerfile3 is execute..."
生成镜像myip:
docker build -f DockerFile3 -t myip .
DockerFile4内容如下:
FROM myipRUN yum install -y curlENTRYPOINT [ "curl", "-s", "]
生成镜像myip4:
【3】案例之自定义镜像mycentos
首先需要了解一个Base(scratch)镜像。Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
① 编写DockerFile文件
目标: 默认centos镜像是不支持登陆后的默认路径、 vim编辑器、查看网络配置ifconfig的,这里自定义DockerFile使其支持。
在自定义目录下创建DockerFile文件,如/mydocker/下,内容如下:
##使用的时候注意去掉注释 可以在vim窗口模式下使用dd命令快速删除一行#继承自centos镜像FROM centos#作者与邮箱MAINTAINER jane
② 构建生成镜像
在当前路径下/mydocker/执行如下格式命令:
docker build -f DockFile路径 -t 新镜像名字:TAG .
会看到 docker build 命令最后有一个 . ,其表示当前目录。
实例如下:
docker build -f DockerFile -t mycentos:2.0 .
[root@localhost mydocker]# docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEmycentos 2.0 df8160eb077f About a minute ago 314.3 MBjane/centos latest b3a32e0a2930 14 hours ago 237.1 MBbadtomcat 1.0 4c900ee6d6e3 19 hours ago 528.7 MBtomcat latest dd7dc39599b6 37 hours ago 528.6 MBcentos latest 495a24dc98e8 3 weeks ago 237.1 MBhello-world latest 9f5834b25059 13 months ago 1.84 kB
③ 创建容器并运行
命令格式如下:
docker run -it 新镜像名字:TAG [/bin/bash]
实例如下:
docker run -it df8160eb077f /bin/bash
④ 列出镜像的变更历史
命令格式如下:
docker history 镜像ID
【4】CMD/ENTRYPOINT 镜像案例
二者相似之处都是都是指定一个容器启动时要运行的命令。
① CMD命令
The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well.
cmd主要用于提供给容器一个默认的可执行脚本命令。也就是容器启动以后,默认的执行的命令。也就是意味着如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么,就会使用cmd指定的默认的执行命令执行。
三种格式
The CMD instruction has three forms: CMD ["executable","param1","param2"] (exec form, this is the preferred form)CMD ["param1","param2"] (as default parameters to ENTRYPOINT)CMD command param1 param2 (shell form)
shell格式
命令默认是在“/bin/sh -c”下执行的。实例如下
FROM centos CMD echo "I'm janus"
命令格式
FROM centos CMD ["/bin/bash", "-c", "echo 'I'm janus'"]
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。另外,如果docker run后面跟了自定义命令,那么CMD 会被 docker run 之后的参数替换。实例如下:
docker run -it -p 8888:8080 tomcat ls -l
② ENTRYPOINT
An ENTRYPOINT allows you to configure a container that will run as an executable.也就是说entrypoint才是正统地用于定义容器启动以后的执行体的,其实我们从名字也可以理解,这个是容器的“入口”。
docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合。
ENTRYPOINT has two forms: ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)ENTRYPOINT command param1 param2 (shell form)
① 命令行格式
也就是带中括号的,和cmd的中括号形式是一致的,但是这里是在shell的环境下执行的,与cmd有区别。
如果run命令后面有东西,那么后面的全部都会作为entrypoint的参数。如果run后面没有额外的东西,但是cmd有,那么cmd的全部内容会作为entrypoint的参数,这同时是cmd的第二种用法。如果要在run里面覆盖,使用--entrypoint即可。
② shell格式
在这种模式下,任何run和cmd的参数都无法被传入到entrypoint里。官网推荐命令行格式。
FROM centos CMD ["I'm janus"]ENTRYPOINT echo
③ CMD测试步骤
##新增DockerFile文件[root@localhost mydocker]# vim DockerFile2##build创建镜像[root@localhost mydocker]# docker build -f DockerFile2 -t myip .Sending build context to Docker daemon 4.096 kBSending build context to Docker daemonStep 0 : FROM centos ---> 495a24dc98e8Step 1 : RUN yum install -y curl ---> Running in 4fd0ea665eafCentOS-8 - AppStream 704 kB/s | 6.4 MB 00:09CentOS-8 - Base 410 kB/s | 5.0 MB 00:12CentOS-8 - Extras 2.2 kB/s | 2.1 kB 00:00Package curl-7.61.1-11.el8.x86_64 is already installed.Dependencies resolved.Nothing to do.Complete! ---> 58218afb3e20Removing intermediate container 4fd0ea665eafStep 2 : CMD curl -s ---> Running in 6d14169fb841 ---> af6a8441dcc9Removing intermediate container 6d14169fb841Successfully built af6a8441dcc9[root@localhost mydocker]# docker run af6a8441dcc9{"ip": "114.244.77.52", "country": "北京市", "city": "联通"}
DockerFile文件内容如下:
FROM centosRUN yum install -y curlCMD [ "curl", "-s", "]
如果我们希望显示 HTTP 头信息,就需要加上 -i 参数,但是就会报错。
[root@localhost mydocker]# docker run c18008dfcc35 -iError response from daemon: Cannot start container 42d9aaf8ffabde5b000bea14673b4d2be86fa8c66c16d3feccece3dc4d2d2b59: [8] System error: exec: "-i": executable file not found in $PATH
我们可以看到可执行文件找不到的报错,executable file not found。之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。因此这里的 -i 替换了原来的 CMD,而不是添加在原来的 curl -s 后面。而 -i 根本不是命令,所以自然找不到。
那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令:
$ docker run myip curl -s -i#小课堂:所以你还可以输入其他你想实现某个功能的命令
④ ENTRYPOINT测试步骤
复制并修改DockerFile文件为DockerFile3:
FROM centosRUN yum install -y curlENTRYPOINT [ "curl", "-s", "]
重复上面构建、运行步骤,结果如下:
【5】自定义Tomcat镜像
① 在/mydocker/路径下创建路径mytomcat,并放入jdk与tomcat二进制压缩包
#纯粹为了copy命令使用touch c.txt
② 在mytomcat目录下新建DockerFile文件
内容如下:
FROM centosMAINTAINER jane
③ 构建生成镜像
命令如下:
docker build -f DockerFile -t mytomcat8.5 .
详细过程如下所示:
[root@localhost mytomcat]# docker build -f DockerFile -t mytomcat8.5 .Sending build context to Docker daemon 193 MBSending build context to Docker daemonStep 0 : FROM centos ---> 495a24dc98e8Step 1 : MAINTAINER jane
[root@localhost test]# docker exec 9169df7aa44f java -versionjava version "1.8.0_121"Java(TM) SE Runtime Environment (build 1.8.0_121-b13)Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)[root@localhost test]#
④ 创建容器实例并运行
命令如下:
docker run -d -p 9080:8080 --name mytomcat8 -v /mydocker/mytomcat/test:/usr/local/apache-tomcat-8.5.42/webapps/test -v /mydocker/mytomcat/tomcatlogs/:/usr/local/apache-tomcat-8.5.42/logs --privileged=true mytomcat8.5
docker logs -f -t --tail 10 712e7776a36e
docker exec -it 9169df7aa44f /bin/bash
⑤ test里面放入项目文件
在test项目里面放入WEB-INF/web.xml 、a.jsp,将会同步到容器内webapps/test里面。
#9169df7aa44f 为容器ID[root@9169df7aa44f test]# lsWEB-INF a.jsp[root@9169df7aa44f test]#
【6】build时文件过大
docker client会默认把Dockerfile同级所有文件发给docker Deamon中,故而如果Dockerfile同级别下有其他文件可能会导致build生成的镜像过大。
那么如何解决呢?
第一种解决方案
build时删除掉无用文件,比如logs
第二种解决方案
保证Dockerfile同级别下没有其他多余文件
第三种解决方案
其实可以参考.gitignore的思想在Dockerfile同级别下创建一个.dockerignore文件。
.dockerignore匹配规则
符号 | 作用 |
| 注释 |
| 匹配0或多个非/的字符 |
| 匹配1个非/的字符 |
| 0个或多个目录 |
| |
#comment#代表根目录(上下文环境目录中)中以abc开头的任意直接子目录或者直接子文件将被忽略#如/abc abc.txt/abc*#代表根目录(上下文环境目录中)中任意直接子目录中以abc开头的任意直接子目录或者直接子文件将被忽略#如 /file/abc /file/abc.txt*/abc*#代表根目录(上下文环境目录中)中任意两级目录下以abc开头的任意直接子目录或者直接子文件将被忽略#如 /file1/file2/abc /file1/file2/abc.txt*/*/abc*#排除根目录中的文件和目录,其名称是单字符扩展名temp。例如,/tempa与/tempb被排除在外。temp? #Docker还支持一个**匹配任意数量目录(包括零)的特殊通配符字符串**/abc*#以!(感叹号)开头的行可用于对排除项进行例外处理,比如原本包含了README.md这个文件的过滤,但是加了如下一行后#就不会再过滤README.md,依然会将其提交到守护进程。!README.md#异常规则的放置位置会影响行为*.md!README*.mdREADME-secret.md#README-secret.md 仍然会被忽略 *.mdREADME-secret.md!README*.md#README-secret.md 不会被忽略您甚至可以使用该.dockerignore文件来排除Dockerfile和.dockerignore文件。这些文件仍然发送到守护程序,因为它需要它们来完成它的工作。但是ADD和COPY命令不会将它们复制到镜像中。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~