docekr学习了解至此,我们都是在使用第三方,也就是远程镜像仓库中的第三方镜像,但是这就会出现一个问题?
问题:镜像是不能修改,只有读的权限,那么在不同的特定环境下,第三方镜像又无法支持我们的需求,这个问题如何解决呢?
所以,就需要我们自定义满足我们需求的镜像,那么我们就必须了解Dockerfile脚本文件

简介

  • Dockerfile构建镜像是以基础镜像为基础的,Dockerfile是一个文本文件,内容是用户编写的一些docker指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
  • Dockerfile就是将自己的程序、文件、环境等构建成自己想要的应用镜像,方便后续部署、启动和维护;通过类似简单编码命令的形式,最终可以构建出属于自己的镜像。

    常用指令分类

    Dockerfile的基本指令有十三个,分别是:FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD
指令类型 命令
基础镜像信息 FROM
维护者信息 MAINTAINER
镜像操作指令 RUN、COP、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令 CMD、ENTRYPOINT

指令详解

1. FROM 指定基础镜像

  • 指定基础镜像 【同时意味着接下来所写的指令将作为镜像的第一层开始】
  • 如果不以任何镜像为基础,那么写法为:FROM scratch

    1. FROM <image>
    2. FROM <image>:<tag>
    3. FROM <image>:<digest>
    4. # <tag>和<digest> 是可选项,如果没有选择,那么默认值为latest
    5. # tag 版本tag标签
    6. # digest

    2.MAINTAINER 维护者信息

  • 指定作者,姓名&邮箱

    1. MAINTAINER <name>

    3. RUN

  • 运行指定的命令[如:执行某些动作、安装系统软件、配置系统信息]

  • RUN是构件容器时就运行的命令以及提交运行结果

run指令运行命令,有两种格式:

  1. 直接跟shell命令
    • linux系统上默认是 /bin/sh -c
    • win系统上默认是cmd /S /C
  2. 类似于函数调用exec
    • 可将executable理解成为可执行文件,后面就是两个参数。
    • RUN [“可执行文件”, “参数1”, “参数2”]

语法:

  1. 1. RUN <command>
  2. 2. RUN ["executable", "param1", "param2"]

示例:

  1. #1. shell 命令格式 向nginx中文首页展示HTML写入‘hello’
  2. RUN echo 'hello ' >/etc/nginx/html/index.html
  3. # 2. exec格式 在新镜像中使用yum的方式安装nginx
  4. RUN ["yum","install","nginx"]

注意:

  1. 多行命令不要写多个RUN,Dockerfile中每一个指令都会建立一层
  2. RUN 指令的行数代表镜像的层数,一个镜像中它的文件层数是有最大值的,而且层数太多增加了构件部署的时间
  3. RUN书写时的换行符是\

    4. CMD

  • 容器启动时要运行的命令
  • CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子

CMD 有三种写法:

  1. # 1. exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
  2. CMD ["executable","param1","param2"]
  3. # 例如:
  4. CMD [ "sh", "-c", "echo $HOME" ]
  5. # 2. exec
  6. CMD ["param1","param2"]
  7. # 例如:
  8. CMD ["/bin/bash"]
  9. # 3. shell格式
  10. CMD command param1 param2
  11. # 例如:
  12. CMD /bin/bash
  13. # 第三种比较好理解了,就时shell这种执行方式和写法
  14. # 第一种和第二种其实都是可执行文件加上参数的形式

注意:

  1. exec格式的情况下,参数必须用双引号【原因:docker解析的是一个JSON array】
  2. CMD在Dockerfile中只能出现一次,如果出现多个,那么只有最后一个会有效,其作用是在启动容器的时候提供一个默认的命令项。如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令,没提供就会使用构建时的命令。

    5. LABEL 标签

  • 为镜像指定标签

语法:

  1. LABEL <key>=<value> <key>=<value> <key>=<value> ...
  2. # Dockerfile种可以有多个LABEL标签
  3. LABEL multi.label1="value1" \
  4. multi.label2="value2" \
  5. other="value3"

注意:

  1. LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

    6. MAINTAINER 作者信息

  • 指定作者和邮箱 ```dockerfile MAINTAINER

例如 :

MAINTAINER autor_yuchang 8888888@qq.com

  1. <a name="d8ba3dd0"></a>
  2. ### 7. EXPOSE **暴露端口**
  3. - 设置容器对外映射的容器端口号
  4. ```dockerfile
  5. EXPOSE <端口1> [<端口2>...]

EXPOSE 8081 其实等价于 docker run -p 8081 当需要把8081端口映射到宿主机中的某个端口(如8888)以便外界访问时,则可以用docker run -p 8888:8081

8. ENV 环境变量

  • 设置环境变量
  • 在容器内被脚本或者程序调用,容器运行的时候这个变量也会保留

