2019-05-07 Dockerfile 详解

栏目: 编程工具 · 发布时间: 5年前

内容简介:本文仅为个人学习记录. 教程来源FROM 有一个比较特殊的镜像(空镜像)一般 golang 程序会直接使用FROM scratch.

本文仅为个人学习记录. 教程来源 Docker--从入门到实践

FROM 指定基础镜像

FROM nginx

FROM 有一个比较特殊的镜像(空镜像)

FROM scratch

一般 golang 程序会直接使用FROM scratch.

RUN 执行命令

run指令有两种格式

  • shell格式
RUN echo 'hello docker'
  • exec格式
RUN apt-get update
RUN apt-get install -y gcc

注意:Dockerfile每一个指令都会构建一层,不得超过127层

所以很多时候我们会使用 && 来减少构建的层数

例如上例可改写为

RUN apt-get update && apt-get install -y gcc

Dockerfile nginx 实例

FROM nginx
RUN echo '<h1>Hello,Docker!!</h1>' > /usr/share/nginx/html/index.html

构建命令

docker build -t nginx:v3 .

运行命令

docker run --name webserver -d -p 80:80 nginx:v3

COPY 复制文件

COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。

COPY [--chown=<user>:<group>]<源路径> ... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

例子:

COPY package.json /usr/src/app/

这里源路径可以使用通配符,其通配符规则要满足 go 的 filepath.Match规则

例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

ADD 更高级的复制文件 (虽然很高级但不建议使用)

ADD [--chown=<user>:<group>]<源路径> ... <目标路径>
ADD [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能

比如 <源路径> 可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600,如果这并不是想要的权限,那么还需要增加额外的一层 RUN 进行权限调整,另外,如果下载的是个压缩包,需要解压缩,也一样还需要额外的一层 RUN 指令进行解压缩。所以不如直接使用 RUN 指令,然后使用 wget 或者 curl 工具下载,处理权限、解压缩、然后清理无用文件更合理。因此,这个功能其实并不实用,而且不推荐使用

注意 ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。 因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则, 所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。

CMD 容器启动命令

Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。 CMD 指令就是用于指定默认的容器主进程的启动命令的

CMD指令的格式和 RUN 相似,也是两种格式:

#shell格式
CMD <命令>
#exec格式
CMD ["可执行文件","参数1","参数2"...]

在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 ",而不要使用单引号。

如果使用 shell 格式的话, 实际的命令会被包装为 sh -c 的参数的形式进行执行.

CMD echo $HOME

在实际执行中, 会将其变更为:

CMD [ "sh", "-c", "echo $HOME" ]

这就是为什么我们可以使用环境变量的原因, 因为这些环境变量会被shell 进行解析处理, 提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题. 这是初学者常出现的一个混淆.

Docker不是虚拟机, 容器中的应用都应该以前台执行,而不是像虚拟机/物理机那样,用upstart/systemd去启动后台服务, 容器内没有后台服务的概念

一些初学者将 CMD 写为

CMD service nginx start

然后发现容器执行后就立即退出了,甚至在容器内去使用systemctl 命令,结果发现根本执行不了.这就是因为没搞明白前台,后台的概念, 没有区分容器和虚拟机的差异,依旧用传统虚拟机的角度去理解容器

对于容器而言, 其启动程序就是容器应用进程, 容器就是为了主进程而存在的, 主进程退出 , 容器就失去了存在的意义,从而退出, 其他辅助进程不是他需要关心的东西

而使用 service nginx start命令 则是希望upstart来以"后台守护进程"的形式启动nginx服务, 但刚才说了 CMD service nginx start 会被理解为 CMD [ "sh", "-c", "echo $HOME" ] ,因此主进程实际上是 sh .那么当service nginx start命令结束后 , sh 也就结束了, sh 作为主进程退出了, 自然就会让容器也跟着退出

正确的做法是 直接执行nginx可执行文件, 并且要求以前台的形式运行.

比如:

CMD ["nginx", "-g", "deamon off"]

个人理解:

推荐使用 exec 格式的用意是为了避免类似 sh -c 的命令干扰

ENTRYPOINT (入口点)

ENTRYPOINT 的格式和 RUN 指令格式一样, 分为 execshell
ENTRYPOINT 的目的和 CMD 一样都是在指定容器启动程序及参数. ENTRYPOINT 在运行是也可以替代,不过比 CMD 略显繁琐, 需要通过 docker run 的参数 --entrypoint 来指定

当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变, 不再是直接的运行其命令, 而是将 CMD 的内容当作参数传给 ENTRYPOINT 指令.可以理解为:

<ENTRYPOINT> "<CMD>"

场景一: 让镜像变成像命令一样使用

假设我们需要一个得知自己当前公网 IP 的镜像,那么可以先用 CMD 来实现:

FROM ubuntu:18.04
RUN apt-get update \
    &&apt-get install -y curl \
    &&rm -rf /var/lib/apt/lists/*
CMD ["curl", "-s" ,"https://ip.cn"]

假如我们使用 docker build -t myip . 来构建镜像的话, 如果我们需要查询当前公网IP, 只需要执行

docker run myip

这里遇到一个问题, 如果我们想用 curl -i 的话就会出现问题

所以这里就引申出了 ENTRYPOINT 的用法

FROM ubuntu:18.04
RUN apt-get update \
    &&apt-get install -y curl \
    &&rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["curl","-s","https://ip.cn"]

ENV 设置环境变量

格式有两种

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2> ...

这个指令很简单,就是设置环境变量而已,无论是后面的其它指令,如 RUN ,还是运行时的应用,都可以直接使用这里定义的环境变量。

.


以上所述就是小编给大家介绍的《2019-05-07 Dockerfile 详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数字化商业模式

数字化商业模式

大前研一 / 王小燕 / 中信出版社 / 2006-4 / 32.00元

《数字化商业模式》为商学院课程的第三部精华集锦,来自金融界、餐饮业、公共设施等领域的领军人物亲自讲述他们的成功案例,以及他们在思考技能、人才管理、事业构想、战略技能等方面的管理理念和战略。任何成功的企业家,不是人云亦云而是能够独立思考的人,不是依赖于他人而是执著、自立的人,不只是沿袭旧思路而是具备创新力、执行力的人。一起来看看 《数字化商业模式》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具