即刻构建,Dockerfile入坑指北

在上一篇文章中,有幸和各位分享了一点人生的经验,正如我在文章末所说,这些都只是沧海一粟,学会 docker 的基本概念和操作还不足以让你快速部署代码,今天我们就来聊一聊 Dockerfile

image

在了解什么是 Dockerfile之前,我们先来做一个小实验

还记得我们在上一节中 pull 下来的 python 镜像吗,首先通过 docker run -it 进入容器内部,回忆一下, -it 这个参数的作用是什么,没错,使用这个参数,docker会为容器分配一个伪输入终端,通过这个终端,用户就可以和容器进行相应的交互了。

进入容器后,先列出当前路径下的所有文件

[root@FUCC ~]# docker run -it python:3.7 /bin/bash
root@692f87774bf7:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@692f87774bf7:/# 

OK,接着,我们将创建一个hello.py 的文件,创建完成后再次列出所有文件

root@692f87774bf7:/# touch hello.py
root@692f87774bf7:/# ls
bin  boot  dev  etc  hello.py  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

可以看到,hello.py 已经创建完成了,这时我们退出容器,使用之前的 docker run -it python:3.7 /bin/bash 命令再次进入容器的交互模式,并列出所有文件

root@692f87774bf7:/# exit
exit
[root@FUCC ~]# docker run -it python:3.7 /bin/bash
root@65c767655e8a:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@65c767655e8a:/#

不用我多说,相信你已经发现了问题的所在,奇怪,为什么我们之前创建的文件凭空消失了呢?

这是因为,在容器内部执行的操作并不会修改镜像,容器其实只是在镜像上面添加了一个可写层,就像字帖里的临摹纸一样,无论你在临摹纸上怎么写,对下面一层都不会有任何影响,这个特性其实和VM的快照有些类似。

但是问题来了,既然在容器内部的操作都不会修改镜像,那如何做到快速部署,每次部署代码前都去重复执行一些操作,岂不是太low了?

假设你是一家社交网站的技术负责人,某一天,奥特虾突然宣布恋情上了热搜,哦不是,八对明星突然同时出轨,你需要在短时间内创建上百台云服务器以支撑吃瓜群众海量的请求,团队选用了 Docker 去部署应用,如果通过上面这种方法去部署,吃瓜群众想杀了你的心都有了,为什么?等你的服务恢复,吃瓜群众早就散了,动不动就崩,怎么愉快吃瓜?

这时,就轮到 Dockerfile 闪亮登场了,老规矩,先看一下 Docker 官方对于 Dockerfile 的介绍

Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession

简单来说,Dockerfile是一个文本文档,其中包含用户可以在命令行上调用以构建镜像的所有命令,举个例子,你可以理解为构建镜像是一个搭积木的过程,Dockerfile 就像是说明书一样,Docker 会根据这份说明书去构建你想生成的镜像。

接下来我们会从一个实际的场景出发,讲一讲如何构建 Dockerfile

依旧是以一个 python 镜像为例,在我的本地(容器外部),有一个 Optimal_Hotel_Matching.py 的代码文件,这是一个爬虫程序,先尝试在容器中运行它
果不其然,出现了报错,这是因为在python镜像中,并没有安装requests这个第三方的http库,这其实就是一个典型的安装依赖环境的过程,我们试着用 Dockerfile 去解决这个问题

[root@FUCC dockerfileTest]# ls
Optimal_Hotel_Matching.py
[root@FUCC dockerfileTest]# docker run  -v $PWD:/usr/src/code  -w /usr/src/code python:3.7 python Optimal_Hotel_Matching.py
Traceback (most recent call last):
  File "Optimal_Hotel_Matching.py", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'
[root@FUCC dockerfileTest]#

在编写第一个 Dockerfile 之前,我们先来熟悉一下 Dockerfile 中几个常用的指令

FROM

语法: FROM <image>
说明:这是 Dockerfile 中的第一条指令,它用于指定一个构建镜像的基础源镜像,如果本地没有的话, Docker 会从仓库中自动拉取

MAINTAINER

语法:MAINTAINER <name> <email>
说明:用于描述镜像创建者的名称和邮箱

RUN

语法: RUN <command> <param1> <param2>
说明:RUN 绝对是 Dockerfile 中最重要的命令之一了,当RUN执行完成后,会在原先的基础镜像上创建一个新的镜像层,每执行一次RUN就会产生一个新的层。通常,安装软件或者配置环境都是通过RUN来实现的

CMD

语法: CMD <command> <param1> <param2>
说明:CMD相对而言比较简单,相信大家看到名字就能理解,这个指令用于指定容器启动时执行的命令

