docker学习笔记(3):Dockerfile详解

  • 引言
  • Dockerfile介绍
  • dockerfile书写规范
  • dockerfile使用实例

引言

Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,而 Docker 容器则可以认为是软件的运行态。从应用软件的角度来看,Dockerfile、Docker 镜像与 Docker 容器分别代表软件的三个不同阶段,Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当 Docker 体系的基石。

Dockerfile介绍

通过下图可以看出使用 Dockerfile 定义镜像,运行镜像启动容器:
docker学习笔记(3):Dockerfile详解_第1张图片

Docker 镜像是由 Dockerfile 构建而成,Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制自己额外的需求时,只需在 Dockerfile 上添加或者修改指令,重新生成 image 即可,省去了敲命令的麻烦。最简单的形式是由FROM、ADD、VOLUME、CMD四个部分组成,我们可以写一个最简单的Dockerfile文件:

FROM ubuntu:14.04  
ADD run.sh /  
VOLUME /data  
CMD ["./run.sh"] 

FROM ubuntu:16.04:设置基础镜像,此时会使用基础镜像ubuntu:16.04的所有镜像层,为简单起见,图中将其作为一个整体展示
ADD run.sh /:将 Dockerfile 所在目录的文件run.sh加至镜像的根目录,此时新一层的镜像只有一项内容,即根目录下的run.sh
VOLUME /data:设定镜像的 VOLUME,此 VOLUME 在容器内部的路径为/data。需要注意的是,此时并未在新一层的镜像中添加任何文件,但更新了镜像的 json 文件,以便通过此镜像启动容器时获取这方面的信息。
CMD ["./run.sh"]:设置镜像的默认执行入口,此命令同样不会在新建镜像中添加任何文件,仅仅在上一层镜像 json 文件的基础上更新新建镜像的 json 文件。

然后之后还有别的命令,我们本篇主要构建的是将我们自己的Python代码能够在docker本地上运行成功,并保存成镜像,推送到dockerhub上。


dockerfile书写规范

dockerfile除了上面最基础但又是比较重要的语法构成外,还有一些其它的命令同样能帮助我们完善docker镜像,下面参考Docker(三):Dockerfile 命令详解 对上述命令进行一个整体的概括与整理:

命令 说明 详解
from 指定基础镜像 必须为第一条非注释指令,多个from可以创建多个镜像,但from前需提交上次镜像ID
run 执行特定命令 位置没有限制,层级构建docker的命令
copy 复制文件 copy指令将从构建上下文目录中的文件复制到镜像内的目标路径
add 高级复制命令 和copy有一样的功能,多了源路径可以是url的情况
env 设置环境变量 设置环境变量,一般最好放前面
expose 设置监听端口 若需要,在 docker run 时使用-P 参数来发布容器端口到 host 的某个端口上。
volume 定义匿名卷 详情见下面的详细说明
workdir 指定工作路径 通过设置工作路径,Dockerfile的其它命令都会在指定目录下执行
cmd 容器启动命令 与run指令的区别在于,run会产生新的镜像,cmd在构建时不进行任何操作
onbuild 设置镜像触发器 当所构建的镜像被用作其它镜像时将会被触发

上表中我们详细说明一下volume命令,因为再后面的docker-compose.xml中它也有着无法替代的作用,它的基本功能是创建挂载点,即向基于所构建镜像创始的容器添加卷,而一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

  • 卷可以容器间共享和重用
  • 容器并不一定要和其它容器共享卷
  • 修改卷后会立即生效
  • 对卷的修改不会对镜像产生影响
  • 卷会一直存在,直到没有任何容器在使用它

VOLUME 让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容。

dockerfile使用实例

下面我将通过我自己项目的例子来进行相关说明,首先我们要在我们项目的根目录下创建一个Dockerfile不带任何后缀的文件,然后在文件内部写下我们想要构建的镜像的配置信息,比如我这里的是:

FROM python:3.6

RUN mkdir -p /usr/lzj/Pro/ChatterBotmaster

WORKDIR /usr/lzj/Pro/ChatterBotmaster

# COPY pip.conf /root/pip/pip.conf
COPY requirements.txt /usr/lzj/Pro/ChatterBotmaster/

RUN pip install -r /usr/lzj/Pro/ChatterBotmaster/requirements.txt
RUN rm -rf /usr/lzj/Pro/ChatterBotmaster

COPY . /usr/lzj/Pro/ChatterBotmaster
CMD ["python","answermain.py"]

写得比较简单,虽然中途尝试过一些其它的方式,比如说直接再Ubuntu下进行制作镜像与启动,但那样步骤太多了,我发现有15步,影响速度又占用极大的空间,另外就是中途的时候有很多报错,所以我还是采用常规写法,然后上述的dockerfile指令中,第四条copy指令我不知道为什么一直提示我不存在该文件,我在其他路径将文件复制过去还是一样的错误,所以干脆我就注释掉了,中间的步骤我忘了截图,关于requirements文件,可以看我之前的一篇例子: 利用pip和pipreqs导出当前python环境下所依赖的包总结 ,我推荐是用pipreqs模块。

然后中间过程忘截图了,因为我构建镜像的那几天,网速很慢,中午吃饭的时候挂着,等到下午接近下班的时候看了下才成功,中间可能会有一些小错误,但对整体并不影响使用,步骤由之前15步缩短为8步,大致为:

Sending build context to Docker daemon  65.57MB
Step 1/8 : FROM python:3.6
 ---> 48c06762acf0
Step 2/8 : RUN mkdir -p /usr/lzj/Pro/ChatterBotmaster
 ---> Using cache
 ---> 010f2065bc65
Step 3/8 : WORKDIR /usr/lzj/Pro/ChatterBotmaster
 ---> Using cache
 ---> b5b9b0094d7d
Step 4/8 : COPY requirements.txt /usr/lzj/Pro/ChatterBotmaster/
 ---> Using cache
 ---> 0a8bb8854704
Step 5/8 : RUN pip install -r /usr/lzj/Pro/ChatterBotmaster/requirements.txt
 ---> Using cache
 ---> bb501a77da43
Step 6/8 : RUN rm -rf /usr/lzj/Pro/ChatterBotmaster
 ---> Using cache
 ---> 06e858f3575d
Step 7/8 : COPY . /usr/lzj/Pro/ChatterBotmaster
 ---> Using cache
 ---> b80ca79fe874
Step 8/8 : CMD ["python","answermain.py"]
 ---> Using cache
 ---> 406493b7842a
Successfully built 406493b7842a
Successfully tagged my-python-app:v1.0

构建成功后,我们就可以使用docker run命令进行启动:
docker学习笔记(3):Dockerfile详解_第2张图片
然后如果当前linux服务器的端口是开放的,我们就可以在Windows上输入该Linux的ip地址加8080端口进行访问。那么到这里,一个简单的images就制作完成了,可以看我上一篇的镜像说明,提交到dockerhub中,以后需要的话,能直接pull拉取。



参考与推荐:
[1]. Docker(三):Dockerfile 命令详解

[2]. Docker搭建Django+Mariadb环境

[3]. Dockerfile参考

[4]. docker容器极简教程

你可能感兴趣的:(Linux)