语法:

  1. # 单个环境变量
  2. ENV <key> <value>
  3. # 多个环境变量
  4. ENV <key>=<value> ...
  5. # 例如: 设置一个环境变量JAVA_HOME
  6. ENV JAVA_HOME /opt/jdk
  7. ENV PATH $PATH:$JAVA_HOME/bin

注意:

  1. 具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥有当前这个基础镜像所有的环境变量
  2. ENV定义的环境变量,可以在dockerfile被后面的所有指令(CMD除外)中使用,但不能被docker run 的命令参数引用
    1. # 具有传递性
    2. ENV tomcat_home_name tomcat_7
    3. RUN mkdir $tomcat_home_name

    9. ADD 复制

  • 复制命令,把文件复制到镜像中
  • 与COPY指令一样

语法:

  1. # <src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url[<src>写成一个url,那么ADD就类似于wget命令]
  2. # <dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径
  3. ADD <src>... <dest>
  4. ADD ["<src>",... "<dest>"]
  5. # 例如:
  6. ADD test relativeDir/
  7. ADD test /relativeDir
  8. ADD http://example.com/foobar /
  9. # 注意:尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据

10. COPY

  • 复制命令
  • 与add命令相同

语法:

  1. COPY <src>... <dest>
  2. COPY ["<src>",... "<dest>"]

注意:

  1. COPY的<src>只能是本地文件,其他用法一致

    11. ENTRYPOINT

  • 启动时 的默认命令【与CMD有些类似】

语法:

  1. # entrypoint 基本语法分为两种
  2. # 1. 指令后直接跟shell命令
  3. ENTRYPOINT command param1 param2
  4. # 2. 可执行文件加参数
  5. ENTRYPOINT ["executable", "param1", "param2"]

ENTRYPOINT & CMD比较

12. VOLUME

  • 实现挂载功能【将内地文件夹或者其他容器中得文件夹挂在到这个容器中】
  • 数据持久化,容器数据共享

语法:

  1. VOLUME ["/data"]
  2. # ["/data"]可以是一个JsonArray ,也可以是多个值
  3. VOLUME ["/var/log/"]
  4. VOLUME /var/log
  5. VOLUME /var/log /var/db
  6. # 也可以用过docker run -v来把匿名挂载点挂载都宿主机器上的某个目录
  7. docker run -d -v 容器目录:本地目录

13. USER

  • 设置启动容器的用户【可以是用户名或用户uid】

语法:

  1. #注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行
  2. USER daemo
  3. USER UID

14. WORKDIR

  • 设置工作目录【用于目录的切换,如果目录不存在则会直接创建一个新目录】

语法:

  1. # 注意:WORKDIR命令可以有多次出现
  2. WORKDIR /path/to/workdir
  3. # WORKDIR也可以解析环境变量
  4. ENV DIRPATH /path
  5. WORKDIR $DIRPATH/$DIRNAME
  6. RUN pwd
  7. # pwd的执行结果是/path/$DIRNAME

15. ONBUILD

  • 用于配置当前所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令

语法:

  1. ONBUILD [INSTRUCTION]

16. ENV

  • 设置容器的环境变量【key=value的形式存在,在容器内被脚本或者程序调用,容器运行的时候这个变量也会保留】

语法:

  1. # 设置一个参数
  2. ENV <key> <value>
  3. #也可以设置多个参数
  4. ENV <key1>=<value1> <key2>=<value2>...
  5. # 例如:设置一个环境变量JAVA_HOME
  6. ENV JAVA_HOME /opt/jdk
  7. ENV PATH $PATH:$JAVA_HOME/bin

注意:

  1. 具有传递性,也就是当前镜像被用作其它镜像的基础镜像时,新镜像会拥有当前这个基础镜像所有的环境变量
  2. ENV定义的环境变量,可以在dockerfile被后面的所有指令(CMD除外)中使用,但不能被docker run 的命令参数引用
  3. 除了ENV之外,docker run -e 也可以设置环境变量传入容器内。

    17. HEALTHCHECK

  • 容器健康状况检查命令

语法:

  1. # 在容器内部运行一个命令来检查容器的健康状况
  2. HEALTHCHECK [OPTIONS] CMD command
  3. # 在基础镜像中取消健康检查命令
  4. HEALTHCHECK NONE

[OPTIONS]的选项支持以下三中选项:

  • —interval=DURATION 两次检查默认的时间间隔为30秒
  • —timeout=DURATION 健康检查命令运行超时时长,默认30秒
  • —retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3

