Dockerfile简介

1.什么是dockerfile?

Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。

docker build命令用于从Dockerfile构建映像。

2. Dockerfile的基本结构

Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,#为 Dockerfile 中的注释。

dockerfile的指令:

  FROM:指定基础镜像(FROM是必备的指令,并且必须为第一条指令)。

  RUN: 用来执行命令行命令。其基本格式:

      shell格式: RUN  <命令>  ,输入在bash环境中的命令即可,一个dockerfile允许使用RUN不得超过127层,所以,使用一次RUN, 使用 ‘ \ ’ 换行,使用‘ && ’执行下一条命令。一般使用此种格式;

      exec格式: RUN  <"可执行文件", "参数1", "参数2">,此种方式像是函数调用中的格式;

  COPY:  复制文件。 其基本格式:

      格式1:COPY <源路径>...<目标路径>

      格式2:COPY [“<源路径1>,....."<目标路径>"]

  ADD: 更高级的复制文件,在COPY的基础上增加了一些功能,如果复制的是压缩包的话,会直接解压,而不需要在使用RUN解压;

  CMD:容器启动命令。其基本格式:

      shell格式: CMD <命令>

      exec格式: CMD ["可执行文件", "参数1", "参数2"...]

      参数列表格式: CMD [“参数1”, “参数2”...],在指定了ENTRYPOINT指令后,用CMD指定具体的参数

  ENTRYPOINT: 入口点。其基本格式分为exec和shell,

      ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。当指定了ENTRYPOINT后,CMD的含义就发生了改变,不在是直接运行其命令,而是将CMD的内容作为参数传递给ENTRYPOINT指令。其执行时就变成了:  <ENTRYPOINT> "<CMD>"

  ENV: 设置环境变量。(都可以使用这里使用的变量)其基本格式:

      格式1:ENV <key> <value>

      格式2:ENV <key1>=<value1> <key2>=<value>...

  ARG: 构建参数。构建参数和ENV的效果一样,都是设置环境变量,所不同的是ARG所构建的环境变量在将来容器运行时是不存在的。其基本格式:

      格式1: ARG <参数名> [=<默认值>]

      格式2: 该默认值可以在构建命令 docker build  中用 --build-arg <参数名>=<值> 来覆盖

  VOLUME: 定义匿名卷。 其基本格式:

      格式1: VOLUME ["<路径1>", "<路径2>"...]

      格式2: VOLUME <路径>

  EXPOSE:  暴露端口。EXPOSE指令是声明运行时容器所提供的端口,在启动容器时不会在因为这个声明而开启端口。 其基本格式:

      格式1: EXPOSE <端口1> [<端口2>...]

  WORKDIR: 指定工作目录。其基本格式:

      格式1: WORKDIR <工作目录路径>

  USER: 指定当前用户。USER是帮助你切换到指定用户。 其基本格式:

      格式1: USER <用户名>

  HEALTCHECK: 健康检查,判断容器的状态是否正常。 其基本格式:

      格式1: HEALTCHECK [选项] CMD <命令> :设置检查容器健康状况的命令

      格式2: HEALTCHECK NONE: 如果基础镜像有健康检查指令,使用此格式可以屏蔽掉其健康检

3. Dockerfile文件说明

Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以字符开头则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,ENV等指令。

3.1 常用指令

3.1.1 FROM

FROM:指定基础镜像,必须为第一个命令。
定制的镜像都是基于 FROM 的镜像,这里的 nginx就是定制需要的基础镜像。后续的操作都是基于 nginx。

格式:
  FROM <image>
  FROM <image>:<tag>
 	#示例:FROM nginx:1.15-alpine。默认使用latest版本的基础镜像

3.1.2 MAINTAINER

维护者信息。

格式:
    MAINTAINER <name>
示例:
    MAINTAINER Jasper Xu
    MAINTAINER sorex@163.com
    MAINTAINER Jasper Xu <sorex@163.com>

3.1.3 RUN

构建镜像时执行的命令

# RUN用于用于指定 docker build 过程中要运行的命令
# 有两种命令执行方式
# shell执行
RUN <command>

# exec执行	
RUN ["executable", "param1", "param2"]
    
# 示例
RUN ["./test.php", "dev", "offline"]
# 等价于 
RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。
例如:

FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
# 以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

如上,以&& 符号连接命令,这样执行后,只会创建 1 层镜像。

3.1.4 CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同

  • CMD 在docker run 时运行,用于指定在容器启动时所要执行的命令
  • RUN 是在docker build时运行,用于指定镜像构建时所要执行的命令
# CMD 在docker run 时运行
# CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖
# CMD指令的首要目的在于为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束
# 注意:如果 dockerfile 中如果存在多个CMD指令,仅最后一个生效

# CMD写法和RUN一致,例如
CMD ["/usr/sbin/httpd","-c","/etc/httpd/conf/httpd.conf"]

