小知识:Docker小白到实战之Dockerfile解析及实战演示

%小知识:Docker小白到实战之Dockerfile解析及实战演示-猿站网-插图

前言

使用第三方镜像肯定不是学习Docker的最终目的,最想要的还是自己构建镜像;将自己的程序、文件、环境等构建成自己想要的应用镜像,方便后续部署、启动和维护;而Dockerfile就是专门做这个事的,通过类似简单编码的形式,最终就可以构建出属于自己的镜像,所以必须学起来。

正文

1. Dockerfile简介

在日常开发过程中,需要编写对应的程序文件,最后通过编译打包生成对应的可执行文件或是类库;这里的Dockerfile文件就好比平时我们编写的程序文件,但内部的语法和关键字并没有程序那么复杂和繁多,相对来说还是很简单的,最后通过docker build命令就可以将对应的程序、文件、环境等构建成镜像啦。

在第一篇文章最后就简单使用了Dockerfile构建了一个镜像,这里重新认识下这个Dockerfile文件,如下图:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-1猿站网-插图

Dockerfile就是一个文本文件,但不需要指定后缀类型;文件内容中FROM、WORKDIR、COPY等就是关键字,按照规则写好之后,就可以将指定的文件构建为镜像啦。

构建操作统一由Docker daemon进行,它会先对文件内容语法进行初步验证(语法不对就会返回错误信息),然后逐一运行指令,每次生成一个新的镜像层,直到执行完所有指令,就构建出最终的镜像。 Dockerfile、镜像、容器的关系如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-2猿站网-插图

总结一下Dockerfile的知识点;

构建时,指令从上到下逐一执行; 每条指令都会创建一个新的镜像层,每一层都是前一层变化的增量; 使用#号进行注释; 关键字约定都是大写,后面至少跟一个参数;

2. Dockerfile关键字

2.1 FROM 关键字

指定基础镜像, 就是新镜像是基于哪个镜像构建的。

比如建房子,可以在一块空地开始,也可以在别人打好的基石基础上开始, 甚至可以在别人弄好的毛坯房基础上装修即可。

如果要建房的话,可以FROM 空地,或者FROM 打好的基石,或者 FROM 毛坯房, 反正最后建好房就行;

这里需要注意的是,不管咋样,空地是少不了的;构建镜像也一样,最底层肯定有一个最基础的镜像。

建议使用官方的镜像作为基础镜像,推荐使用Alpine这种类型,因为它是严格控制的,而且体积很小。

用法如下:

FROM [–platform=<platform>] <image>[:<tag>] [AS <name>] ARG  CODE_VERSION=latest # 定义变量  FROM base:${CODE_VERSION} # 指定基础镜像 

2.2 MAINTAINER/LABEL 关键字

MAINTAINER 指定维护者的相关信息,也就是构建的镜像是由谁构建的,他的邮箱是什么;

LABLE 就是用于给镜像打标签,以键值对的方式进行指定,相对MAINTAINER 来说比较灵活,可以使用LABLE替代MAINTAINER。

用法如下:

# LABEL <key>=<value> <key>=<value> <key>=<value> …  LABEL com.example.version=“0.0.1-beta” LABEL vendor1=“ACME Incorporated”

2.3 RUN 关键字

构建过程中需要运行的命令, 比如在构建过程中需要执行一条命令下载对应的包,这里就需要用到RUN关键字;

用法如下:

# 两种命令方式都可以  # RUN <command>  # RUN [“executable”“param1”“param2” # 执行命令,Linux支持的相关命令  RUN /bin/bash -c source $HOME/.bashrc; echo $HOME RUN [“/bin/bash”“-c”“echo hello”

2.4 WORKDIR 关键字

根据镜像启动容器时,通常需要进入到容器内部;则可以通过WORKDIR指定进入容器时的目录;

用法如下:

WORKDIR /path # 指定路径 

2.5 ENV 关键字

可以在构建过程中设置环境变量;就好比平时我们安装完程序,需要配置环境变量,方便访问;ENV关键字就是根据需求可以设置对应的环境变量;

用法如下:

# ENV <key>=<value> …  # 指定环境变量  ENV PATH=/usr/local/postgres-$PG_MAJOR/bin:$PATH 

2.6 ADD 关键字

将宿主机的资源拷贝进镜像中,会自动解压缩,而且还能从远程宿主机中读取资源并拷贝到镜像中;

用法如下:

