一、基础概念

1、基本概念

Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了 Dockerfile,当我们需要定制额外的

需求时,只需在 Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。

2、文件格式

Dockerfile由一行行命令语句组成,并且支持用“#”开头作为注释,一般的Dockerfile分为四部分:基础镜像信息维护者信息镜像操作指令容器启动时执行的指令

二、基础命令

1、FROM

指定base镜像。

# 制作基准镜像
FROM 镜像
# 比如我们要发布一个应用到tomcat里,那么的第一步就是FROM tomcat
FROM tomcat<:tags>

第一条指令必须为FROM指令,并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)

2、LABEL&MAINTAINER

指定维护者的信息。

# MAINTAINER,一般写个人id或组织id
# LABEL 就是注释,方便阅读的,纯注释说明。不会对Dockerfile造成任何影响
# 比如:
MAINTAINER zhangsan
LABEL version = "1.0.0"
LABEL description = "我们是大百度!"
# ...等等描述性信息,纯注释。

3、WORKDIR

类似于Linux中的cd命令,但是他比cd高级的地方在于,我先cd,发现没有这个目录,我就自动创建出来,然后在cd进去,为后续的RUN 、 CMD 、 ENTRYPOINT

指令配置工作目录。

WORKDIR /usr/local/testdir

4、COPY

将文件从 本地 复制到镜像。

# 示例
# 将1.txt拷贝到根目录下。它不仅仅能拷贝单个文件,还支持Go语言风格的通配符,比如如下:
COPY 1.txt /
# 拷贝所有 abc 开头的文件到testdir目录下
COPY abc* /testdir/
# ? 是单个字符的占位符,比如匹配文件 abc1.log
COPY abc?.log /testdir/

5、ADD

将文件从 本地 复制到镜像。可以是Dockerfile所在的目录的一个相对路径;可以是URL,也可以是tar.gz(自动解压)

# 示例
# 将1.txt拷贝到根目录的abc目录下。若/abc不存在,则会自动创建
ADD 1.txt /abc
# 将test.tar.gz解压缩然后将解压缩的内容拷贝到/home/work/test
ADD test.tar.gz /home/work/test

docker官方建议当要从远程复制文件时,尽量用curl/wget命令来代替ADD。因为用ADD的时候会创建更多的镜像层。镜像层的size也大。

6、COPY与ADD比较

1)COPY能干的事ADD都能干,甚至还有附加功能。

2) ADD可以支持拷贝的时候顺带解压缩文件,以及添加远程文件(不在本宿主机上的文件)类似wget。

3) 只是文件拷贝的话可以用COPY,有额外操作只能用ADD代替。

7、ENV

设置环境变量,环境变量可被后面的指令使用。例如:

# 设置环境常量,方便下文引用,比如:
ENV JAVA_HOME /usr/local/jdk1.8
# 引用上面的常量,下面的RUN指令可以先不管啥意思,目的是想说明下文可以通过${xxx}的方式引用
RUN ${JAVA_HOME}/bin/java -jar xxx.jar

8、VOLUME

创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。后面单独文章讲解。

 VOLUME ["/data"]

三、运行指令

一共有三个:RUN、CMD、ENTRYPOINT

1、RUN

构建镜像时执行的命令。

1.1 执行时机

RUN指令是在构建镜像时运行,在构建时能修改镜像内部的文件。每条指令将在当前镜像基础上执行,并提交为新的镜像。

1.2 命令格式

: 命令格式不光是RUN独有,而是下面的CMD和ENTRYPOINT都通用。

SHELL命令格式

RUN yum -y install vim

EXEC命令格式

RUN ["yum","-y","install","vim"]

二者对比

SHELL:当前shell是父进程,生成一个子shell进程去执行脚本,脚本执行完后退出子shell进程,回到当前父shell进程。

EXEC:用EXEC进程替换当前进程,并且保持PID不变,执行完毕后直接退出,不会退回原来的进程。

总结:也就是说shell会创建子进程执行,EXEC不会创建子进程。

1.3 举例

举个最简单的例子,构建镜像时输出一句话,那么在Dockerfile里写如下即可:

RUN ["echo", "image is building!!!"]

再比如我们要下载vim,那么在Dockerfile里写如下即可:

RUN ["yum","-y","install","vim"]

下面会有实战来完完整整的演示。

2、CMD

2.1 执行时机

容器启动时执行,而不是镜像构建时执行。

2.2 解释说明

容器启动时运行指定的命令。

Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。重点在于如果容器启动的时候有其他额外的附加指令,则CMD指令不生效

2.3 举例