一般用最简单的方式启动一个容器时使用docker run 会传递参数给docker指令

docker run -it image /bin/bash

后面的/bin/bash 其实是传递参数,告知容器启动时运行一个shell。这个过程可以用CMD 指令等效的替换

CMD ['/bin/bash']

因此在Dockerfile中存在这个CMD指令指定的命令时,启动容器就可以不进行参数传递。


如果dockerfile中已经指定了容器启动时运行的程序,同时在使用docker run 启动容器时使用了命令行参数,那么dockerfile 中的CMD 指令将无效

docker run -it image /bin/ps

发现启动容器后没有shell ,只是打印出了当前容器中的进程状态,cmd 指令效果被覆盖。

3.1.5 COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

COPY <src> <dest>
COPY ["<src>", "<dest>"]
# <src>:要复制的源文件或目录,支持使用通配符
# <dest>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建
# 建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径
# 注意:在路径中有空白字符时,通常使用第二种格式

文件复制准则

  • <src>必须是build上下文中的路径,不能是其父目录中的文件
  • 如果<src>是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制
  • 如果指定了多个<src>,或在<src>中使用了通配符,则必须是一个目录,且必须以/结尾
  • 如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径

3.1.6 ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD :在执行 <源文件> 为 tar 压缩文件的话,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget。
  • COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源。

3.1.7 WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

WORKDIR <工作目录路径>

3.1.8 ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

 ENV <key> <value>

3.1.9 EXPOSE

仅仅只是声明端口。
作用

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

3.1.9 VOLUME

在介绍VOLUME指令之前,我们来看下如下场景需求:

1)容器是基于镜像创建的,最后的容器文件系统包括镜像的只读层+可写层,容器中的进程操作的数据持久化都是保存在容器的可写层上。一旦容器删除后,这些数据就没了,除非我们人工备份下来(或者基于容器创建新的镜像)。能否可以让容器进程持久化的数据保存在主机上呢?这样即使容器删除了,数据还在。

2)当我们在开发一个web应用时,开发环境是在主机本地,但运行测试环境是放在docker容器上。

这样的话,我在主机上修改文件(如html,js等)后,需要再同步到容器中。这显然比较麻烦。

3)多个容器运行一组相关联的服务,如果他们要共享一些数据怎么办?

对于这些问题,我们当然能想到各种解决方案。而docker本身提供了一种机制,可以将主机上的某个目录与容器的某个目录(称为挂载点、或者叫卷)关联起来,容器上的挂载点下的内容就是主机的这个目录下的内容,这类似linux系统下mount的机制。 这样的话,我们修改主机上该目录的内容时,不需要同步容器,对容器来说是立即生效的。 挂载点可以让多个容器共享。

VOLUME用于指定持久化目录

VOLUME ["/data1","/data2"]

和docker run -v创建的挂载点区别

  1. 通过docker run命令的-v标识创建的挂载点只能对创建的容器有效。
  2. 通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。但是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。

上面的dockfile文件通过VOLUME指令指定了两个挂载点 /data1 和 /data2.
我们通过docker inspect 查看通过该dockerfile创建的镜像生成的容器,可以看到如下信息

"Mounts": [
        {
            "Name": "d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21",
            "Source": "/var/lib/docker/volumes/d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21/_data",
            "Destination": "/data1",
            "Driver": "local",
            "Mode": "",
            "RW": true
        },
        {
            "Name": "6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36",
            "Source": "/var/lib/docker/volumes/6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36/_data",
            "Destination": "/data2",
            "Driver": "local",
            "Mode": "",
            "RW": true
        }
    ],
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dockerfile是一个文本格式的配置文件,用于快速创建自定义的镜像。它由一行行命令语句组成,并且支持以#开头的注释行。一般而言,Dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。\[2\] 在Dockerfile中,第一行必须指定基础镜像信息,使用FROM关键字。接下来是维护者信息,使用MAINTAINER关键字。然后是镜像操作指令,如RUN等,每执行一条RUN命令,镜像添加新的一层。最后是CMD指令,用于指明运行容器时的操作命令。\[2\] 例如,一个简单的Dockerfile可以包含以下内容: ``` #基础镜像 FROM centos #维护者 MAINTAINER first<[email protected]> #容器启动命令 CMD echo "hello Dockerfile" ``` 这个Dockerfile使用了centos作为基础镜像,指定了维护者信息,并在容器启动时执行了一个命令。\[1\] 使用Dockerfile构建镜像的命令是: ``` docker build -t 镜像名字:版本 . ``` 其中,镜像名字是你想要给镜像起的名字,版本是镜像的版本号,"."表示Dockerfile所在的当前目录。\[1\] #### 引用[.reference_title] - *1* *2* [Docker手把手教程(四)Dockerfile完全指南](https://blog.csdn.net/weixin_44593822/article/details/127359647)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Docker容器-------dockerfile概念简介](https://blog.csdn.net/qq_45088125/article/details/125814112)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值