• Docker手把手教程(四)Dockerfile完全指南


    目录

    一.什么是Dockerfile

    二.构建镜像 

    三.常见的13种指令


    一.什么是Dockerfile

    概述
    Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 快速创建自定义的镜像。
    我们之前要运行一个容器,要先docker search一下看看有没有,然后再docker pull拉取镜像,最后再docker run创建并运行容器。但是大家有没有想过,如果docker的仓库里你想要的镜像一个也没有呢,这个怎么办呢,这就需要咱们自定义镜像了,这就需要Dockerfile。
    基本结构
    Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。一般而言, Dockerfile 分为四部分 : 基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
    例如 :
    1. ## Dockerfile文件格式
    2. # 1、第一行必须指定 基础镜像信息
    3. FROM java:8
    4. # 2、维护者信息
    5. MAINTAINER baizhan baizhan@163.com
    6. # 3、镜像操作指令
    7. RUN echo "wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.55/bin/apachetomcat-9.0.55.tar.gz"
    8. run tar -zxvf apache-tomcat-9.0.55.tar.gz -C /usr/local
    9. # 4、容器启动执行指令
    10. CMD /usr/local/tomcat/bin/catalina.sh
    Dockerfile 四部分说明:
    • 一开始必须要指明所基于的镜像名称, 关键字是FROM, 这是必须的.
    • 接下来是维护者信息关键字是MAINTAINER, 非必须, 但良好的习惯有利于后期的职责明确.
    • 后面是镜像操作指令, 如RUN等, 每执行一条RUN命令,镜像添加新的一层.
    • 最后是CMD指令,来指明运行容器时的操作命令. er

    二.构建镜像 

    简单示例
    在一个空白的文本文件 , 命名为 Dockerfile, 注意名字必须是这个! 咱们在/opt目录下创建此文件,
    vim Dockerfile
    示例 1
    Dockerfile 文件内容 :
    1. #基础镜像
    2. FROM centos
    3. #维护者
    4. MAINTAINER first<first@163.com>
    5. #启动容器运行命令
    6. CMD echo "hello Dockerfile"
    示例 2
    Dockerfile 文件内容 :
    1. FROM java:8
    2. MAINTAINER WCC
    3. CMD java -version
    构建镜像
    docker build -t 镜像名字:版本 .

    注意镜像名字和版本名称都是自己起。

    注意
    . 代表Dockerfile文件在当前路径

    咱们在刚在创建文件的那个目录下执行构建镜像命令。

    docker build -t my_custom1:v1 .

    Dockerfile文件中每一句话都对应一层的文件系统,我的文件内容用的示例一,所以会有三层文件系统,所以执行完上述命令之后,返回信息如下

    咱们通过上面的命令已经把自己写的Dockerfile文件build成了一个镜像,现在咱们看看是否有这个镜像,然后创建并运行(run)

     可以看到输出hello Dockerfile(是咱们Dockerfile中写的第三条命令),成功!

     大家可以用示例2自己再练习一下。

    三.常见的13种指令

    FROM
    指定基础镜像,必须为第一个命令。
    指令格式:
    1. FROM <image>
    2. FROM <image>:<tag>
    注意:
    tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
    MAINTAINER
    维护者信息
    指令格式:
    MAINTAINER <name>

    示例

    MAINTAINER Jasper Xu MAINTAINER sorex@163.com
    WORKDIR
    工作目录,类似于 cd 命令,即切换目录,在Dockerfile文件里配置之后,创建并启动容器,会自动将当前目录切换到WORKDIR指定的目录。
    指令格式:
    WORKDIR /usr/workdir

    示例:

    先进了a里,下面两个都是相对路径(没加斜杠)

    1. WORKDIR /a (这时工作目录为/a)
    2. WORKDIR b (这时工作目录为/a/b)
    3. WORKDIR c (这时工作目录为/a/b/c)
    注意:
    通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、 COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
    RUN
    构建镜像时 执行的命令
    指令语法:
    1. # 1. shell执行
    2. 格式 RUN <command>
    3. # 2. exec执行
    4. 格式 RUN ["executable", "param1", "param2"]

    示例: 

    1. #启动容器后进入opt目录
    2. WORKDIR /OPT
    3. #运行容器之后新建docker目录(在/opt下建,因为我们是先进入到了/opt目录下)
    4. RUN mkdir docker
    5. #又切换了另一个目录
    6. WORKDIR /usr/local
    7. 把echo "test"重定向到a.info
    8. RUN echo "test" > a.info
    注意:
    RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache
    ADD
    将本地文件添加到容器中, tar 类型文件会自动解压 ( 网络压缩资源不会被解压 ) ,可以访问网络资源,类似wget
    指令格式:
    1. ADD <src>... <dest>
    2. ADD ["",... ""] 用于支持包含空格的路径示例:
    示例
    添加所有以 "hom" 开头的文件
    ADD hom* /mydir/
    ? 替代一个单字符 , 例如: "home.txt"
    ADD hom?.txt /mydir/
    添加 "test" WORKDIR/relativeDir/
    ADD test relativeDir
    添加 "test" /absoluteDir/
    ADD test /absoluteDir/
    COPY
    功能类似 ADD ,但是是不会自动解压文件,也不能访问网络资源。
    语法格式:
    COPY <源路径> <目标路径>

    示例:

    COPY ./start.sh /start.sh
    CMD
    构建容器后调用 ,也就是在容器启动时才进行调用。指定这个容器启动的时候要运行的命令只有最后一 个会生效可被替换。
    注意和RUN指令的区别,RUN是 构建镜像时 执行的命令,执行的时期不同。
    指令格式:
    1. CMD指令与RUN指令相似,也具有两种格式:
    2. 1. shell格式:CMD <命令>
    3. 2. exec格式: CMD ["可执行文件", "参数1", "参数2", …]

    示例:

    1. CMD echo "This is a test." | wc -
    2. CMD ["/usr/bin/wc","--help"]
    注意:
    CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
    ENTRYPOINT
    配置容器,使其可执行化。配合 CMD 可省去 "application" ,只使用参数。
    指定容器启动的要运行的命令,可以追加命令。
    指令格式:
    1. ENTRYPOINT ["executable", "param1", "param2"]
    2. ENTRYPOINT command param1 param2 (shell内部命令)
    示例
    ENTRYPOINT ["top", "-b"]
    注意:
    ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而 docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
    ENV
    这个指令非常简单,就是用于设置环境变量而已,无论是接下来的指令,还是在容器中运行的程序,都可以使用这里定义的环境变量。
    指令格式:
    ENV <key>=<value>

    示例

    1. #系统里的实际路径
    2. ENV JAVA_HOME=/usr/local/jdk1.7.0_79
    3. #将jdk文件的bin包配置到路径里,配置之后在任何路径都可以使用java命令
    4. ENV PATH=$JAVA_HOME/bin:$PATH
    EXPOSE
    指定于外界交互的端口,指容器对外暴露的端口,比如咱们之前执行过运行容器的命令,
    docker run -it -p 9080:8080 tomcat
    其中是将宿主机的9090端口和容器的8080端口绑定到一起了,前提是容器得对外暴露自己的8080端口,否则也绑定不上。
    指令格式:
    EXPOSE

    示例

    EXPOSE 80
    注意:
    EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口。
    VOLUME
    用于指定持久化目录
    指令格式:
    VOLUME ["/path/to/dir"]
    参数是挂载点的地址。
    示例
    1. VOLUME ["/data"]
    2. VOLUME ["/var/www", "/var/log/apache2"]
    注意:
    一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
    1 卷可以容器间共享和重用
    2 容器并不一定要和其它容器共享卷
    3 修改卷后会立即生效
    4 对卷的修改不会对镜像产生影响
    5 卷会一直存在,直到没有任何容器在使用它

    USER

    USER 指令用于将会用以什么样的用户去运行,使用的比较少。
    指令格式:
    1. USER user
    2. USER user:group
    注意:
    使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过 docker run 运行容器时,可以通过-u参数来覆盖所指定的用户。

    ONBUILD

    帮助别人定制而准备的
    指令格式:
    ONBUILD [INSTRUCTION]
    示例
    先创建一个Dockerfile文件
    1. FROM centos
    2. WORKDIR /data
    3. ONBUILD RUN mkdir test

    然后把这个build成镜像,镜像搭建起来之后按理说在会切换到data目录下,且该目录下有test文件夹,但是却没有,因为用ONBUILD修饰了之后,这个Dockerfile形成的镜像文件是用来被别的Dockerfile文件引用的,而不是自己用。就像下面一样,比如我再写另一个Dockerfile文件,我开头可以直接如下写,相当于代码语法里面的继承。

    FROM test:02
    CMD ENTRYPOINT 的区别
    RUN :执行命令并创建新的Image Layer
    CMD :设置容器启动后默认执行的命令和参数
    ENTRYPOINT :设置容器启动时运行的命令

     
    区别:
    • CMD #指定这个容器启动的时候要运行的命令,可被替换
    • ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
    例子
    Dockerfile 文件
    1. #基础镜像
    2. from centos
    3. #启动容器运行命令
    4. CMD ["ls" ,"-a"]
    构建镜像
    docker build -t test04:v1 .

    然后咱们docker run的时候,想执行什么命令可以在最后面添加,如果Dockerfile里用的是CMD的话,那么就是代表替换CMD要执行的命令;如果Dockerfile里用的是ENTRYPOINT 的话,那么就是代表在原来的命令后面追加,比如写个 -l,现在想执行的命令就是ls -al,而如果是CMD方式的话,在docker run语句最后追加一个-l就不对了,因为没有一条命令叫做-l

     

  • 相关阅读:
    C++怎么判断windows系统是64位还是32位
    【用户画像】ClickHouse中的数据类型、表引擎介绍及使用、项目几个问题的解决办法
    Windows 事件日志监控
    ArduinoUNO实战-第二十一章-通过调整电位器来改变9克舵机的角度
    [Games 101] Lecture 10 Geometry 1 (Introduction)
    MySQL进阶实战6,缓存表、视图、计数器表
    14:第二章:架构后端项目:10:封装“返回结果”;(也就是定义API统一返回对象)(同时,使用枚举类统一管理错误信息)
    VUE:组件
    【书生大模型实战】L0-Python
    结构体的基础知识,足够详细
  • 原文地址:https://blog.csdn.net/weixin_44593822/article/details/127359647