Dockerfile

学习自:Dockerfile详解(超详细) - 简书

1、说明

Dockerfile是一个组合镜像命令的文本文件,其中存放了一系列指令,Docker通过这些指令自动生成镜像。

写好Dockerfile之后,通过指令docker build -t repository:tag 路径 即可构建,要求路径下存在Dockerfile文件

镜像是分层的,Dockerfile中每多一条指令,就多一层。用&&或\连接的多条指令仍视为一条指令。

2、规则

  1. 文件名一定是Dockerfile;
  2. Dockerfile中用到的所有文件都和Dockerfile文件位于同级目录下
  3. Dockerfile中的相对路径默认都是Dockerfile所在目录;
  4. Dockerfile是分层结构,一行就是一层,构建镜像时是分层构建的,因此某些指令能写到一行就写到一行,减少层次;
  5. Dockerfile对指令大小写不敏感,但是指令都用大写;
  6. 非注释第一行一定是FROM;
  7. Dockerfile工作空间目录下支持隐藏文件(.dockerignore),类似git的.gitignore
  8. 一行写不下,可以用\来换行接着写

3、指令

1)FROM:基础镜像

语法:FROM <image>:<tag> [as new_name]

例子:

FROM 172.30.138.23/base/nginx_2024v1:latest

说明

  • FROM是非注释首行代码;
  • 为该镜像文件指定基础镜像,后续指令都基于该基础镜像环境运行;
  • 基础镜像可以是任何一个已存在的镜像文件
  • as new_name是可选的,常用于长期工程、多阶段构建(有利于减少镜像大小
  • 通过--from other_name 使用,例如COPY --from oter_name

2)LABEL:镜像描述信息

语法

#①
LABEL K1=V1 K2=V2

#②
LABEL K1=V1
LABEL K2=V2

#③
LABEL K1=V1 \
    K2=V2

例子

LABEL author="zp wang <test@qq.com>"
LABEL describe="test image"

说明

  • V一般情况下是带引号字符串
  • LABEL长用于以K-V对的形式给镜像添加一些META信息;
  • 可以用于替代MAINTAINER指令
  • 会集成基础镜像中的LABEL,如果二者存在同名K,新K覆盖老K

3)MAINTAINER:作者信息

语法:MAINTAINER 姓名 <邮箱>

例子

MAINTAINER Shine Le <test@qq.com>

说明:其功能正逐渐被LABEL替代

4)COPY:从本机复制文件到镜像中

用途:

  从本机复制文件到镜像中,每个镜像在运行起来之后,都有其独立的文件系统结构,就像一个虚拟机一样。

  使用COPY指令可以把本机中的文件复制到镜像中的指定目录下。

语法:COPY src dst

例子

COPY startServer.sh /app/bin/startServer.sh

说明

  关于src

  • src是本机路径,且为以Dockerfile所在目录为起始的相对路径;
  • src的路径必须是以Dockerfile所在的目录为起始,不能选到Dockerfile的父目录;
  • 如果src是目录,那么其下的所有文件、子目录都会递归复制到dst,但src目录自身不会复制
  • 因此要把某个目录复制到镜像中的同名目录下,dst中还要把该目录名给加上;
  • 如果指定了多个src,那么dst必须是目录,且以/结尾;

  关于dst

  • dst为容器中的路径,每个容器都像一个虚拟机,其中的文件有独立的文件结构和路径;
  • 如果dst不存在,那么会自动递归创建。

5)ADD:从本机复制文件到镜像

用途:

  同COPY,但是ADD支持将tar文件解压缩

语法:ADD src dst

说明

  • 如果src是一个压缩文件,那么会被解压为一个目录;
  • 如果src是一个URL,那么会通过URL下载一个文件;
  • 如果src是多个,那么dst必须是以/结尾的目录,否则src会被视为一个普通文件。

6)WORKDIR:设置(容器)工作目录

用途:

  类似cd命令,改变(容器中的)当前工作目录。

  默认情况下,容器命令执行时的当前目录为/,可以通过WORKDIR改变当前目录。

  之后的RUN、CMD、ENTRYPOINT、COPY、ADD都会将该目录作为当前工作目录。

语法:WORKDIR 绝对路径

例子

WORKDIR /opt

说明

  • 如果路径中的某个目录不存在会自动创建,包括它的父目录;
  • 一个Dockerfile中的WORKDIR可以出现多次,也可以为相对路径,这里的相对是指相对于前一个WORKDIR
  • 可以在WORKDIR中调用ENV指定的变量。

7)ENV:设置环境变量

语法

  ENV K1 V1

  ENV K1=V1 K2=V2 K3=V3 ……

