12

kubernetes(五)之Dockerfile-王辉的博客

 3 years ago
source link: https://blog.51cto.com/13812615/2502283
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Dockerfile

镜像相关的操作

  • 镜像生成的途径
    • Dockerfile
    • 基于容器制作docker commit
      kubernetes(五)之Dockerfile
  • 构建docker镜像的源码
    • docker可以根据Dockerfile中的指令进行镜像的自动构建
    • Dockerfile是一个包含了一个用户可以调用的命令行去组织一个镜像
    • 通过docker build命令可以将一些用户可调用的命令行指令去构建对应的镜像
      kubernetes(五)之Dockerfile

构建Dockerfile的注意事项

  • 必须有一个工作目录放Dockerfile文件与附文件
  • Dockerfile文件名必须是Dockerfile

Dockerfile的格式

  • 包含的信息:
    • 指令: 所有指令一般都是大写;是一个资源清单;没有复杂的判断语法等
  • FROM

    • 是Dockerfile最重要的一个且必须为文件开篇第一个非注释行,用于为镜像文件构建过程中指定基础镜像,后续的指令运行于此基准镜像所提供的运行环境
    • 实践中,基准竟想可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,若本机不存在则去dockerHub拉取
    • 语法:
      • FROM <repository>[:tag]: repostory是镜像仓库名称,tag是镜像的标签,如不指定,默认是latest
      • FROM <repository>@<digist>:digest是镜像的ID(校验码)
  • MAINTAINER

    • 用于指定Dockerfile的维护者信息,目前已经被废弃
    • 出现的位置推荐在FROM的下一行
    • 语法:
  • LABEL

    • 代替MAINTAINER指令,可以定义镜像的额外信息,可以定义多个信息
    • 镜像的元信息(metadata)
    • 语法:
      • LABEL <key>=<value> <key1>=<value1>
  • COPY
    • 用于从docker宿主机拷贝文件到镜像的可写层
    • 拷贝的原路径必须是我们的工作目录
    • 语法:支持多个源地址
      • COPY <src>... <dest>
      • COPY ["<src>",...,"<dest>"]:路径中由空白字符时,使用此格式
    • 注意事项
      • src必须是build上下文中的路径,不能是父路径中的文件
      • 如果src是目录,则其内部的子文件或者子目录会被递归复制,但是src目录自身不会被复制
      • 如果指定了多个src,或者在src后面使用了通配符,则dest必须是一个目录且必须以/结尾
      • 如果dest事先不存在,其将会被自动创建