Tips: 在我刚接触Docker的时候,RUN 和 CMD 一度傻傻分不清楚,其实这两者的作用完全不同,RUN 用于构建镜像,是对镜像进行操作,而 RUN 则是指定了容器启动时执行的命令,是对容器进行操作

COPY

语法:COPY <src> <dest>
说明:COPY 用于复制本地文件,并将其放置在指定的容器目录,但是需要注意的是 COPY 并不能将复制的压缩文件自动解压,也不能复制网络文件,如果有这两点需求可以使用 ADD 命令,这两个命令的用法是相同的, ADD 可以将复制的压缩文件自动解压

WORKDIR

语法: WORKDIR <path>
说明:为RUN、CMD、ENTRYPOINT指令配置工作目录,在一个 Dockerfile 中可以使用多个WORKDIR指令

编写第一个Dockerfile

掌握了以上指令后,我们就已经能写一个较为基础的 Dockerfile 了,回到我们之前的需求,一句话总结下来就是,安装requests库后运行代码文件

思考一下,应该怎么做?

如果你还是没有眉目,不妨来看看我为你准备的参考答案

FROM python:3.7                                 #指定基础镜像为python:3.7
MAINTAINER ultraxia "ultraxia@foxmail.com"      #维护者名称和邮箱
RUN pip install requests                  #安装requests库,并构建一个新的镜像层
WORKDIR /dockerfileTest               #指定工作目录为/dockerfileTest
COPY . .                     #将当前目录下的文件复制到容器中,这里为工作目录 
CMD [ "python", "Optimal_Hotel_Matching.py" ]    #运行代码

将上面的内容保存为名称为Dockerfile的文件,并放置在项目所在的目录

[root@FUCC dockerfileTest]# ls
Dockerfile  Optimal_Hotel_Matching.py

开始构建

这时,我们就可以使用docker build去构建了,通常为了区分不同的镜像,需要给镜像打上tag(标签)

[root@FUCC dockerfileTest]# docker build --tag python:requests .
Sending build context to Docker daemon  5.12 kB
Step 1/6 : FROM python:3.7
 ---> 42d620af35be
Step 2/6 : MAINTAINER ultraxia "ultraxia@foxmail.com"
 ---> Running in b9ca2049ef19
 ---> c6fb2a731a82
Removing intermediate container b9ca2049ef19
Step 3/6 : RUN pip install requests
 ---> Running in 4edba5ca3ead

Collecting requests
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests)
  Downloading https://files.pythonhosted.org/packages/e6/60/247f23a7121ae632d62811ba7f273d0e58972d75e58a94d329d51550a47d/urllib3-1.25.3-py2.py3-none-any.whl (150kB)

解释一下这条命令
docker build 命令用于使用 Dockerfile 创建镜像
--tag 参数用于指定镜像tag,这里我们命名为python:requests
. docker 会从当前目录寻找Dockerfile文件,并开始构建镜像

构建完成!使用 docker images命令验证一下吧

[root@FUCC dockerfileTest]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
python                  requests            04f20acdc288        2 hours ago         926 MB
docker.io/python        3.7                 42d620af35be        3 weeks ago         918 MB
docker.io/rabbitmq      3-management        7aae48fa6ef6        3 weeks ago         179 MB
docker.io/golang        latest              f50db16df5da        4 weeks ago         774 MB
docker.io/mariadb       latest              3a2ef06682ac        4 weeks ago         356 MB
docker.io/centos        latest              9f38484d220f        4 months ago        202 MB
docker.io/hello-world   latest              fce289e99eb9        7 months ago        1.84 kB
docker.io/django        latest              eb40dcf64078        2 years ago         436 MB
[root@FUCC dockerfileTest]#

可以看到,此时本地的仓库中已经生成了一个tag为requests的python镜像。试着运行一下这个镜像,看看是否还会出现No module named 'requests'的报错,以及,程序是否会如我们期待的一样开始运行。

[root@FUCC dockerfileTest]# docker run python:requests
Computing distance between 116.368816,39.866464  and  116.438946,39.921624
Computing distance between 116.370910,39.869603  and  116.438946,39.921624
Computing distance between 116.409583,39.983356  and  116.438946,39.921624
Computing distance between 116.302621,39.966272  and  116.438946,39.921624
Computing distance between 116.322551,39.886995  and  116.438946,39.921624

可以看到,运行成功,容器中的代码运行完成后,容器退出。

完结了吗?

在这一篇里,我通过一个简单的案例和各位分享了 Dockerfile 的简单应用,事实上在企业的实际生产中,Dockerfile 的内容会比这个更复杂一些。

最后,正好赶上七夕,祝各位七夕快乐,下期再见。

今天过节的人会有时间看你的文章吗?不会

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容