环境变量的使用方式(下文的K是上文K-V定义时的K)

  • $K
  • ${K}
  • ${K:-default V}
  • ${K:+default V}

例子

#定义
ENV NGINX_VERSION 1.16.1

#使用
RUN cd /usr \ 
    && tar -zxvf nginx_${NGINX_VERSION}.tar.gz

 

8)USER:设置启动容器的用户

语法:USER username

例子

USER dcos

9)RUN:构建镜像时指定的命令

语法

  • shell形式:RUN 指令1 && 指令2 && ……
  • exec形式:RUN ["executable" , "参数1" , "参数2" , ……]

例子

#简单用法
#打印1和2
RUN echo 1 && echo 2

#常规用法
RUN chown -R dcos:docker /app/bin/startServer.sh /usr/nginx/conf

#分行多条指令
RUN cd /usr \
    && curl -O https://172.29.32.190:8081/nginx/${NGINX_VERSION}.tar.gz \
    && tar -zxvf nginx/${NGINX_VERSIOIN}.tar.gz

说明

  • RUN在下次构建期间,会优先查找本地缓存,如果不想用缓存可以用--no-cache解除:
    docker build --no-cache
  • shell形式:
    • 默认用/bin/sh -c执行后续的命令;
    • 可以用&&与\连接多个命令
  • exec形式:
    • exec形式会被解析为JSON序列,这意味着必须用双引号""
    • 与shell不同,exec形式不会调用shell解析。但是exec形式可以运行在不包含shell命令的基础镜像中;
    • 例如:RUN ["echo","$HOME"] ;这样的指令 $HOME并不会被解析,必须RUN ["/bin/sh","-c","echo $HOME"]

10)EXPOSE:打开指定端口以实现与外部通信

语法:EXPOSE <port>/<protocol>

例子

EXPOSE 80
EXPOSE 80/http
EXPOSE 2379/tcp

说明

  • 不写protocol时,默认协议为tcp;
  • 实际暴露时需要在docker run时用-P指定。

11)VOLUME:挂载,将宿主机目录挂载到容器中

语法:VOLUME 挂载路径 挂载点

例子:

VOLUME ["/data"]                    # [“/data”]可以是一个JsonArray ,也可以是多个值

VOLUME /var/log 
VOLUME /var/log /opt

说明

  • 一般不用于Dockerfile,且在Kubernetes场景中几乎没用

12)CMD:为容器设置默认启动命令或参数

语法

#1 shell形式
CMD 指令 参1 参2

#2 exec形式
CMD ["executable","参1","参2"]

#3 exec形式,但是只设置参数
CMD ["参1","参2"]

例子

CMD ["/app/bin/startServer.sh"]

说明

    • CMD运行结束后容器将终止,CMD可以被docker run后边的命令覆盖;
    • 一个Dockerfile只有顺序向下的最后一个CMD生效;
    • 三种语法:
      • shell,默认/bin/sh -c
        • 此时运行为shell子进程,可以使用shell的操作符(if、环境变量、?*通配符)
        • 位于容器中的进程的PID !=1 ,这意味着该进程并不能接受到外部传入的停止信号docker stop
      • execCMD ["executable","参数1",'参数2"]  
        • 不会以/bin/sh -c运行(非shell子进程),因此不支持shell操作符;
        • 若运行的命令依赖shell特性,可以手动启动 CMD ["/bin/sh","-c","executable","参1","参2",……]
      • exec,CMD ["参1","参2"]
        • 一般结合ENTRYPOINT指令使用。

13)ENTRYPOINT:为容器指定默认运行程序或命令

用途

与CMD类似,但存在区别,主要用于指定启动的父进程的PID=1。

用法

#1 shell形式
ENTRYPOINT command

#2 execz形式
ENTRYPOINT ["/bin/bash","参1","参2"]

说明

  • ENTRYPOINT设置默认命令不会被docker run命令行指定的参数覆盖,指定的参数会被传递给ENTRYPOINT指定的程序;
  • docker run命令的--entrypoint选项可以覆盖ENTRYPOINT指令指定的程序
  • 一个Dockerfile中可以有多个ENTRYPOINT,但只有最后一个生效;
  • ENTRYPOINT主要用于启动父进程,后边的参数会被当做子进程来启动

 

4、补充

1)Dockerfile非注释首行是FROM,代表它的基础镜像。但是首个基础镜像的FROM是什么?

由于FROM是构建镜像上下文的开始,因此必须存在。

 

基础镜像:FROM scratch,表示使用一个空镜像。

 

posted @ 2024-04-16 13:47  ShineLe  阅读(7)  评论(0编辑  收藏  举报