Docker学习(四) Dockerfile

Docker学习

序号内容链接
1Docker概述及部分原理https://blog.csdn.net/qq_35551748/article/details/108483628
2Docker安装https://blog.csdn.net/qq_35551748/article/details/108262522
3Docker常用命令https://blog.csdn.net/qq_35551748/article/details/108569397
4Docker数据卷https://blog.csdn.net/qq_35551748/article/details/110926790
5Dockerfilehttps://blog.csdn.net/qq_35551748/article/details/110949905


一、Docker镜像构建步骤

  1. 编写一个Dockerfile文件
  2. docker build 构建成为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像

二、什么是Dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明,Docker就是通过读取Dockerfile中的指令来自动生成镜像的。

三、Dockerfile基础结构

Dockerfile一般可以分为四部分:
基础镜像信息 维护者信息 镜像操作指令 启动时执行指令

四、Dockerfile编写说明

  • Dockerfile中每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  • Dockerfile中指令必须大写
  • Dockerfile中指令按照从上到下的顺序顺序执行
  • Dockerfile中能写到一行的指令一定要写在一行,因为每条指令都会创建一个新的镜像层,并对镜像进行提交
  • Dockerfile中#表示注释,用于说明Dockerfile中的指令
  • Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下,可以为Dockerfile父目录的子目录
  • Dockerfile中相对路径默认都是Dockerfile所在的目录

五、Docker执行Dockerfile的大致流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成

六、Dockerfile常用指令

指令说明
FROM指定基础镜像
MAINTAINER指定维护者信息,已经过时,可以使用LABEL maintainer=xxx 来替代
LABEL指定生成镜像的元数据标签信息
ADD复制指定的src路径下的内容到容器中的dest路径下,src可以为url会自动下载,可以为tar文件,会自动解压
COPY复制本地主机的src路径下的内容到镜像中的dest路径下,但不会自动解压
ENV指定环境变量,可以在docker run的时候使用-e改变
WORKDIR配置工作目录,为后续的RUN、CMD、ENTRYPOINT指令配置工作目录
VOLUME创建数据卷挂载点
EXPOSE声明镜像内服务监听的端口
RUN运行命令
CMD指定启动容器时默认的命令
ENTRYPOINT指定镜像的默认入口
USER指定运行容器时的用户名或UID
ARG指定镜像内使用的参数(如版本号信息等),可以在build的时候,使用–build-args改变
ONBUILD指定只对当前镜像的子镜像生效的触发器

6.1 FORM

FROM 是Dockerfile 内置命令中唯一一个必填项,其有以下三种用法。FROM用来指定后续指令执行的基础镜像,所以在一个有效的Dockerfile中,FROM永远是第一个命令。
FROM 指定的基础镜像既可以是本地已经存在的镜像,也可以是远程仓库中的镜像。当Dockerfile执行时,如果本地没有其指定的基础镜像,那么就会从远程仓库中下载此镜像。
在FROM用法中,tag和digest属于可选项,如果没有则默认取指定镜像的最新版,也就是latest版本。如果找不到latest版本,那么整个Dockerfile 就会报错返回。

# 格式
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>

# 如果不以任何镜像为基础
FROM scratch

# 示例
FROM mysql:8.0.22

6.2 MAINTAINER

MAINTAINER用于让镜像制作者提供本人的详细信息。Dockerfile并不限制 MAINTAINER指令可出现的位置,但一般将其放置于 FROM指令之后。已经过时,可以使用LABEL maintainer=xxx 来替代

# 格式
MAINTAINER <name>

# 示例
MAINTAINER xiaoming
MAINTAINER xiaoming@163.com
MAINTAINER xiaoming <xiaoming@163.com>

6.3 LABEL

LABEL用于为镜像添加元数据,元数据以键值对的形式指定。使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,如太长需要换行的话则使用\符号,以免生成过多的中间镜像。并且LABEL会继承基础镜像中的LABEL,如遇到key相同,则值覆盖。

# 格式
LABEL <key>=<value> <key>=<value> <key>=<value> ...

# 示例
LABEL version="1.0" description="xxxxx" by="xxxxx"

6.4 ADD

ADD用于复制指定的src路径下的内容到容器中的dest路径下,src可以为url会自动下载,可以为tar文件,会自动解压。路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径,推荐写成绝对路径。可以是一个本地文件或者是一个本地压缩文件,还可以是一个url,如果写成一个url,那么ADD就类似于wget命令。