CMD ["echo", "container starting..."]

3、ENTRYPOINT

3.1 执行时机

容器创建时执行,而不是镜像构建时执行。

3.2 解释说明

在容器启动的时候执行此命令,且Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。

3.3 举例

ENTRYPOINT ["ps","-ef"]

4、RUN vs CMD vs ENTRYPOINT

简单的说:

1、RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。
2、CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。
3、ENTRYPOINT 配置容器启动时运行的命令。

RUN

RUN是在构建层面的,就是每执行一个RUN,就代表多一层。所以我们经常会用于安装软件包,好比 RUN yum -y install vim。执行这个命令就是让当前镜像可以支持vim指令。

CMD

CMD 指令允许用户指定容器的默认执行的命令。此命令会在容器启动且 docker run 没有指定其他命令时运行。如果 docker run 指定了其他命令,CMD 命令将被忽略。

如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。

ENTRYPOINT

ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行。ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT

不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。

5、RUN VS CMD案例

上面虽然用文字阐述了它们之间的区别,但是估计还是会有点不太明白,所以这里通过一个小小案例来理解。

创建Dockerfile,并添加如下内容

FROM centos
RUN ["echo", "image building!!!"]
CMD ["echo", "container starting..."]

构建镜像

docker build -t runvscmd-test .

可以看出构建镜像的过程中发现RUN的image building!!! 输出了,所以RUN命令是在镜像构建时执行。而并没有container starting…的输出。

启动容器

docker run runvscmd-test

启动容器的时候 container starting...,足以发现CMD命令是在容器启动的时候执行。

总结: 这就是上面所说的 run是 构建镜像 时候的指令,CMD和ENTRYPOINT是启动容器时的指令。

接下来在举个例子来理解区分CMD和ENTRYPOINT。

6、CMD VS ENTRYPOINT案例

ENTRYPOINT和CMD可以共用,若共用则他会一起合并执行。如下Demo:

FROM centos
RUN ["echo", "image building!!!"]
ENTRYPOINT ["ps"]
CMD ["-ef"]

构建启动容器

# 构建镜像
docker build -t docker-test .
# 启动容器
docker run docker-test

输出结果

UID        PID  PPID  C STIME TTY          TIME CMD
root 1 0 0 13:02 ? 00:00:00 ps -ef

他给我们合并执行了:ps -ef,这么做的好处在于如果容器启动的时候添加额外指令,CMD会失效,可以理解成我们可以动态的改变CMD内容而不需要重新构建镜像等操作。比如

docker run docker-test -aux

输出结果:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root 1 2.0 0.0 46340 1692 ? Rs 13:02 0:00 ps -aux

结果直接变成了 ps -aux,CMD命令不执行了。

总结:从这个示例中就可以看出区别,ENTRYPOINT无论容器启动是否带参数,都会执行。而CMD就不一样。上面没带参数那么它就会被执行。而下面带了 -aux,

CMD指令就不会执行了。

四、项目实战

这里就是以当前自己的vue项目来演示,正常不用docker,那么就是先打包项目,npm run bulid,再启动项目 npm run start。

但是因为vue项目依赖Node,就好像我们java项目依赖JDk一样。所以不同环境版本一直很重要,所以这里通过镜像来启动项目。

1、DockerFile文件

在vue项目当前目录创建DockerFile文件,并写入以下脚本。

#获取基础镜像
FROM node:12.17
#指定作者
MAINTAINER xiaoxiao
#指定工作目录
WORKDIR /app
#将当前根目录的vue项目所有文件,都移动到/app目录下
#COPY package*.json ./
COPY . .
##安装项目相关依赖
RUN npm install
#将当前根目录的vue项目所有文件,都移动到/app目录下
#打包项目
RUN npm run build
#暴露端口
EXPOSE 8000
#启动项目
ENTRYPOINT ["npm","run","start"]

2、构建镜像

命令

# docker build代表构建镜像 -t后面指定生成镜像名称 .代表在当前目录构建
docker build -t xiaoxiao-web .

构建镜像命令执行完后,我们可以看下该镜像有没有创建成功

可以看出镜像已经构建成功,不过镜像有点大。

3、启动容器

# docker run表示启动容器 -d 在后台运行 --name 容器的名称 -p端口映射 xiaoxiao-web就是指定哪个镜像
docker run -d --name=xiaoxiao-run-web -p 7000:8000 xiaoxiao-web

说明容器已经启动成功。

4、进入容器

#09ff5738660e 为容器ID
docker exec -it 09ff5738660e /bin/bash

