Docker小白到实战之Dockerfile解析及实战演示,果然顺手
前言
使用第三方镜像肯定不是学习Docker的最终目的,最想要的还是自己构建镜像;将自己的程序、文件、环境等构建成自己想要的应用镜像,方便后续部署、启动和维护;而Dockerfile就是专门做这个事的,通过类似简单编码的形式,最终就可以构建出属于自己的镜像,所以必须学起来。
正文
1. Dockerfile简介
在日常开发过程中,需要编写对应的程序文件,最后通过编译打包生成对应的可执行文件或是类库;这里的Dockerfile文件就好比平时我们编写的程序文件,但内部的语法和关键字并没有程序那么复杂和繁多,相对来说还是很简单的,最后通过docker build
命令就可以将对应的程序、文件、环境等构建成镜像啦。
在第一篇文章最后就简单使用了Dockerfile构建了一个镜像,这里重新认识下这个Dockerfile文件,如下图:
Dockerfile就是一个文本文件,但不需要指定后缀类型; 文件内容中FROM、WORKDIR、COPY等就是关键字,按照规则写好之后,就可以将指定的文件构建为镜像啦。
构建操作统一由Docker daemon进行,它会先对文件内容语法进行初步验证(语法不对就会返回错误信息),然后逐一运行指令,每次生成一个新的镜像层,直到执行完所有指令,就构建出最终的镜像。 Dockerfile、镜像、容器的关系如下:
总结一下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文件
新建一个项目,啥都不需要改,就用默认的接口演示,如下:
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 build -t myimage:v1.0 .
解析:
- -t:指定镜像的名字及标签,通常 name:tag 或者 name 格式,myimage就是镜像名字,v1.0就是tag;
- -f :指定要使用的Dockerfile路径,这里由于Dockerfile在当前路径,所以不用指定;
- 最后面的点:官方称为构建上下文,点表示指定为当前目录。 会把指定的这个目录下的文件发送给docker daemon进行构建,所以千万不要指定/(斜杠代表根目录,有很多文件的)。
- 其他选项参数小伙伴可以根据需要使用,以上是比较重要的。
3.3 根据构建出来的镜像启动容器,看Dockerfile中的命令效果;
启动容器如下:
ENTRYPOINT ["dotnet", "DockerfileDemo.dll"]
这行代码就等同于的项目目录下直接执行 dotnet DockerfileDemo.dll是一样的,目的就是启动我们的项目。
通过docker logs
可以查看容器内部的日志,如下:
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"]
执行如下命令,构建新的镜像:
# 这里没有显示指定tag 默认就latest
docker build -t newimage .
通过docker logs
看看容器日志,如下:
看看数据卷挂载是否成功,进入容器,看根目录下就会多了Logs目录,也可以通过docker inspect 容器
看容器详细信息,如下:
标签也打成功了:
也可以通过docker inspect 镜像
查看镜像内部的详细信息,执行命令docker inspect newimage
如下:
关于步骤和效果,在Dockerfile注释和图表中已经详细描述。
3.5 CMD和ENTRYPOINT的区别
两个命令都是启动容器时指定执行命令和对应的参数,但两者稍有不同,如下:
- CMD:只能最后一个命令会生效,命令会被docker run之后的参数替换掉;
- ENTRYPOINT:可以追加命令,比如增加参数;
上面构建出来的newimage镜像用到的是ENTRYPOINT,所以我们先来测试一下ENTRYPOINT,如下:
docker run
启动容器时指定了参数 --urls="http://+:9999"
,容器正常启动,并且参数还能生效,等同于在当前目录直接执行如下命令:
dotnet DockerfileDemo.dll --urls="http://+:9999"
现在把ENTRYPOINT换成CMD试试,如下:
# 在以上的Dockerfile中
# 将ENTRYPOINT ["dotnet", "DockerfileDemo.dll"]换成CMD,如下:
CMD ["dotnet", "DockerfileDemo.dll"]
然后重新构建一个镜像试试,测试如下:
如上图,对于CMD而言,如果在运行容器时,后面指定参数,这个参数就会把CMD命令替换掉,不能拼接,导致命令不对,所以报错;但这样就可以执行,如下:
如果在当前构建的上下文目录中不想要一些文件参与构建,可以通过在.dockerignore文件中进行配置,这个和git中的.gitignore一个道理,编写也比较简单,这里就不演示了。
对了,.NetCore的镜像列表可以参照这个地址:https://hub.docker.com/_/microsoft-dotnet-aspnet/,每个镜像都有对应的Dockerfile,感兴趣的小伙伴可以点进去看看,参考参考。
总结
关于Dockerfile的演示就先说那么多,小伙伴们一定要举一反三,上面演示只是一个小例子而已,在正式项目中可以根据需要,编辑出属于符合需求的Dockefile文件,最终构建出方便、好用的镜像,这样开发和运维就和谐了(嘿嘿嘿)。
Docker之前文章目录:
好了,下次聊聊Docker中的网络应用,关注“Code综艺圈”,和我一起学习吧;
Docker小白到实战之Dockerfile解析及实战演示,果然顺手的更多相关文章
- docker学习笔记-05:DockerFile解析
一.DockerFile是什么 1.DockerFile是用来构建docker镜像的构建文件,是由一系列参数和命令构成的脚本. 2.构建三步骤: 手动编写一个dockerfile文件,然后直接dock ...
- Docker小白到实战之Docker网络简单了解一下
前言 现在对于Docker容器的隔离性都有所了解了,但对容器IP地址的分配.容器间的访问等还是有点小疑问,如果容器的IP由于新启动导致变动,那又怎么才能保证原有业务不会被影响,这就和网络有挂钩了,接下 ...
- Docker小白到实战之容器数据卷,整理的明明白白
前言 上一篇把常用命令演示了一遍,其中也提到容器的隔离性,默认情况下,容器内应用产生的数据都是由容器本身独有,如果容器被删除,对应的数据文件就会跟着消失.从隔离性的角度来看,数据就应该和容器共存亡:但 ...
- Docker 实战—使用 Dockerfile 构建镜像
Dockerfile 指令详解请访问:https://www.cnblogs.com/cloudfloating/p/11737447.html 使用 Alpine Linux 作为基础镜像 Alpi ...
- Docker系列(24)- 实战:DockerFile制作tomcat镜像
实战:DockerFile制作tomcat镜像 step-1 准备镜像文件 tomcat压缩包,jdk压缩包! step-2 编写dockerfile文件,官方命名Dockerfile,build会自 ...
- Docker实战-编写Dockerfile
一.编译镜像 1. 编译镜像 Dockerfile类似于Makfile,用户使用docker build就可以编译镜像,使用该命令可以设置编译镜像时使用的CPU数量.内存大小.文件路径等 语法:doc ...
- Dockerfile解析(八)
一.Dockerfile是什么 Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本. 1. 构建的步骤 运行容器:docker run 构建新的镜像:docker ...
- 6、DockerFile解析:三步走、保留字指令
1.dockerfiel是什么 1.是什么 Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本. 2.构建三步骤 编写Dockerfile文件 docker bu ...
- Docker学习(六)Dockerfile构建自定义镜像
Docker学习(六)Dockerfile构建自定义镜像 前言 通过前面一篇文章可以知道怎么去使用一个镜像搭建服务,但是,如何构造自己的一个镜像呢,docker提供了dockerfile可以让我们自己 ...
随机推荐
- 看视频学SignalR—在微软虚拟学院学习SignalR
SignalR把实时Web功能变得异常简单. 如果您希望在几个小时内对SignalR有一个直观的了解,观看微软虚拟学院(MVA)的视频教学Lighting Up Real-Time Web Commu ...
- 手撸一个SpringBoot-Starter
1. 简介 通过了解SpringBoot的原理后,我们可以手撸一个spring-boot-starter来加深理解. 1.1 什么是starter spring官网解释 starters是一组方便的依 ...
- Python小白的数学建模课-15.图论基本概念
图论中所说的图,不是图形图像或地图,而是指由顶点和边所构成的图形结构. 图论不仅与拓扑学.计算机数据结构和算法密切相关,而且正在成为机器学习的关键技术. 本系列结合数学建模的应用需求,来介绍 Netw ...
- CVPR2021 | Transformer用于End-to-End视频实例分割
论文:End-to-End Video Instance Segmentation with Transformers 获取:在CV技术指南后台回复关键字"0005"获取该论文 ...
- 3D性能优化 | 说一说glTF文件压缩
引言 最近做T级互动,需要使用到3D模型.相信大家和我一样,在开始着手的时候,一定会有这么些问题: 1.如何选择3D模型的导出格式 2.如何对模型文件进行优化 3.在大流量的项目中兼容性怎么样 让我们 ...
- 寻找写代码感觉(一)之使用 Spring Boot 快速搭建项目
写在前面 现在已经是八月份了,我已经荒废了半年居多,不得不说谈恋爱确实是个麻烦的事,谈好了皆大欢喜,分手了就是萎靡不振,需要很长一段时间才能缓过来. 人还是要有梦想的,至于实现只不过是一个契机,但凡不 ...
- 2021 年 iOS 应用程序开发七种最佳语言
移动应用程序现在几乎是每个在线业务的必备品.最新的 StatCounter 数据显示,多达56% 的在线连接是通过移动设备建立的,这使它们高于平板电脑和计算机.更重要的是,同一个消息来源说,其中27% ...
- COM笔记-关于HRESULT
HRESULT HRESULT(Here's the RESULT)值分成32位值, HRESULT值中16到30这15个比特位包含的是设备代码.设备代码标识的是可以返回HRESULT返回代码的操作系 ...
- 阿里云rds分区
SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'xw_user_appl ...
- wpf 实现印章,公章效果
能写一些特定外观的控件,是一个做界面开发的程序员的基础技能.基本上,不管你是做web,QT,MFC,Winform,WPF等等,如果自己看到一个比较好看的有趣的效果,能大致推断出它的实现方式并照猫画虎 ...