Dockerfile入门:构建镜像的完整指南
目录
一、dockerfile简介
什么是dockerfile?
dockerfile是什么?
为什么要用dockerfile?
Dockerfile、Docker镜像和Docker容器的关系
二、DockerFile需要注意的编写规范
三、Docekrfile指令解析
四、常用的Dockerfile指令详解、格式与用法
4.1 FROM(必须)
4.2 MAINTAINER
4.3 USER
4.4 ENV(必须)
4.5 VOLUME
4.6 EXPOSE
4.7 COPY
4.8 ADD
4.9 WORKDIR
4.10 RUN(必须)
4.11 CMD
五、docker build构建镜像
六、【实战】docker自定义镜像
1、编写Dockerfile
2、构建镜像
3、查看镜像
七、总结
相关文章
一、dockerfile简介
什么是dockerfile?
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令(Instruction)和操作命令;每一条指令构建一层镜像,因此每一条指令的内容,就是描述该层镜像应当如何构建(也就是你要执行的操作命令)。
dockerfile是什么?
- dockerfile是纯文本文件;
- dockerfile是用来构建镜像的;
- dockerfile 用于指示 docker image build 命令自动构建Image的源代码;
dockerfile构建镜像的的格式:
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">docker</span><span style="color:#98c379"> build</span><span style="color:#d19a66"> -t</span><span style="color:#98c379"> 要打的镜像名:版本号</span><span style="color:#98c379"> Dockerfile路径</span></code></span></span>dockerfile构建镜像的的实例:
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">docker</span><span style="color:#98c379"> build</span><span style="color:#d19a66"> -t</span><span style="color:#98c379"> work:v1</span><span style="color:#98c379"> .</span></code></span></span>为什么要用dockerfile?
❓在dockerhub中官方提供很多镜像已经能满足我们99%的服务了,为什么还需要自定义镜像?
🤔️解析:是,官方的镜像很多,同时也可以满足我们99%的服务;但是,如果有的公司要做自己的产品,那么,官网的镜像肯定是没有的,这时候就需要用到自定义镜像,而自定义镜像就是dockerfile构建成的;
🥳我们可以用dockerfile自定义写需要的操作,来用dockerfile的指令来实现,最终采用docker build来构建镜像,构建完镜像可以采用docker save命令打成tar包,以便于日后在其他服务器上使用,也可以采用docker push提交到私有镜像仓库或dockerhub中。
如上图所示,Dockerfile是独立于本地docker实例的一个文本文件,用于自动化地构建具有特定功能的docker镜像。
Dockerfile镜像构建三部曲:
(1)构建Dockerfile文件;
(2)采用docker build命令构建镜像;
(3)采用docker run命令依据镜像运行容器实例。
Dockerfile、Docker镜像和Docker容器的关系
从应用软件开发角度来看,它们分别表示软件开发的三个阶段:
- (1)Dockerfile是软件开发的原材料;
- (2)Docker镜像是软件的交付品;
- (3)Docker容器是Docker交付镜像的实例化,代表软件的实际运行过程。
总结:Dockerfile面向开发,Docker镜像为交付标准,Docker容器与部署、运维相关,三则相辅相成缺一不可,他们是Docker的三大基石。Docker在实际运行中,Dockerfile、Docker镜像、Docker容器三者的运作内容如下所示:
- 1、Dockerfile定义了进程需要的一切内容,包括:代码执行、文件/环境变量、依赖包、运行环境、操作系统发行版本、服务进程、内核进程等等,很多与操作系统底层相关的内容。
- 2、通过docker build指令会生成一个Docker镜像,它是为用户提供各种服务的基础;
- 3、Docker容器则是一个实例化的服务进程。
二、DockerFile需要注意的编写规范
1. # 代表注释
2.指令必须要大写,后面最少需要带一个参数,最多无限制;
3.执行dockerfile的时候,指令是按照从上到下的顺序执行的;
三、Docekrfile指令解析
注意:指令全部都必须为大写,后面跟的是你要执行的操作命令
| 指令 | 功能简介 |
|---|---|
| FROM | 指定构建新image是使用的基础image,通常必须是Dockerfile的第一个有效指令;定义一个基础镜像。 |
| LABEL | 附加到image之上的元数据,键值格式;定义一些元数据。 |
| ENV | 以键值格式设定环境变量,可被其后的指令所调用,且基于新生成的image运行的Container中也会存在这些变量。 |
| RUN | 以FROM中定义的image为基础环境运行指令命令,生成结果将作为新image的一个镜像层,并可由后续指令所使用。RUN后跟要执行的命令。 |
| CMD | 基于dockerfile生成的image运行的container时,CMD能够指定容器中默认运行的程序,因而其只应该定义一次。 |
| ENTRYPOINT | 类似于CMD指令的功能,但不能被命令行指定要运行的应用程序覆盖,且与CMD共存时,CMD的内容将作为该指令中定义的程序的参数。 |
| WORKDIR | 相当于cd切换目录的命令,如果切换的那个地方没有哪个目录,则会自动创建一个目录。 |
| COPY | 相当于cp命令,复制主机上或者前一阶段构建结果中(需要使用--from选项)文件或目录生成新的镜像。 |
| ADD | 与COPY指令的功能相似,但ADD传输压缩包的时候,是可以解压的。 |
| VOLUME | 指定基于新生成的Image运行Container时期望作为volume使用的目录。 |
| EXPOSE | 指定基于新生成的lmage运行Container时期望 暴露的端口,但实际暴露与否取决于"docker run”命令的选项,支持TCP和UDP协议。 |
| USER | 为Dockerfile中该指令后面的RUN、CMD和ENTRYPOING指令中要运行的应用程序指定运行者身份UID,以及一个可选的GID。 |
| ARG | 定义专用于build过程中的变量,但仅对该指标之后的调用生效,其值可由命令行选项"--build-arg"进行传递。 |
| ONBUILD | 触发器,生效于由该Dockerfile 构建出的新l/mage被用于另一个Dockerfile中的FROM指令作为基础镜像时。 |
| STOPSIGNAL | 用于通知Container终止的系统调用信号。 |
| HEALTHCHECK | 定义检测容器应用的健康状态的具体方法。 |
| SHELL | 为容器定义运行时使用的默认shel程序,Linux系统默认使用 [/bin/sh”,"-c"], Windows默认使用 [’cmd', "/S',"/C']。 |
四、常用的Dockerfile指令详解、格式与用法
(必须)是写dockerfile必须有的,没有加的是(可选)的。
4.1 FROM(必须)
指定一个基础镜像,必须为第一个命令。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">FROM</span><span style="color:#98c379"> 基础镜像</span></code></span></span>举例
一个nvidia、cuda10.1的centos7基础镜像
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">FROM</span><span style="color:#98c379"> nvidia/cuda:10.1-cudnn7-devel-centos7</span></code></span></span>4.2 MAINTAINER
维护者信息,可以写邮箱,编辑人等等。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> 邮箱/名字</span></code></span></span>举例
展示邮箱和名字
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> liucy</span> <span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> 121212@qq.com</span> <span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> 121212@163.com</span></code></span></span>4.3 USER
指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">USER</span><span style="color:#98c379"> 用户名</span> <span style="color:#abb2bf">&&</span> <span style="color:#61afef">USER</span><span style="color:#98c379"> user:group </span> <span style="color:#abb2bf">&&</span> <span style="color:#61afef">USER</span><span style="color:#98c379"> uid </span> <span style="color:#abb2bf">&&</span> <span style="color:#61afef">USER</span><span style="color:#98c379"> uid:gid </span> <span style="color:#abb2bf">&&</span> <span style="color:#61afef">USER</span><span style="color:#98c379"> user:gid </span> <span style="color:#abb2bf">&&</span> <span style="color:#61afef">USER</span><span style="color:#98c379"> uid:group</span></code></span></span>举例
指定root用户
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">USER</span><span style="color:#98c379"> root</span></code></span></span>4.4 ENV(必须)
设置环境变量
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">ENV</span><span style="color:#98c379"> 环境变量路径</span></code></span></span>举例
设置jdk1.8的环境变量
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">ENV</span><span style="color:#98c379"> JAVA_HOME=/usr/local/jdk1.8.0_333/</span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> export</span><span style="color:#98c379"> JRE_HOME=</span><span style="color:#e06c75">$JAVA_HOME</span><span style="color:#98c379">/jre</span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> export</span><span style="color:#98c379"> CLASSPATH=.:</span><span style="color:#e06c75">$JAVA_HOME</span><span style="color:#98c379">/lib:</span><span style="color:#e06c75">$JRE_HOME</span><span style="color:#98c379">/lib</span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> PATH=</span><span style="color:#e06c75">$JAVA_HOME</span><span style="color:#98c379">/bin:</span><span style="color:#e06c75">$PATH</span></code></span></span>4.5 VOLUME
用于指定持久化目录(指定此目录可以被挂载出去)
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">VOLUME</span><span style="color:#98c379"> 挂载路径</span></code></span></span>举例
挂载到/data目录
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">VOLUME</span><span style="color:#abb2bf"> [</span><span style="color:#98c379">"/data"</span><span style="color:#abb2bf">]</span></code></span></span>4.6 EXPOSE
设置端口,EXPOSE指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应该就会开启这个端口的服务。
在Dockerfile中写入这样的声明有两个好处:
是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;
在运行是使随机端口映射时,也就是docker run -P(大写)时,会自动随机映射EXPOSE端口。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">EXPOSE</span><span style="color:#98c379"> 端口号</span></code></span></span>举例
设置一个8080端口
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">EXPOSE</span><span style="color:#d19a66"> 8080</span></code></span></span>4.7 COPY
复制文件,相当于linux命令中的cp命令;
功能类似ADD,但是是不会自动解压文件,也不能访问网络资源
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">COPY</span><span style="color:#98c379"> 源文件及路径</span><span style="color:#98c379"> 目标路径</span></code></span></span>举例
复制一个mysql到/usr/local/下
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">COPY</span><span style="color:#98c379"> /root/mysql</span><span style="color:#98c379"> /usr/local/</span></code></span></span>4.8 ADD
将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">ADD</span><span style="color:#98c379"> 源文件及路径</span><span style="color:#98c379"> 目标路径</span></code></span></span>举例
移动一个mysql-2-2.tar
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">ADD</span><span style="color:#98c379"> /usr/local/mysql-2-2.tar</span><span style="color:#98c379"> /root/</span></code></span></span>4.9 WORKDIR
切换目录,相当于linux命令中的cd命令,切换到这个目录,进入容器时就是这个目录,所以,workdir就属于启动默认的目录。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">WORKDIR</span><span style="color:#98c379"> 目录名</span></code></span></span>举例
设置启动就在/data/目录
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">WORKDIR</span><span style="color:#98c379"> /data/</span></code></span></span>4.10 RUN(必须)
构建镜像时执行的命令,执行的命令就是你指定的要他干什么,使用linux命令就可以。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">RUN</span><span style="color:#98c379"> 要执行的命令</span></code></span></span>举例
打镜像时下载一个netstat命令
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">RUN</span><span style="color:#98c379"> yum</span><span style="color:#d19a66"> -y</span><span style="color:#98c379"> install</span><span style="color:#98c379"> net-tools</span></code></span></span>4.11 CMD
构建镜像后调用,也就是在容器启动时才进行调用。写一次dockerfile只能出现一次CMD,而出现CMD的地方,就属于结尾,如果下面有RUN指令,则都不执行。
格式
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">CMD</span><span style="color:#98c379"> 要执行的命令</span></code></span></span>举例
执行删除dockerfile(打完镜像,要删除dockerfile)
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">CMD</span><span style="color:#98c379"> rm</span><span style="color:#d19a66"> -rf</span><span style="color:#98c379"> /data/dockerfile</span></code></span></span>五、docker build构建镜像
dockerfile构建镜像的的格式:
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">docker</span><span style="color:#98c379"> build</span><span style="color:#d19a66"> -t</span><span style="color:#98c379"> 要打的镜像名:版本号</span><span style="color:#98c379"> Dockerfile路径</span></code></span></span>dockerfile构建镜像的的实例:
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">docker</span><span style="color:#98c379"> build</span><span style="color:#d19a66"> -t</span><span style="color:#98c379"> work:v1</span><span style="color:#98c379"> .</span></code></span></span>六、【实战】docker自定义镜像
说明:
此处只是测试使用,并不能用到生产中,(生产中要根据自己的情况来写),可以构建成镜像,也可以创建容器,可以进入容器查看这些文件,但是web页面访问不到,因为没有加入jar包之类的,可以自行放入一个jar包,端口设置3000,然后启动jar包就可以了去访问web页面了。
前言:
有一点特别重要,构建镜像的时候要看好你的文件是不是这个目录,要不然打到一半会报错,说找不到文件,切记要记得放文件,在放文件的目录执行。
1、编写Dockerfile
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#7f848e"><em>#创建Dockerfile文本</em></span> <span style="color:#61afef">vim</span><span style="color:#98c379"> Dockerfile</span></code></span></span><span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#7f848e"><em>#设置基础镜像</em></span> <span style="color:#61afef">FROM</span><span style="color:#98c379"> nvidia/cuda:10.1-cudnn7-devel-centos7</span> <span style="color:#7f848e"><em>#维护者信息</em></span> <span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> liucy</span> <span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> 121212@qq.com</span> <span style="color:#61afef">MAINTAINER</span><span style="color:#98c379"> 121212@163.com</span> <span style="color:#7f848e"><em>#指定运行时的用户以及镜像的实际用户</em></span> <span style="color:#61afef">USER</span><span style="color:#98c379"> root</span> <span style="color:#7f848e"><em>#下载netstat命令</em></span> <span style="color:#61afef">RUN</span><span style="color:#98c379"> yum</span><span style="color:#d19a66"> -y</span><span style="color:#98c379"> install</span><span style="color:#98c379"> net-tools</span> <span style="color:#7f848e"><em>#设置jdk1.8的环境</em></span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> JAVA_HOME=/usr/local/jdk1.8.0_333/</span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> export</span><span style="color:#98c379"> JRE_HOME=</span><span style="color:#e06c75">$JAVA_HOME</span><span style="color:#98c379">/jre</span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> export</span><span style="color:#98c379"> CLASSPATH=.:</span><span style="color:#e06c75">$JAVA_HOME</span><span style="color:#98c379">/lib:</span><span style="color:#e06c75">$JRE_HOME</span><span style="color:#98c379">/lib</span> <span style="color:#61afef">ENV</span><span style="color:#98c379"> PATH=</span><span style="color:#e06c75">$JAVA_HOME</span><span style="color:#98c379">/bin:</span><span style="color:#e06c75">$PATH</span> <span style="color:#7f848e"><em>#开放一个3000端口</em></span> <span style="color:#61afef">EXPOSE</span><span style="color:#d19a66"> 3000</span> <span style="color:#7f848e"><em>#移动并解压Grafana.tar安装包</em></span> <span style="color:#61afef">ADD</span><span style="color:#98c379"> /root/Grafana.tar</span><span style="color:#98c379"> /home/</span> <span style="color:#7f848e"><em>#复制当前目录下的所有到/data/cs/里</em></span> <span style="color:#61afef">COPY</span><span style="color:#98c379"> ./</span><span style="color:#98c379"> /data/home/</span> <span style="color:#7f848e"><em>#设置python3.6.8环境</em></span> <span style="color:#61afef">RUN</span><span style="color:#98c379"> cd</span><span style="color:#98c379"> /data/Python-3.6.8/</span><span style="color:#abb2bf"> && </span><span style="color:#61afef">./configure</span><span style="color:#d19a66"> --prefix=/root/python36</span><span style="color:#abb2bf"> && </span><span style="color:#61afef">make</span><span style="color:#abb2bf"> && </span><span style="color:#61afef">make</span><span style="color:#98c379"> install</span><span style="color:#abb2bf"> && </span><span style="color:#61afef">ln</span><span style="color:#d19a66"> -s</span><span style="color:#98c379"> /root/python36/bin/python3.6</span><span style="color:#98c379"> /usr/bin/python3</span><span style="color:#abb2bf"> && </span><span style="color:#61afef">ln</span><span style="color:#d19a66"> -s</span><span style="color:#98c379"> /root/python36/bin/pip3</span><span style="color:#98c379"> /usr/bin/pip3</span> <span style="color:#7f848e"><em>#切换到/data/目录</em></span> <span style="color:#61afef">WORKDIR</span><span style="color:#98c379"> /data/</span> <span style="color:#7f848e"><em>#最后执行删除Dockerfile</em></span> <span style="color:#61afef">CMD</span><span style="color:#98c379"> rm</span><span style="color:#d19a66"> -rf</span><span style="color:#98c379"> Dockerfile</span></code></span></span>2、构建镜像
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#61afef">docker</span><span style="color:#98c379"> build</span><span style="color:#d19a66"> -t</span><span style="color:#98c379"> dockerfile:v1</span><span style="color:#98c379"> .</span></code></span></span>等待构建完成。
3、查看镜像
<span style="background-color:#282c34"><span style="color:#abb2bf"><code class="language-bash"><span style="color:#abb2bf">[root@cs ~]# docker images</span> <span style="color:#61afef">REPOSITORY</span><span style="color:#98c379"> TAG</span><span style="color:#98c379"> IMAGE</span><span style="color:#98c379"> ID</span><span style="color:#98c379"> CREATED</span><span style="color:#98c379"> SIZE</span> <span style="color:#61afef">dockerfile</span><span style="color:#98c379"> v1</span><span style="color:#98c379"> 15c89s63e742</span><span style="color:#d19a66"> 2</span><span style="color:#98c379"> months</span><span style="color:#98c379"> ago</span><span style="color:#98c379"> 8.5GB</span></code></span></span>