从这里可以看出2点 1:我一进来就是根目录就是/app 这就是上面我们自己设置的工作目录。2:前端项目文件已经都拷贝到当前根目录下。

5、访问项目

成功

参考

1、《每天5分钟玩转 Docker 容器技术》书籍

2、面试官:你说你精通 Docker,那你来详细说说 Dockerfile 吧

3、DockerFile 详解

【Docker】(10)---详细说说 Dockerfile文件的更多相关文章

  1. ASP.NET CORE做的网站运行在docker上(不用dockerfile文件部署)

    按网上的做法用dockerfile文件是可以弄得出来的,http://www.docker.org.cn/article/119.html, 不过我想把网站文件放在外面硬盘目录,再映射进去,这样只要在 ...

  2. 『现学现忘』Docker基础 — 34、DockerFile文件详解

    目录 1.DockerFile文件说明 2.Dockerfile构建过程解析 (1)Docker容器构建三步骤 (2)Dockerfile文件的基本结构 (3)Dockerfile注意事项 (4)Do ...

  3. 面试官:你说你精通 Docker,那你来详细说说 Dockerfile 吧

    接上一篇:30分钟快速上手Docker,看这篇就对了! 一. 带着问题学Dockerfile 1.疑问 我们都知道从远程仓库可以pull一个tomcat等镜像下来,然后docker run启动容器,然 ...

  4. Docker学习(六)——Dockerfile文件详解

    Docker学习(六)--Dockerfile文件详解 一.环境介绍 1.Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下,可以为Dockerfile父目录的子目录 ...

  5. 【Docker】(6)---Dockerfile文件

    springboot项目打包镜像中的Dockerfile文件 在讲Dockerfile文件之前应该先讲下maven的一个插件叫:dockerfile-maven-plugin.他们是组合一起用的 一. ...

  6. Docker(十)-Docker创建DockerFile文件

    制作Docker image 有两种方式: 使用 Docker container,直接构建容器,再导出成 image 使用. 是使用 Dockerfile,将所有动作写在文件中,再 build 成 ...

  7. Docker定制容器镜像(利用Dockerfile文件)

    1.创建Dockerfile文件 新建一个目录,在里面新建一个dockerfile文件(新建一个的目录,主要是为了和以防和其它dockerfile混乱 ) [root@docker01 myfiles ...

  8. docker Dockerfile文件的编写部分命令

    镜像的构建过程:编写dockerfile文件,执行docker build 进行构建镜像,最后docker run 运行容器镜像实例. docker build -t mycentos:1.01 . ...

  9. Docker学习笔记-Dockerfile文件详解

    什么是Dockerfile? Docker中有个非常重要的概念叫做--镜像(Image).Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运 ...

随机推荐

  1. lsyncd替代inotify+rsync实现实时同步

    因公司业务需要需要实时同步日志文件,刚一开始使用的是inotify+rsync来实现实时同步,但时间久而久之发现同步的速度越来越慢,往往延迟好几个小时.查了一下网上的inotify+rsync方案基本 ...

  2. golang net/http包

    http协议 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为 ...

  3. uniapp H5 打包并部署到 nginx

    个人也是了百度了挺久的了,花费的时间( 俩个半小时 ) uniapp 的打包首先要先配置,配置好了才能去进行打包,如图所示. 这只是第一步. 注意: 1.运行基础路径最好用 ./ ,如果配置了其他请自 ...

  4. [考试总结]noip模拟40

    最近真的是爆炸啊... 到现在还是有不少没改出来.... 所以先写一下 \(T1\) 的题解.... 送花 我们移动右端点,之后我们用线段树维护全局最大值. 之后还要记录上次的位置和上上次的位置. 之 ...

  5. Python - 面向对象编程 - __del__() 析构方法

    del 语句 Python 提供了 del 语句用于删除不再使用的变量 语法 del 表达式 删除变量的栗子 var = "hello" del var print(var) # ...

  6. ABP 极简入门教程(三 权限)

    此处演示为MVC项目,同样权限定义需要到Application中才能在获取API时进行权限验证 一.打开Sample.Core\Authorization\PermissionNames.cs增加授权 ...

  7. jdbcTemplate快速入门

    一. c3p0和dbcp区别 二.导包 hibernate通过映射自动创建表: 三.代码实现

  8. JNDI注入基础

    JNDI注入基础 一.简介 JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务 ...

  9. Java学习笔记--注解和反射

    注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...

  10. 解决umount: /home: device is busy

    取消挂载/home时出现umount: /home: device is busy,        原因是因为有程序在使用/home目录,我们可以使用fuser查看那些程序的进程,        然后 ...