Dockerfile

目录

今日内容概述

Dockerfile构建镜像

今日内容详细

Dockerfile构建镜像

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。一般来说,Dockerfile主体内容分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行的指令。

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

Dockerfile

下面我们来看看具体的指令

FROM:指定基础镜像,必须为第一个命令

FROM 指定基础镜像,目的是为了给构建镜像提供一个基础环境
# 格式:
FROM <image>
  FROM <image>:<tag>
  FROM <image>@<digest>
示例:  FROM mysql:5.7
注:  tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像

MAINTAINER::维护者信息

指定维护者信息	# 没什么好说的

RUN:构建镜像时执行的命令

基于FROM指定的docker镜像运行一个指令,将结果反映到新生成的镜像。RUN指令后面执行的命令必须是镜像中已经存在了的命令。
# RUN有两种命令执行的方式
shell执行:
格式:
    RUN <command>
exec执行
格式:
    RUN ["executable", "param1", "param2"]
示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
注:  RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

CMD:构建容器后调用(在容器启动时才进行调用)

CMD指令用于指定一个容器启动时要运行的命令,这有点类似于RUN指令,只是RUN指令是指定镜像被构建时要运行的命令;而CMD是指定容器被启动时要运行的命令。这和使用docker run 命令时指定要运行的命令非常类似
# CDM可以为要运行的命令指定参数
CMD ["/bin/bash,"-l"]	这里将-l标志传递给了/bin/bash命令

CMD指令也有两种格式:
exec格式		
["nginx", "-g", "daemon off;"]
			
shell格式
nginx -g 'daemon off;'

# 需要注意的是,要运行的命令是存放在一个数组结构中的,这将告诉Docker按指定的样子来运行该命令,当然也可以不使用数组指定CMD指令,这时候Docker会在指定的命令前加上/bin/sh -c。这在执行该命令的时候可能会导致意料之外的行为,所以Docker推荐使用数组语法来设置要执行的命令。

最后一点,使用docker run 命令可以覆盖CMD指令,如果我们在Dockerfile里指定了CMD指令,而同时在docker run 命令中也指定了要运行的命令,命令行中指定的命令会覆盖Dockerfile中的CMD指令。

在Dockerfile中只能指定一条CMD指令,如果指定了多条CMD指令,也只有最后一条CMD指令会被使用。

ENTRYPOINT

ENTRYPOINT指令与CMD指令非常类似,也很容易和CMD指令弄混,它们有什么区别呢?
我们已经知道,docker run 命令行会覆盖CMD指令,但有时我们希望容器按我们希望的方式去工作,那么CMD就不够合适。
而ENTRYPOINT指令提供的命令不容易在启动容器时被覆盖,实际上docker run 命令行中指定的任何参数都会被当做参数再次传递给ENTRYPOINT指令中指定的命令。
例子:
ENTRYPOINT ["/usr/sbin/nginx"]
类似于CMD指令,我们也可以在该指令中通过数组的方式为命令行指定相应的参数
ENTRYPOINT ["/usr/sbin/nginx,"-g","daemon off;"]

# 如果ENTRYPOINT和CMD指令同时存在,则CMD的相关内容会被设置成ENTRYPOINT的参数

ADD和COPY

ADD : 将本地文件添加到镜像
    ADD支持自动解压,但是仅仅支持解压tar包
    ADD支持远程下载,但是不会解压网络资源
示例:
ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/
    
# ADD指令会使得构建缓存变得无效,这一点非常重要,如果通过ADD指令向镜像添加一个文件过目录,那么将使Dockerfile中的后续指令都不能继续使用之间的构建缓存。

COPY : 将文件复制到镜像
语法:COPY < src>… < dest>|[“< src>”,… “< dest>”]
指令逻辑与ADD十分相似,同样Docker Daemon会从编译目录寻找文件或目录,dest为镜像中的绝对路径或者相对于WORKDIR的路径

WORKDIR

WORKDIR用来从镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT或/CMD指定的程序会在这个目录下执行

我们可以使用该指令为Dockerfile中后续到的一系列指令设置工作目录,也可以为最终的容器设置工作目录
实例:
WORKDIR /opt/webapp/db
RUN bundle install
WORKDIR /opt/webapp
ENTRYPOINT ["rackup"]
# 这里我们将工作目录切换为/opt/webapp/db后运行了bundle install命令,之后又将工作目录设置为/opt/webapp,最后设置了ENTRYPOINT指令来启动rackup命令

可以通过-w标志在运行时覆盖工作目录
docker run -it -w /var/log ubuntu pwd /var/log
该命令会将容器内的工作目录设置为/var/log

ENV:设置环境变量

设置一个容器的环境变量
格式:
    ENV <key> <value>  #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
    ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
    ENV myName John Doe
    ENV myDog Rex The Dog
    ENV myCat=fluffy

新的环境变量可以在后续的任何RUN指令中使用;也可以使用docker run 命令行的-e参数来传递变量,这些变量只会在运行时有效。

USER

USER指令用来指定该镜像会以什么样的用户去运行
示例:
USER www
基于该镜像启动的容器会以www用户的身份来运行,我们可以指定用户名或UID以及组或GID,甚至是两者的组合
USER www
USER www:group
USER www:gid

我们也可以在docker run 命令中通过-u选项来覆盖该指令指定的值

# 如果不通过USER指令指定用户,默认用户为root

VOLUME:用于持久化目录

VOLUME指令用来向基于镜像创建的容器添加卷,一个卷是可以存在与一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统,并提供如下共享数据或者对数据进行持久化的功能。
1.卷可以在容器内共享和复用
2.一个容器可以不是必须和其他容器共享卷
3.对卷的修改不会对更新镜像产生影响
4.卷会一直保存直到没有任何容器再使用它。

卷功能让我们可以将数据(代码)、数据库或者其他内容添加到镜像中而不是将这些内容提交到镜像中,并且允许我们在多个容器间共享这些内容。

格式:
    VOLUME ["/path/to/dir"]
示例:
    VOLUME ["/data"]
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]

ARG:用于指定传递给构建运行时的变量

格式:
    ARG <name>[=<default value>]
示例:
    ARG site
    ARG build_user=www

ONBUILD:用于设置镜像触发器

ONBUILD指令能为镜像添加触发器(triggger),当一个镜像被用作其他镜像的基础镜像时,该镜像中的触发器将会被执行。
触发器会在构建过程中插入新的指令,我们可以认为这些指令是紧跟在FROM之后指定的,触发器可以是任何构建指令。

# 触发器,ONBUILD后面跟指令,在构建时不会执行,只有在当前镜像作为基础镜像构建时才会执行。

格式:  ONBUILD [INSTRUCTION]
示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src

EXPOSE:指定于外界交互的端口

格式:
    EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080    
    EXPOSE 11211/tcp 11211/udp
注:  
        EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出所有的端口

LABEL:用于为镜像添加元数据

格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
  LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
注:
  使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

构建镜像

1.Dockerfile
Dockerfile命名必须D大写其他必须小写
Dockerfile中所有的指令必须大写
2.构建镜像的命令
docker build -t 镜像名称 
参数:
-t : 指定构建镜像的名称
上一篇:Dockerfile


下一篇:Dockerfile 构建镜像