注意:

  1. HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。
  2. CMD后边的命令的返回值决定了本次健康检查是否成功 ```shell 0: success - 表示容器是健康的

1: unhealthy - 表示容器已经不能工作了

2: reserved - 保留值

例如:

例子:

HEALTHCHECK —interval=5m —timeout=3s \ CMD curl -f http://localhost/ || exit 1

健康检查命令是:curl -f http://localhost/ || exit 1

两次检查的间隔时间是5秒,命令超时时间为3秒

  1. <a name="80d1b54f"></a>
  2. ## Dockerfile的编写和实战
  3. 了解完,dockerfile的基本命令,我们尝试编写一个dockerfile文件
  4. <a name="b3a893dd"></a>
  5. ### 编写dockerfile
  6. 1. 使用idea编写,下载docker插件
  7. ![](https://zhangyu-blog.oss-cn-beijing.aliyuncs.com/img/image-20211124103405250.png#crop=0&crop=0&crop=1&crop=1&id=MLNQj&originHeight=219&originWidth=789&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
  8. ![](https://zhangyu-blog.oss-cn-beijing.aliyuncs.com/img/image-20211124103533853.png#crop=0&crop=0&crop=1&crop=1&id=i0C4V&originHeight=206&originWidth=962&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
  9. 2. 在centos系统上安装一个nginx
  10. ```dockerfile
  11. FROM centos
  12. MAINTAINER test123 123456789@qq.com
  13. RUN ping -c 1 www.baidu.com
  14. RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
  15. ADD nginx-1.18.0.tar.gz /usr/src
  16. RUN cd /usr/src/nginx-1.18.0 \
  17. && mkdir /usr/local/nginx \
  18. && ./configure --prefix=/usr/local/nginx && make &&make install \
  19. && ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ \
  20. && nginx
  21. RUN rm -rf /usr/src/nginx-1.18.0
  22. EXPOSE 80
  23. CMD ["nginx","-g","daemon off;"]

并把已经下载好的nginx包和编写好的dockerfile文件上传到服务器中,在同一文件夹

  1. 用Dockerfile构建镜像

docker build 命令

  1. [root@bogon data]# docker build --help
  2. Usage: docker build [OPTIONS] PATH | URL | -
  3. Build an image from a Dockerfile
  4. Options:
  5. --add-host list Add a custom host-to-IP mapping (host:ip)
  6. --build-arg list Set build-time variables
  7. --cache-from strings Images to consider as cache sources
  8. --cgroup-parent string Optional parent cgroup for the container
  9. --compress Compress the build context using gzip
  10. --cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
  11. --cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
  12. -c, --cpu-shares int CPU shares (relative weight)
  13. --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
  14. --cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
  15. --disable-content-trust Skip image verification (default true)
  16. -f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
  17. --force-rm Always remove intermediate containers
  18. --iidfile string Write the image ID to the file
  19. --isolation string Container isolation technology
  20. --label list Set metadata for an image
  21. -m, --memory bytes Memory limit
  22. --memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
  23. --network string Set the networking mode for the RUN instructions during build (default "default")
  24. --no-cache Do not use cache when building the image
  25. --pull Always attempt to pull a newer version of the image
  26. -q, --quiet Suppress the build output and print image ID on success
  27. --rm Remove intermediate containers after a successful build (default true)
  28. --security-opt strings Security options
  29. --shm-size bytes Size of /dev/shm
  30. -t, --tag list Name and optionally a tag in the 'name:tag' format
  31. --target string Set the target build stage to build.
  32. --ulimit ulimit Ulimit options (default [])
  33. [root@bogon data]#
  34. # 常用的指令
  35. --build-arg=[] # 设置镜像创建时的变量
  36. -f # 指定要使用的dockerfile 的路径【当Dockerfile和当前执行命令的目录不在同一个时,可以指定Dockerfile】
  37. --force-rm # 设置镜像过程中删除中间容器
  38. --rm # 设置镜像成功后删除中间容器
  39. --tag,-t # 镜像的名字及标签,通常name:tag或者name格式

开始构建,执行命令

  1. docker build -t mynginx:1.18.0 .
  2. # -t 镜像的名字及标签
  3. # 最后有一个‘.‘不要忘记,代表当前目录

我们可以看到,执行过程中,根据我们编写的指令,有步骤
Dockerfile自定义镜像 - 图1

  1. 查看并运行自定义镜像

Dockerfile自定义镜像 - 图2
可以看到,通过docker images 命令可以看到我们构建的镜像已经存在于本地
启动镜像:

  1. # 1. 先启动centos
  2. docker run -d -i -t -p 8081:80 30178ab47eaf
  3. # 启动容器,不可以加/bin/bash 会把dockerfilr中的CMD命令覆盖导致无法启动80端口
  4. # 产生问题: docker curl: (56) Recv failure: Connection reset by peer
  5. # 解决:启动命令不可以加/bin/bash参数

Dockerfile自定义镜像 - 图3

提交本地镜像到远程

  1. docker login登录

    1. docker login # 登录远程仓库
  2. 将容器提交为新镜像 ```shell docker commit 容器id\容器名 新的镜像名字:版本

注意:镜像名必须为 xxx/name xxx为你dockerhub上的用户名base为仓库名,不然会后面push会失败

docker commit 5615647e67a1 casainurbania/base:v1.0

  1. 3. 推送到远程仓库
  2. ```shell
  3. docker push casainurbania/base:v1.0

MYSQL5.6案例dockerfile分析

推荐: MYSQL5.6案例dockerfile分析