规则:

  • 如果<src>为URL并且<dest>没有以/结尾,则<src>指定的文件将被下载并直接创建为<dest>,如果<dest>以/结尾,则文件名URL指定的文件将被直接下载,并保存为<dest>/<filename>,URL不能是ftp格式的url
  • 如果<src>是一个本地系统上压缩格式的tar文件,它会展开成一个目录,但是通过URL获取的tar文件不会自动展开
  • 如果<src>有多个或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径,如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>
# 格式
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]

# 示例
# 添加所有以"test"开头的文件
ADD test* /mydir/
# ?替代一个单字符,例如:"test01.txt"
ADD test?.txt /mydir/
# 添加"test" 到 `WORKDIR`/relativeDir/
ADD test relativeDir/
# 添加"test" 到 /absoluteDir/
ADD test /absoluteDir/

6.5 COPY

COPY用于复制本地主机的src路径下的内容到镜像中的dest路径下。COPY功能类似ADD,但是不会自动解压文件,也不能访问网络资源,也就是说src只能是本地文件。

规则:

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

6.6 ENV

ENV用于为镜像定义所需的环境变量,并可被 Dockerfile文件中位于其后的其它指令(如 ENV、ADD、COPY等)所调用 ,即先定义后调用,调用格式:$variable_name或者${variable_name}

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

6.7 WORKDIR

WORKDIR 为工作目录,指当前容器环境的工作目录,用于为 Dockerfile中所有的 RUN、CMD、ENTRYPOINT、COPY和 ADD指定设定工作目录,通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行,并且只会影响当前WORKDIR之后的指令。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。在Dockerfile文件中,WORKDIR可以出现多次,路径可以是相对路径,但是它是相对于前一个WORKDIR指令指定的路径。WORKDIR也可以解析环境变量。

# 格式
WORKDIR <dirpath>

# 示例
# 这时工作目录为/a
WORKDIR /a
# 这时工作目录为/a/b
WORKDIR b
# 这时工作目录为/a/b/c
WORKDIR c

6.8 VOLUME

VOLUME用于创建挂载点,可以挂载宿主机上的卷或者其他容器上的卷。不能指定宿主机当中的目录,宿主机挂载的目录是自动生成的。如果挂载点目录路径下此前该文件存在, docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中。

一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

  • 卷可以容器间共享和重用
  • 容器并不一定要和其它容器共享卷
  • 修改卷后会立即生效
  • 对卷的修改不会对镜像产生影响
  • 卷会一直存在,直到没有任何容器在使用它
# 格式
VOLUME ["/data"]

# 示例
VOLUME ["/var/test/"]
VOLUME /var/test
VOLUME /var/test1 /var/test2

6.9 EXPOSE

EXPOSE用于暴露指定端口,为容器打开指定要监听的端口,以实现与外部通信。但EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口。

# 格式
# <protocol>用于指定传输层协议,可以是TCP或者UDP,默认是TCP协议
EXPOSE <port>[/<protocol>] [<port>[/<protocol>]...]

# 示例
EXPOSE 80 443
EXPOSE 80/tcp 80/udp

6.10 RUN

RUN用于指定 docker build过程中运行的程序,其可以是任何命令,但是这里有个限定,一般为基础镜像可以运行的命令,如基础镜像为centos,安装软件命令为yum而不是ubuntu里的apt-get命令。RUN和CMD都可以改变容器运行的命令程序,但是运行的时间节点有区别,RUN表示在docker build运行的命令,而CMD是将镜像启动为容器运行的命令。因为一个容器正常只用来运行一个程序,因此CMD一般只有一条命令,如果CMD配置多个,则只有最后一条命令生效。而RUN可以有多个。如果RUN的命令很多,就用&&符号连接多个命令,少构建镜像层,提高容器的效率。RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache

shell和exec的区别: shell直接在后面跟shell命令,linux操作系统上默认 /bin/sh -c,windows操作系统上默认 cmd /S /C;exec则类似函数调用,参数是一个JSON格式的数组,当中<executable>是要运行的命令,后面是传递给命令的选项或者参数。

# 格式
# shell
RUN <command>
# exec
RUN ["executable", "param1", "param2"]

# 示例
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]

6.11 CMD