# 两种命令方式都可以  ADD [–chown=<user>:<group>] <src>… <dest> ADD [–chown=<user>:<group>] [“<src>”,… “<dest>”] ADD https://example.com/big.tar.xz /usr/src/things/ 

2.7 COPY 关键字

将宿主机的资源拷贝到镜像中,只支持读取构建所在宿主机的资源。相对于ADD关键字来说更加透明,操作什么就是什么。

用法如下:

# 拷贝资源到容器,两种命令格式都行  # COPY [–chown=<user>:<group>] <源地址>… <目标地址> # COPY [–chown=<user>:<group>] [“<源地址>”,… “<目标地址>”] COPY requirements.txt /tmp/ 

2.8 VOLUME 关键字

挂载数据卷,之前在常用命令那说到通过命令的方式进行数据卷挂载,在Dockerfile中使用VOLUME指定挂载路径即可,根据构建出来的镜像运行容器时,默认就有构建时挂载的信息。

用法如下:

# 挂载数据卷  VOLUME [“/data” VOLUME /myvol 

2.9 EXPOSE 关键字

指定运行容器时对外暴露的端口;即根据镜像启动容器时,容器向外暴露端口。

用法如下:

# EXPOSE <port> [<port>/<protocol>…]  EXPOSE 80/tcp # 暴露端口  EXPOSE 80/udp 

2.10 CMD 关键字

指定启动容器时要执行的命令,只有最后一个会生效;即根据镜像启动容器时,容器需要执行啥命令。

用法如下:

# 两种格式都行  # CMD [“param1”,“param2” # CMD command param1 param2  # 执行命令统计 行数、字数、字节数  CMD echo “This is a test.” | wc –  # 执行wc –help命令  CMD [“/usr/bin/wc”,“–help”

2.11 ENTRYPOINT 关键字

指定根据镜像启动容器时要执行的命令,可以追加命令;执行时机同CMD。

用法如下:

# ENTRYPOINT [“executable”“param1”“param2” # ENTRYPOINT command param1 param2  ENTRYPOINT [“top”“-b”

2.12 ARG 关键字

通过ARG指令定义了一个变量;和写代码时定义的变量一样,根据需要,定义就行啦。

用法如下:

# ARG <name>[=<default value>]  ARG user1=someuser  ARG buildno=1 

2.13 ONBUILD 关键字

基于父镜像构建新的镜像时,父镜像的OBUILD会被触发。

3. 实战演示

这里还是以.NetCore项目构建镜像为例,其他编程语言的项目同理;这次咱们一步一步的来,搞清楚每个命令的使用。

以下关于项目创建和发布的具体细节在第一篇最后就分享了,小伙伴可以参考,这里主要演示Dockerfile关键字。

3.1 准备项目和Dockerfile文件

新建一个项目,啥都不需要改,就用默认的接口演示,如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-3猿站网-插图

Dockerfile内容如下:

# 指定基础镜像,在此基础上构建自己的项目镜像  FROM mcr.microsoft.com/dotnet/core/aspnet:3.1  # 指定自己的工作目录,进入容器时目录  WORKDIR /myApp  # 将构建上下文目录下的文件拷贝到容器的当前工作目录中,即/myApp  COPY . .  # 容器向外暴露端口,项目以什么端口启动就暴露对应的端口  EXPOSE 80  # 执行命令,这里默认是以80端口启动的  #就类似于在Linux系统的项目目录下执行 dotnet DockerfileDemo.dll 是一样的  ENTRYPOINT [“dotnet”“DockerfileDemo.dll”

记得右键Dockerfile,选择属性,然后设置Dockerfile为始终复制,这样后续更新变动,发布时就会自动拷贝到对应的发布目录。

3.2 以文件的形式发布项目,并连同Dockerfile拷贝到安装好Docker的机器上进行构建(这里还是用我的云服务器);

%小知识:Docker小白到实战之Dockerfile解析及实战演示-4猿站网-插图

docker build -t myimage:v1.0 .解析:

-t:指定镜像的名字及标签,通常 name:tag 或者 name 格式,myimage就是镜像名字,v1.0就是tag; -f :指定要使用的Dockerfile路径,这里由于Dockerfile在当前路径,所以不用指定; 最后面的点:官方称为构建上下文,点表示指定为当前目录。会把指定的这个目录下的文件发送给docker daemon进行构建,所以千万不要指定/(斜杠代表根目录,有很多文件的)。 其他选项参数小伙伴可以根据需要使用,以上是比较重要的。

3.3 根据构建出来的镜像启动容器,看Dockerfile中的命令效果;

启动容器如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-5猿站网-插图

