社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

Docker小白到实战之Dockerfile解析及实战演示,果然顺手

dotNET跨平台 • 2 年前 • 259 次点击  

前言

使用第三方镜像肯定不是学习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=[:] [AS ]
 ARG  CODE_VERSION=latest # 定义变量
 FROM base:${CODE_VERSION} # 指定基础镜像
2.2 MAINTAINER/LABEL 关键字

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

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

用法如下:

 # LABEL = 


    
= = ...
 LABEL com.example.version="0.0.1-beta" 
 LABEL vendor1="ACME Incorporated"
2.3 RUN 关键字

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

用法如下:

 # 两种命令方式都可以
 # RUN 
 # 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 = ...
 # 指定环境变量
 ENV PATH=/usr/local/postgres-$PG_MAJOR/bin:$PATH
2.6 ADD 关键字

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

用法如下:

 # 两种命令方式都可以
 # ADD [--chown=:... 
 # ADD [--chown=:] ["",... ""]
 ADD https://example.com/big.tar.xz /usr/src/things/
2.7 COPY 关键字

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

用法如下:

 # 拷贝资源到容器,两种命令格式都行
 # COPY [--chown=:... 
 # COPY [--chown=:] ["",... ""]
 COPY requirements.txt /tmp/
2.8 VOLUME 关键字

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

用法如下:

 # 挂载数据卷
 VOLUME ["/data"]
 VOLUME /myvol
2.9 EXPOSE 关键字

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

用法如下:

 # EXPOSE  [/...]
 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 [=]
 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之前文章目录:

  1. Docker小白到实战之开篇概述

  2. Docker小白到实战之常用命令演示,通俗易懂

  3. Docker小白到实战之容器数据卷,整理的明明白白

好了,下次聊聊Docker中的网络应用,关注“Code综艺圈”,和我一起学习吧;

图片


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/119802
 
259 次点击