CMD类似于 RUN指令, CMD指令也可用于运行任何命令或应用程序,但是二者的运行时间点不同 。RUN指令运行于映像文件构建过程中,而CMD指令运行于基于 Dockerfile构建出的新映像文件启动一个容器时(CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令)。CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;CMD指定的命令可以被 docker run的命令行选项所覆盖 ,在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效。

# 格式
# 执行shell内部命令
CMD command param1 param2
# 执行可执行文件,优先
CMD ["executable","param1","param2"]
# 设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数
CMD ["param1","param2"]

6.12 ENTRYPOINT

ENTRYPOINT类似 CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序。与CMD不同的是,由 ENTRYPOINT启动的程序不会被 docker run命令行指定的参数所覆盖,而且这些命令行参数会被当作参数传递给 ENTRYPOINT指定指定的程序 。但是docker run命令的 --entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序。docker run 命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用 。Dockerfile文件中也可以存在多个 ENTRYPOINT指令,但仅有最后一个会生效。

# 格式
# shell内部命令
ENTRYPOINT command param1 param2
# 可执行文件, 优先
ENTRYPOINT ["executable", "param1", "param2"]

6.13 USER

USER用于指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户。如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行,使用这个命令一定要确认容器中拥有这个用户,并且拥有足够权限。

# 格式
USER user
USER user:group
USER uid
USER uid:gid
USER user:gid
USER uid:group

# 示例
USER test

6.14 ARG

ARG用于指定传递给构建运行时的变量。也可以在docker build创建镜像的时候,使用--build-arg <varname>=<value>来指定变量,如果通过docker build创建镜像时指定了一个参数但没有在Dockerfile中定义,那么将产生一个Warning([Warning] One or more build-args [test] were not consumed)。如果我们给了ARG定义了参数默认值,那么过docker build创建镜像时没有指定参数值,则会使用这个默认值。

# 格式
ARG <name>[=<default value>]

# 示例
ARG test
ARG build_user=test

6.15 ONBUILD

ONBUILD 用于在 Dockerfile中定义一个触发器。当包含ONBUILD指令所构建的镜像被其它镜像当做基础镜像时,该镜像中ONBUILD指令定义的触发器将会被触发。
尽管任何指令都可注册成为触发器指令,但是ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令。使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签。在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败。ONBUILD 在构建镜像时不会运行,是别人基于这个镜像作为基础镜像构建时,才会运行,也就是说这个命令只对当前镜像的子镜像生效。

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

七、Dockerfile示例

7.1 构建centos镜像

# 指定基础镜像(官方的centos)
FORM centos
# 指定镜像制作者信息
MAINTAINER test<xxxxxxxxx@qq.com>
# 指定环境变量
ENV MYPATH /usr/local
# 指定工作目录
WORKDIR $MYPATH
# 指定构建镜像时运行的命令
RUN yum -y install vim
RUN yum -y install net-tools
# 指定暴露的端口
EXPOSE 80
# 指定容器启动时运行的命令
CMD /bin/bash

7.2 构建tomcat镜像

# 指定基础镜像(官方的centos)
FORM centos
# 指定镜像制作者信息
MAINTAINER test<xxxxxxxxx@qq.com>
# 拷贝本地文件到容器内
COPY test.txt /usr/local/test.txt
# 添加压缩包
ADD jdk-8u261-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.29.tar.gz /usr/local
# 指定构建镜像时运行的命令
RUN yum -y install vim
# 指定环境变量
ENV MYPATH /usr/local
# 指定工作目录
WORKDIR $MYPATH
# 配置java环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_261
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.29
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.29
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 指定暴露的端口
EXPOSE 8080
# 指定容器启动时运行的命令
CMD /usr/local/apache-tomcat-9.0.29/bin/startup.sh

7.3 构建java项目镜像

# 指定基础镜像(jdk8)
FROM openjdk:8
# 指定镜像制作者信息
MAINTAINER test<xxxxxxxxx@qq.com>
# 将项目打包好的jar包复制到容器内(以下两种方式均可,区别是ADD既可以为网络资源也可以为本地文件,而COPY只能为本地文件)
ADD target/test-service.jar /test-service.jar
COPY target/test-service.jar /test-service.jar
# 指定暴露的端口
EXPOSE 8080
# 指定容器启动时运行的命令(以下两种方式均可,区别是ENTRYPOINT是以追加的方式,CMD是以覆盖的方式)
ENTRYPOINT ["java","-jar","/test-service.jar"]
CMD ["java","-jar","/test-service.jar"]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值