ENTRYPOINT [“dotnet”, “DockerfileDemo.dll”]这行代码就等同于的项目目录下直接执行 dotnet DockerfileDemo.dll是一样的,目的就是启动我们的项目。

通过docker logs可以查看容器内部的日志,如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-6猿站网-插图

3.4 丰富化Dockefile文件内容并查看构建之后的细节

文件内容如下:

# 指定基础镜像,在此基础上构建自己的项目镜像  FROM mcr.microsoft.com/dotnet/core/aspnet:3.1  # 指定维护人  MAINTAINER CodeZYQ<1137533407@qq.com>  # 打标签  LABEL createname=“CodeZYQ” # 指定自己的工作目录,进入容器时目录 app  WORKDIR /myapp  # 将构建上下文目录下的文件拷贝到容器中的工作目录中  COPY . .  # 定义变量  ARG myPort=8080  # 使用环境变量方式改变启动端口,拼接用到了定义的变量  ENV ASPNETCORE_URLS=http://+:$myPort  # 通过RUN 执行相关命令,根据需要执行相关命令  RUN mkdir testDir  # 挂载数据卷,这里模拟挂载日志目录  VOLUME /Logs  # 容器向外暴露端口,项目以什么端口启动就暴露对应的端口  EXPOSE $myPort  # 执行命令,这里默认是以80端口启动的  # 就类似于在Linux系统的项目目录下执行 dotnet DockerfileDemo.dll 是一样的  ENTRYPOINT [“dotnet”“DockerfileDemo.dll”

执行如下命令,构建新的镜像:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-7猿站网-插图

通过docker logs看看容器日志,如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-8猿站网-插图

看看数据卷挂载是否成功,进入容器,看根目录下就会多了Logs目录,也可以通过docker inspect 容器 看容器详细信息,如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-9猿站网-插图

标签也打成功了:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-10猿站网-插图

也可以通过docker inspect 镜像查看镜像内部的详细信息,执行命令docker inspect newimage如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-11猿站网-插图

关于步骤和效果,在Dockerfile注释和图表中已经详细描述。

3.5 CMD和ENTRYPOINT的区别

两个命令都是启动容器时指定执行命令和对应的参数,但两者稍有不同,如下:

CMD:只能最后一个命令会生效,命令会被docker run之后的参数替换掉; ENTRYPOINT:可以追加命令,比如增加参数;

上面构建出来的newimage镜像用到的是ENTRYPOINT,所以我们先来测试一下ENTRYPOINT,如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-12猿站网-插图

docker run启动容器时指定了参数 –urls=”http://+:9999″,容器正常启动,并且参数还能生效,等同于在当前目录直接执行如下命令:

dotnet DockerfileDemo.dll –urls=”http://+:9999″

现在把ENTRYPOINT换成CMD试试,如下:

# 在以上的Dockerfile中  # 将ENTRYPOINT [“dotnet”“DockerfileDemo.dll”]换成CMD,如下:  CMD [“dotnet”“DockerfileDemo.dll”

然后重新构建一个镜像试试,测试如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-13猿站网-插图

如上图,对于CMD而言,如果在运行容器时,后面指定参数,这个参数就会把CMD命令替换掉,不能拼接,导致命令不对,所以报错;但这样就可以执行,如下:

%小知识:Docker小白到实战之Dockerfile解析及实战演示-14猿站网-插图

如果在当前构建的上下文目录中不想要一些文件参与构建,可以通过在.dockerignore文件中进行配置,这个和git中的.gitignore一个道理,编写也比较简单,这里就不演示了。

对了,.NetCore的镜像列表可以参照这个地址:https://hub.docker.com/_/microsoft-dotnet-aspnet/,每个镜像都有对应的Dockerfile,感兴趣的小伙伴可以点进去看看,参考参考。

%小知识:Docker小白到实战之Dockerfile解析及实战演示-15猿站网-插图

总结

关于Dockerfile的演示就先说那么多,小伙伴们一定要举一反三,上面演示只是一个小例子而已,在正式项目中可以根据需要,编辑出属于符合需求的Dockefile文件,最终构建出方便、好用的镜像,这样开发和运维就和谐了(嘿嘿嘿)。

原文链接:https://mp.weixin.qq.com/s/NjByfjyU0uZGSIPptIo2Cw

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:如何快速的在 Kubernetes 上部署云原生微服务网关 APISIX

2023-3-19 13:17:31

建站知识

小知识:什么是容器镜像?

2023-3-19 13:32:31

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索