[root@centos7-node1 ~]# mkdir /data/build_workshop -p
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# echo "<h1>this is a test page</h1>" > index.html
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# vim Dockerfile         
FROM busybox:latest
LABEL maintainer="wanghui<[email protected]>"
COPY index.html /data/web/html/
[root@centos7-node1 build_workshop]# docker build . -t myimg:v0.1
[root@centos7-node1 build_workshop]# docker run --name t1 --rm -it myimg:v0.1 /bin/sh
/ # ls /data/web/html/
index.html
[root@centos7-node1 build_workshop]# mkdir /data/build_workshop/pages/
[root@centos7-node1 build_workshop]# mv /data/build_workshop/index.html /data/build_workshop/pages/
[root@centos7-node1 build_workshop]# echo "<h1>test1 page</h1>" >  /data/build_workshop/pages/test1.html
[root@centos7-node1 build_workshop]# echo "<h1>test2 page</h1>" >  /data/build_workshop/pages/test2.html 
[root@centos7-node1 build_workshop]# vim /data/build_workshop/.dockerignore    #忽略拷贝文件
pages/test2.html
[root@centos7-node1 build_workshop]# vim /data/build_workshop/Dockerfile 
FROM busybox:latest
LABEL maintainer="wanghui<[email protected]>"
COPY pages/*.html /data/web/html/
[root@centos7-node1 build_workshop]# docker build . -t myimg:v0.2
[root@centos7-node1 build_workshop]# docker run --name t1 --rm -it myimg:v0.2 /bin/sh   #验证
/ # ls /data/web/html/
index.html  test1.html
  • ADD
    • ADD类似于COPY指令,ADD支持tar文件和url路径
    • 语法:
      • ADD <src>... <dest>
      • ADD ["<src>","...","<dest>"]
    • 操作准则
      • 同COPY指令
      • 如果src为URL地址且dest不以/结尾,则src指定的文件警备下载并直接创建为dest
      • 如果dest以/结尾,则文件名URL指定的文件会被下载保存为dest/filename
      • 如果src是本地上传的一个压缩格式的tar文件,它将被展开为一个目录,其行为类似与tar -x命令,然而URL获取的他人文件不会被自动展开
      • 如果src有多个,或期间使用了通配符,则dest必须是一个以/结尾的目录路径
      • 如果dest不以/结尾,则被视为一个普通文件,src的内容将被写入到dest
[root@centos7-node1 ~]# mkdir /data/build_workshop/add_example
[root@centos7-node1 ~]# cd /data/build_workshop/add_example
[root@centos7-node1 add_example]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@centos7-node1 add_example]# vim Dockerfile
FROM  busybox:latest
LABEL maintainer="wanghui <[email protected]>"
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /data/
ADD nginx-1.16.1.tar.gz /data/
[root@centos7-node1 add_example]# docker run --name t1 --rm -it myimg:v0.3 /bin/sh
/ # ls /data/
nginx-1.16.1         nginx-1.18.0.tar.gz
  • WORKDIR

    • 用于指定Dockerfile中所有的RUN,CMD,ENTRYPOINT,COPY,ADD指定设定工作目录
      • WORKDIR /var/log
      • WORKDIR $STATEPATH: 可以引用环境变量,结合ENV使用
    • 注意事项: 可以使用多个WORKDIR,最终用最新的WORKDIR
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# cp add_example/ worksdir_example -r  && cd  worksdir_example
[root@centos7-node1 worksdir_example]# vim Dockerfile 
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /data/
FROM  busybox:latest
LABEL maintainer="wanghui <[email protected]>"
WORKDIR  /usr/
ADD nginx-1.16.1.tar.gz src/
[root@centos7-node1 worksdir_example]# docker build . -t myimg:v0.4
[root@centos7-node1 worksdir_example]# docker run --name t1 --rm -it  myimg:v0.4 /bin/sh
/usr # ls src/nginx-1.16.1/ 
  • VOLUME
    • 用于在image中创建一个挂载点目录,以挂载上docker host上的卷或者其他容器上的卷
    • 语法:
      • VOLUME <mountpoint>
      • VOLUME ["<mountpoint>"]
    • 注意:
      • 如果挂载点目录路径下此前文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新的挂载卷中
[root@centos7-node1 build_workshop]# mkdir /data/build_workshop/volumes_example/pages/
[root@centos7-node1 build_workshop]# cd /data/build_workshop/volumes_example
[root@centos7-node1 volumes_example]# echo "<h1>test1 page</h1>" >  /data/build_workshop/volumes_example/pages/test1.html
[root@centos7-node1 volumes_example]# echo "<h1>test2 page</h1>" > /data/build_workshop/volumes_example/pages/test2.html 
[root@centos7-node1 volumes_example]# vim Dockerfile 
FROM busybox:latest
LABEL maintainer="wanghui<[email protected]>"
COPY pages/*.html /data/web/html/
ADD   http://nginx.org/download/nginx-1.15.8.tar.gz /tmp/
WORKDIR /usr/
VOLUME /data/web/html/
[root@centos7-node1 volumes_example]# docker build . -t myimg:v0.5
[root@centos7-node1 volumes_example]# docker run --name t1 -it --rm myimg:v0.5 /bin/sh
/usr # cd /data/web/html/
/data/web/html # ls
index.html  test1.html  test2.html
[root@centos7-node1 ~]# docker inspect -f {{.Mounts}} t1     #另起窗口,找到Source,发现Source映射目录的内容与容器中的一样[随机存储卷]
  • EXPOSE
    • 用于为容器打开制定监听的端口,以实现与外部通信
    • 语法:
      • EXPOSE <port>[/<protocol>] ...: 指定端口和协议
    • 注意事项:
      • EXPOSE 11211/udp 11211/tcp:一次指定多个端口
FROM busybox:latest
LABEL maintainer="wanghui<[email protected]>"
COPY pages/*.html /data/web/html/
ADD   http://nginx.org/download/nginx-1.15.8.tar.gz /tmp/
WORKDIR /usr/
VOLUME /data/web/html/
EXPOSE 80/tcp
[root@centos7-node1 expose_example]# docker build . -t myimg:v0.6
[root@centos7-node1 volumes_example]# docker run --name t1 -it -P --rm myimg:v0.6 /bin/sh
/usr # httpd -f -h /data/web/html/    #启动httpd服务
[root@centos7-node1 expose_example]# docker port t1   #查看映射,然后访问即可
  • ENV
    • 用与定义所需要的环境变量,并可以被Dockerfile文件中位于其后的其他指令(如ENV,ADD,COPY等)所调用
    • 调用格式为 $variable_name${variable_name}
    • 在build阶段使用的
    • 语法:
      • ENV <key> <value>: 一次只能设置一个变量
      • ENV <key>=<value>: 一次可以设置多个变量,特数字答复需要使用\转义[推荐使用]
FROM busybox:latest
ENV webhome="/data/web/html/"
LABEL maintainer="wanghui<[email protected]>"
COPY pages/*.html ${webhome}
ADD http://nginx.org/download/nginx-1.15.8.tar.gz ${webhome}
WORKDIR ${webhome}
ADD nginx-1.16.1.tar.gz ./
VOLUME  ${webhome}
EXPOSE 80/tcp
[root@centos7-node1 env_example]# docker build . -t myimg:v0.7
  • ARG
    • 定义变量,可以在build阶段传值,替换dockerfile中的值
    • 语法:
      • ARG <name>=[default]
    • 注意:
      • 支持docker1.14及其以上的版本
      • 推荐使用ARG
FROM busybox:latest
ARG webhome="/data/web/html/"
LABEL maintainer="wanghui<[email protected]>"
COPY pages/*.html ${webhome}
ADD http://nginx.org/download/nginx-1.15.8.tar.gz ${webhome}
WORKDIR ${webhome}
ADD nginx-1.16.1.tar.gz ./
VOLUME  ${webhome}
EXPOSE 80/tcp
[root@centos7-node1 arg_example]# docker build . -t myimg:v0.8     #正常不加参数的编译,使用的是默认的参数
[root@centos7-node1 arg_example]# docker build --build-arg webhome="/webdata/htdocs/" . -t myimg:v0.8   #加入参数的编译
[root@centos7-node1 arg_example]# docker run --name t1 -it --rm myimg:v0.8 /bin/sh   #结果测试
  • RUN
    • 用于指定docker build过程中运行程序,其可以是任何命令
    • 语法:
      • RUN <command>:command通常是一个shell命令,且以/bin/sh -c来运行它, 这意味着此进程在容器中的PID不为1,不能接受Unix信号,因此,当使用docker stop <container>停止容器时,此进程接收不到SIGTERM信号
      • RUN ["<executable>","param1","param2"]:参数是一个json格式的数组,其中excutable是要运行的命令,后面的param是要传递给命令的选项或者参数,然而此种格式的参数不会以/bin/sh -c来发起,因此常见的shell操作,如变量替换以及通配符操作将不会进行,不过,如果要运行依赖此shell特性的话,可以将其替换成如下的格式: RUN ["bin/sh","-c","<executable>","<param1>"]
    • 注意: 执行的命令必须是FROM拉取镜像中可以执行的;
FROM busybox:latest
ARG webhome="/data/web/html/"
LABEL maintainer="wanghui<[email protected]>"
COPY pages/*.html ${webhome}
ADD http://nginx.org/download/nginx-1.15.8.tar.gz ${webhome}
WORKDIR ${webhome}
ADD nginx-1.16.1.tar.gz ./
VOLUME  ${webhome}
EXPOSE 80/tcp
RUN  mkdir -p /web/bbs && \
     ["/bin/sh","-c","echo helle >> /web/bbs/index.html"]
[root@centos7-node1 run_example]# docker build . -t myimg:v0.9
FROM centos:7
LABEL maintainer="wanghui <[email protected]>"
ARG  docroot=/var/www/html/
RUN yum makecache && \
    yum -y install httpd php php-mysql && \
    yum clean all && \
    rm -fr /var/cache/yum/*
[root@centos7-node1 ap]# docker run --name web1 --rm -it php-httpd:v0.1 bash
  • CMD
    • 运行在docker run阶段,用于容器中运行命令或者应用程序
      • RUN指令运行于镜像的构建过程中,而CMD的运行是基于Dockerfile构建出的新镜像文件启动一个容器时
      • CMD指令首要目的在于为溶洞的容器指定默认要运行的程序,且其运行结束后容器也将终止,不过,CMD指令的命令可以被docker run的命令行所覆盖
      • 在Dockerfile中可以存在多个CMD命令,但仅最后一个生效
    • 语法:
      • CMD <command>
      • CMD ["<executable>","param1","param2"]
      • CMD ["param1","param2"]: 用于为ENTRYPOINT提供默认参数
FROM centos:7
LABEL maintainer="wanghui <[email protected]>"
ARG  docroot=/var/www/html/
RUN yum makecache && \
    yum -y install httpd php php-mysql && \
    yum clean all && \
    rm -fr /var/cache/yum/*
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
[root@centos7-node1 ap]# docker build . -t php-httpd:v0.2
[root@centos7-node1 ap]# docker run --name web1 --rm  php-httpd:v0.2 
[root@centos7-node1 ap]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@centos7-node1 ap]# docker run --name web1 -it php-httpd:v0.2 /bin/bash
[root@47818a3ba906 /]# ps -ef    #httpd被覆盖了
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  1 09:41 pts/0    00:00:00 /bin/bash
  • ENTRYPOINT
    • 类似CMD指令的功能,用于为容器指定默认的运行程序,从而使容器像是一个独立的可执行程序
      • 与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令指定的参数所覆盖,而且这些命令行参数被当做传递给ENTRYPOINT指定的程序
      • 不过,docker run命令的--entrypoint选项参数可以覆盖ENTRYPOINT指定的程序
    • 语法:
      • ENTRYPOINT <command>
      • ENTRYPOINT ["<executable>","param1","param2"]
    • 注意事项
      • docker run 命令传入的参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令的最后作为其参数使用
      • Dockerfile存在多个ENTRYPOINT指令,但仅有最后一个会生效
[root@centos7-node1 ap]# tree ./
./
├── Dockerfile
├── entrypoint.sh
├── ok.html
└── phpinfo.php
[root@centos7-node1 ap]# cat Dockerfile 
FROM centos:7
LABEL maintainer="wanghui <[email protected]>"
ARG  docroot=/var/www/html/
RUN yum makecache && \
    yum -y install curl httpd php php-mysql && \
    yum clean all && \
    rm -fr /var/cache/yum/*
ADD ok.html phpinfo.php ${docroot}
ADD entrypoint.sh /bin/
EXPOSE 80/tcp
VOLUME ${docroot}
HEALTHCHECK --interval=3s --timeout=3s --start-period=2s CMD curl -f http://localhost/ok.html || exit 1
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
ENTRYPOINT ["/bin/entrypoint.sh"]
[root@centos7-node1 ap]# cat entrypoint.sh 
#!/bin/bash
listen_port=${LISTEN_PORT:-80}
server_name=${SERVER_NAME:-localhost}
doc_root=${DOC_ROOT:-/var/www/html/}
cat > /etc/httpd/conf.d/myweb.conf <<EOF
#LISTEN $listen_port
<VirtualHost *:${listen_port}>
    ServerName  "$server_name"
    DocumentRoot  "$doc_root"
    <Directory "$doc_root">
       Options  none
       AllowOverride none
       Require all granted
    </Directory>
</VirtualHost>
EOF
exec "$@"
Dockerfile  entrypoint.sh  ok.html  phpinfo.php
[root@centos7-node1 ap]# cat ok.html 
OK
[root@centos7-node1 ap]# cat phpinfo.php 
<?php
  phpinfo();
?>
    • 用于指定image运行时任何RUN,CMD,ENTRYPOINT指令指定程序运行的用户名或者UID
    • 默认情况下USER是root
    • 语法:
      USAER <uid>|username
      • 用户必须是存在与/etc/passwd中的有效用户,否则容器会运行失败
  • HEALTHCHECK

    • 检测容器是否正常运行
    • 语法:
      • HEALTHCHECK CMD command:检查容器内的服务是否运行正常
      • HEALTHCHECK none:不需要健康检查
    • 注意事项:
      --interval : 检查周期,默认30s
      --timeout:等待超时,默认30s
      --start-period: 开始检测的时间,默认是0s
      --retries:重试次数
  • ONBUILD
    • 用于在Dockerfile中定义触发器,延迟运行
      • Dockerfile用于build镜像文件,此镜像文件也也可以作为base image被另外的一个Dockerfile用作FROM指令参数,并以次构建新的镜像
        • 在后面的Dockerfile中的FROM指令在build过程中被执行时,会触发创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器
    • 语法:
      • ONBUILD <INSTRUCTION>
    • 注意事项
      • 尽管任何指令都可以注册成为触发器指令,但是ONBUILD不能自我嵌套,且不会出发FROM和MAINTAINER指令
      • 在ONBUILD指令中使用ADD和COPY要格外小心,因为新构建过程中的上下文在缺少指定的原文件时会失败
[root@centos7-node1 ~]# cd /data/build_workshop/
[root@centos7-node1 build_workshop]# mkdir testimg/ myicme/ -p
[root@centos7-node1 build_workshop]# vim testimg/Dockerfile 
FROM busybox:latest
LABEL maintainer="wanghui <[email protected]>"
RUN mkdir -p /data/web/html
ONBUILD ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/src
[root@centos7-node1 build_workshop]# docker build ./testimg/  -t testimg:v0.1   # 构建testing:v0.1
[root@centos7-node1 build_workshop]# vim myicme/Dockerfile
FROM  testimg:v0.1
LABEL from="testimg:v0.1
[root@centos7-node1 build_workshop]# docker build ./myicme/ -t myicme:v0.1   #此时构建才会执行下载testing:v0.1
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM  testimg:v0.1
# Executing 1 build trigger
Downloading [==>                                                ]  47.73kB/1.04MB
  • 镜像临时导入导出
[root@centos7-node1 ~]# docker image save php-httpd:v0.6 -o php-httpd.tar   #导出镜像
[root@centos7-node1 ~]# docker image load -i php-httpd.tar     # 导入镜像
[root@centos7-node1 ~]# docker history php-httpd:v0.6   #构建历史查看

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK