Docker(五) Dockerfile构建镜像

目录

一. Dockerfile简介

1. 什么是Dockerfile

2. Dockefile构建原理

3. Dockerfile构建指令

二. Dockerfile指令详解

1. FROM

2. RUN

3. WORKDIR

4. ENV

5. EXPOSE

6. VOLUME

7. COPY

8. ADD

9. CMD

10. ENTRYPOINT

三. Dockerfile打包项目实例


一. Dockerfile简介

1. 什么是Dockerfile

        在之前的学习中,我们了解到可以将运行起来的容器通过commit打包为一个镜像,但是这种方法仅限于在已有容器的基础上,并且具有一定的局限性。于是便产生了Dockerfile构建镜像。

        Dockerfile是一种Docker镜像的描述文件,是由一系列命令和参数构成的脚本。它主要作用是用来构建docker镜像的构建文件。Dockerfile文件在构建时,按照指令顺序由上到下依次执行,每条指令都会基于上一层创建并叠加一个新的镜像层,并对镜像进行提交。最终得到我们定制的镜像。

2. Dockefile构建原理

         Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。

        在构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。然后服务器会解析dockerfile文件,并自动执行其中的指令,来构建我们定制的镜像。

3. Dockerfile构建指令

# docker build [OPTIONS] [PATH | URL | -]

  • OPTIONS:
    • -f : 显式指定构建镜像的 Dockerfile 文件名称(Dockerfile 可不在上下文目录中),若不指明则默认为当前目录下的 'Dockerfile'
    • -t : 指明docker镜像的名称和版本号 imag:tag
  • 上下文路径|URL:指定构建镜像的上下文目录路径。docker会将上下文目录的所有内容作为镜像环境全部打包发给服务器,构建镜像的过程中,可以且只可以引用上下文中的任何文件(但是上下文目录并不封装到镜像中,只是作为镜像构建的服务器目录环境) 。因此,在实际开发中通常创建一个空目录来放置Dockerfile,并使用 . 指定当前目录作为上下文目录。
#举例子
docker build -f mydockerfile -t mycentos:1.0 .

二. Dockerfile指令详解

1. FROM

        FROM指令用来指定构建的基础镜像。所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。因此一个 DockerfileFROM 是必备的指令,并且必须是第一条指令。其语法如下:

  • FROM <image>:<tag>

#举例子
FROM centos:7
  • FROM指定构建镜像的基础源镜像,如果本地没有指定的镜像,则会自动从 Docker 的公共库 pull 镜像下来。
  • FROM必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile 从FROM语句开始。
  • FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像。
  • 如果FROM语句没有指定镜像标签,则默认使用latest标签。

2. RUN

        RUN指令用于在构建镜像时,将在当前镜像层基础上执行指定命令(如yum下载安装、文件处理、环境配置等等),并提交为新的镜像层,后续的RUN都以之前RUN提交后的镜像为基础。RUN 指令在定制镜像时是最常用的指令之一。其语法如下:

  • shell 格式:RUN <命令>  比如:RUN yum install vim
  • exec 格式:RUN ["可执行文件", "参数1", "参数2"](不要使用单引号) 比如:RUN ["yum","install","vim"]
#例子:定制镜像时安装vim和wget(等同于,在终端操作的 shell 命令。)
FROM centos:7
RUN yum install -y vim
RUN ["yum","install","-y","net-tools"]

改进:dockerfile支持以 && 连接多条指令,行尾添加 \ 的命令换行,以及行首 # 进行注释的格式,这样我们可以将多条RUN命令串联起来,将两层镜像层简化为一层,缩小镜像体积减少镜像臃肿。

#例子:定制镜像时安装vim和wget(等同于,在终端操作的 shell 命令。)
FROM centos:7
RUN yum install -y vim \
    && yum install -y net-tools

3. WORKDIR

        使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录,即刚入容器时所在的目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。其语法为:

  • WORKDIR <工作目录路径>
FROM centos:7
WORDIR /usr

 注意:

  • 不要使用RUN cd 来指定变更工作目录:由于Docker是分层的RUN的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。
  • 可以使用多个WORKDIR指令:后续命令如果参数是相对路径,则会基于之前命令指定的路径。

4. ENV

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

  • ENV <key> <value>         # 只能设置一个变量
  • ENV <key1>=<value1> <key2>=<value2>... #允许一次设置多个变量
#ENV 定义环境变量
ENV NODE_VERSION 7.2.0
# $NODE_VERSION 调用环境变量 
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

5. EXPOSE

        EXPOSE 指令是声明运行时容器提供的服务端口。这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。该指令仅仅是声明我们这个镜像中打算使用哪些端口,并没有实质性的作用,只是便于开发人员理解和维护镜像配置。我们还是要通过 -p 来公开映射外部访问端口。其语法如下:

  • EXPOSE <端口1> [ <端口2>... ]

6. VOLUME

        为了防止启动容器时用户忘记将动态文件所保存目录挂载为数据卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,则相应目录会自动挂载到一个匿名数据卷上。其语法为:

  • VOLUME ["<路径1>", "<路径2>"...] #多路径挂载
  • VOLUME <路径> #单路径挂载
#匿名挂载
VOLUME /data

#容器启动
docker run -d xxx #/data 目录就会在运行时自动挂载为匿名卷

docker run -d -v mydata:/data xxxx #mydata 这个命名卷替代了Dockerfile 中定义的匿名卷的挂载配置。

7. COPY

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

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

注意:

  • <源路径> 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 filepath.Match 规则
  • <目标路径> 只有一个,可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。
FROM centos:7

WORKDIR /usr
COPY aa.txt bb.txt /apps/ #复制两个文件到绝对路径/apps下

8. ADD

        ADD 指令和 COPY 的格式和性质基本一致,也是用来给镜像复制文件。但是在 COPY 基础上增加了一些功能。

  • <源路径> 可以是一个 URL:在这情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去,下载后的文件权限自动设置为 600 。但下载文件不会自动解压缩。
  • <源路径> 为一个 tar 压缩文件:ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
FROM centos:7
WORKDIR /usr

#从URL下载
ADD https://xxx.tar.gz /data/apps/

#本地解压文件
ADD tomcat-8.5.tar.gz /data/apps/
RUN mv tomcat-8.5 tomcat #改名

9. CMD

        CMD指令用于在容器启动时自动执行某些命令(类似于开机启动项),其包括以下三种语法格式:

  • shell 格式(推荐):CMD <命令>
  • exec 格式(双引号):CMD ["可执行文件", "参数1", "参数2"...]
  • 参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,搭配用 CMD 指定具体的参数。

注意:

  • 每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。
  • 如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。
FROM centos:7
WORKDIR /usr

#CMD ["ls","/usr"] 开机展示/usr目录
CMD ls /usr
-----------------------------------
docker run -it mycentos:3.0    #默认执行CMD
docker run -it mycentos:3.0 ls /root #指定"ls /root"会覆盖CMD

10. ENTRYPOINT

        ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。其语法规则如下:

  • ENTRYPOINT <命令>
  • ENTRYPOINT ["可执行文件","参数1","参数2"]

注意:

  • 每个 Dockerfile 只能有一条 ENTRYPOINT 命令。如果指定了多条命令,只有最后一条会被执行。
  • 如果用户启动容器时候指定了运行的参数,则会添加到 ENTRYPOINT 指定的命令之后。
FROM centos:7
WORKDIR /usr

#ENTRYPOINT ["ls","/usr"] 开机展示/usr目录
ENTRYPOINT ls
-----------------------------------
docker run -it mycentos:3.0    #默认执行
docker run -it mycentos:3.0 /usr #追加 ls /usr 执行

        ENTRYPOINT常与CMD搭配使用,当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:<ENTRYPOINT> "<CMD>"。因此,常在ENTRYPOINT中指定固定不变的命令,在CMD中指定可变命令参数,在docker run时通过指定参数来覆盖CMD内容实现镜像变成像命令一样使用。(注意ENTRYPOINT和CMD都只能使用exec格式)

FROM centos:7
WORKDIR /usr

ENTRYPOINT ["ls"]
CMD ["/usr"]
-------------------
docker run -it mycentos:3.0 #默认执行 ls /usr
docker run -it mycentos:3.0 /root #执行 ls /root

三. Dockerfile打包项目实例

FROM openjdk:8-jdk #基础jdk环境
WORKDIR /app #指定工作目录
COPY demo-0.0.1-SHAPSHOT.jar app.jar #复制项目jar包并改名
EXPOSE 8081 #暴露端口
ENTRYPOINT ["java","-jar"] #固定执行指令
CMD ["app.jar"] #可变 jar名称

------------------------------------
docker run -d -p 8081:8081 --name demo demo:01 #运行容器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿阿阿安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值