zoukankan      html  css  js  c++  java
  • dockerfile和资源限制(五)

    镜像生成途径

    • dockerfile
    • 基于容器制作

    什么是dockerfile

     dockerfile说白就是用来构建docker 镜像的源码,大家看到源码俩字不用惊慌,所为的dockerfile源码只是一些基础的指令并没有控制语句或条件判断等,仅仅是一些文本指令

    dockerfile语法格式其实只有两类语法格式:

    1. 注释信息
    2. 指令和参数

    注意:

    1. 默认dockerfile中的语法虽然不区分大小写,但是约定俗成一律用大写
    2. dockerfile在执行时,是自上而下去执行的
    3. dockerfile第一个非注释行必须是FROM指令,用来指定基础镜像

    FROM指令

    • FROM指令是最重的一个且必须为Dockerfile文件开篇的第一行非注释,用于为镜像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境
    • 实践中,基准镜像可以使任何可用的镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件
    • 如果找不到指定的镜像文件,docker build会返回一个错误信息

    MAINTAINER指令

    • 用于让Dockerfile制作者提供本人的详细信息
    • Dockerfile并不限制MAINTAINER指令出现在哪,但推荐将其放置于FROM之后
    • 语法格式为
      •   MAINTAINER<authro's detail>
      •   <author's detail>可是任何文本信息,但约定俗成地使用作者名称和邮件地址
      •   MAINTAINER "liwang<liwang@126.com>"

     COPY指令

    如果仅仅是把本地的文件拷贝到容器镜像中,COPY 命令是最合适不过的。其命令的格式为:

    语法规则:

    • COPY <src> <dest>
    • COPY ["<src>",....,"<dest>"]
      • <src>:要复制的源文件或目录,支持使用通配符
      • <dest>:目标路径,建议使用绝对路径
    • note:在文件中如果有空格,通常使用第二种格式

    复制法则:

    • 复制目标目录如果不存在会自动创建
    • 如果复制的是目录,那么dest必须要跟目录名称,而且必须以/结尾

    ADD指令

    ADD指令和COPY命令很类似,不同之处在于:

    • ADD指令可以将本地tar包在注入镜像后进行解压缩,如果是URL路径那么只能是将tar包打包进镜像而不会展开

    WORKDIR指令

     用于为Dockerfile中所有的RUN,CMD,ENTRYPOINT,COPY,ADD指定设定工作目录

    语法格式为:

    WORKDIR <dirpath>

    VOLUME指令

    用于在image中创建一个挂载点目录,以挂载docker上的卷或者其他容器上的卷

    语法格式为:

    • VOLUME <mountpoint>
    • VOLUME [<mountpoint>]

    如果挂载点目录路径下此前存在,docker run命令会在卷挂载完成以后将此前的所有文件复制到新挂载的卷中

    EXPOSE指令 

    • 用于为容器打开指定要监听的端口以实现与外部通信
    • 语法格式:
      • EXPOSE <port>/<protocol> <port>/<protocol> <port>/<protocol>
    • 一次可以指定多个暴露的端口
      • EXPOSE 80/tcp 11211/udp

     ENV指令

    用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如:ENV,ADD,COPY等)所调用

    调用格式为$variable_name或${variable_name}

    语法格式为:

    • ENV <key>:<value>
    • ENV <key>=<value>
    • 第一种格式中,<key>之后的所有内容均被视作<value>的组成部分,因此,一次只能设置一个变量
    • 第二种格式中,可以一次设置多个变量,每一个变量为一个“<key>=<value>”键值对,如果<value>包含空格,可以以反斜线进行转义,也可以通过对<value>加引号进行标识,进行续航
    • 定义多个变量时,建议使用第二种方式

    RUN指令和CMD指令

    RUN和CMD可以执行指定的shell命令;

    区别:

    1. 运行的时间段不同;
    2. CMD可以有多个,但是只有最后一个CMD有效;
    3. RUN可以有多个,并且都可以生效

    RUN指令主要是dockerfile创建为镜像时要执行的任务,而CMD主要作用在于创建为容器时指定默认要运行的程序,不过,CMD可以被docker run的命令行选项所覆盖

    如下图所示:

     CMD 语法格式

    • CMD <command> 或
    • CMD ["<excutable>","<param1>","<param2>"]
    • CMD["<param1>","<param2>"]

    前两种语法格式与RUN意义相同

    第三种语法格式主要用于为ENTRYPOINT指令提供默认参数

    ENTRYPOINT指令

    ENTRYPOINT指令和CMD指令很像,只不过ENTRYPOINT不能被覆盖(除非指定特殊选项),并且CMD命令会当做参数传递给ENTRYPOINT

    使用ENTRYPOINT的意义在于我们可以给我们的应用配置文件制作一个配置文件模板,这样,我们就可以在容器外部注入变量生成新的配置文件

    以nginx:1.14-alpine为例子,我们可以基于一个配置文件模板生成不同端口号的nginx,以下为例子:

    Dockerfile文件内容

    FROM nginx:1.14-alpine
    LABEL maintainer="liwang<liwang@163.com>"
    ENV HTML=/data/html/
    ADD index.html ${HTML}
    ADD entrypoint.sh /bin/
    CMD ["/usr/sbin/nginx","-g","daemon off;"]
    ENTRYPOINT ["/bin/entrypoint.sh"]

    entrypoint.sh脚本文件内容如下:

    cat > /etc/nginx/conf.d/www.conf <<EOF
    server {
        server_name $HOSTNAME;
        listen ${PORT:-80};
        root ${HTML:-/usr/share/nginx/html};
    }
    EOF
    
    exec "$@"

    Dockerfile目录的文件结构如下:

    [root@bogon Dockerfile]# ls
    Dockerfile  entrypoint.sh  index.html

    生成镜像

    [root@bogon Dockerfile]# docker build -t mynginx ./

    这时候我们运行容器的时候就可以在容器外部给予变量生成不同的nginx配置文件,如下:

    我们想生成1000端口的nginx那么可以如下:

    [root@bogon Dockerfile]# docker run --name myweb1 -itd -e "PORT=1000" mynginx
    539896dad037ea6f3e804a281b46cce5eec21c96bcd331d0dc6ed8da1653c540
    [root@bogon Dockerfile]# docker exec -it myweb1 /bin/sh
    / # netstat -tnpl
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/nginx -g daemon o
    tcp        0      0 0.0.0.0:1000            0.0.0.0:*               LISTEN      1/nginx -g daemon o
    / # hostname
    539896dad037
    / # wget -O - -q 539896dad037:1000
    this is httpd box

    我们想生成2000端口的nginx那么可以如下:

    [root@bogon Dockerfile]# docker run --name myweb2 -itd -e "PORT=2000" mynginx  
    ce9b85e9a77b761bb832e2b29582093dd53bbcb9120bbf30fd4b69850874bc1a
    [root@bogon Dockerfile]# docker exec -it myweb2 /bin/sh                      / # netstat -tnpl
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 0.0.0.0:2000            0.0.0.0:*               LISTEN      1/nginx -g daemon o
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/nginx -g daemon o

    USER指令

    • 用于指定运行image时或Dockerfile中任何RUN,CMD,或ENTRYPOINT指令指定的程序时用户名或UID
    • 默认情况下container运行的用户为root
    • 语法格式
      • USER <UID> |<USERNAME>
      • 这里要注意的是UID可以是任意数字,但实践中必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败

    HEALTHCHECK指令

    有时候我们判断一个容器是否正常不能单一的只看容器当中的进程是否存在,比如,我们运行一个nginx,但是我们的document_root指错了,容器的进程一样会执行,但是这个服务已经不能够按照用户的需求正常访问了,因此我们用HEALTHCHECK去探测我们的服务是否正常

    语法格式:

    HEALTHCHECK [OPTIONS] CMD command 

    options选项有:

    • --interval=#(默认30s)
    • --timeout=#(默认30s)
    • --start-period=#(默认0秒)
    • --retries=#(默认为3次)

    检测command指令发出后返回值有3种:

    • 0:健康
    • 1:不健康
    • 2:预留的,用户可以根据2返回值来做操作

    for example:

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

    案例:

    dockerfile如下:

    [root@jiaqi211 dockerfile]# cat Dockerfile 
    FROM busybox:latest
    MAINTAINER "liwang<liwang@126.com>"
    HEALTHCHECK --start-period=3s CMD wget -O - -q http://0.0.0.0:80 || exit 1
    RUN mkdir -p /data/web/html/; 
        cd /data/web/html && echo "welcome to busybox" > index.html
    CMD ["-f","-h","/data/web/html/"]
    ENTRYPOINT ["/bin/httpd"]
    EXPOSE 80 

    等待片刻如下:

    [root@jiaqi211 dockerfile]# docker ps 
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS                NAMES
    d4837b1dc5a9        busyweb             "/bin/httpd -f -h /d…"   2 minutes ago       Up 2 minutes (healthy)   0.0.0.0:80->80/tcp   myweb1

    如果我们把红色字体中80端口改成一个不通的端口比如10080,结果如下:

    [root@jiaqi211 dockerfile]# docker ps 
    CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                          PORTS                   NAMES
    bbaa030c1560        busyweb             "/bin/httpd -f -h /d…"   About a minute ago   Up About a minute (unhealthy)   0.0.0.0:32775->80/tcp   myweb1

    SHELL指令

    在shell中默认一般使用["/bin/sh","-c"],我们可以修改默认的shell

    语法格式如下:

    • SHELL ["excutable","parameters"]

    不过改的情况不多见

    ARG指令

    ARG指令可以在docker build时传变量,而ENV是在docker run时给予变量

    ARG用法如下:

    [root@jiaqi211 dockerfile]# vim Dockerfile 
    FROM busybox:latest
    ARG author="liwang<liwang@126.com>"
    LABEL maintainer="${author}"
    HEALTHCHECK --start-period=3s CMD wget -O - -q http://0.0.0.0:10080 || exit 1
    RUN mkdir -p /data/web/html/; 
        cd /data/web/html && echo "welcome to busybox" > index.html
    CMD ["-f","-h","/data/web/html/"]
    ENTRYPOINT ["/bin/httpd"]
    EXPOSE 80

    验证1:如果不传变量会用已经定义好的变量传入

    [root@jiaqi211 dockerfile]# docker build -t myweb1 ./
    [root@jiaqi211 dockerfile]# docker inspect myweb1
    .....
    "Labels": {
                    "maintainer": "liwang<liwang@126.com>"
                }
    .....

    验证2:如果传入变量会按照用户传入的变量传入

    [root@jiaqi211 dockerfile]# docker build -t myweb1 --build-arg author="fengzi<fengzi@126.com>" ./
    [root@jiaqi211 dockerfile]# docker inspect myweb1
    .....
    "Labels": {
                    "maintainer": "fengzi<fengzi@126.com>"
                }
    .....

    ONBUILD

    • 用于在Dockerfile中定义一个触发器
    • Dockerfile用于build映像文件,此映像文件可以被作为基础映像被另一个Dockerfile用做FROM指令参数,并构建新的映像文件,在后面docker build时会被触发
    • ONBUILD不能触发FROM 和 MAINTAINER指令

    语法格式:

    • ONBUILD <INSTRUCTION>

    示例

    镜像目录的文件如下:

    [root@localhost ~]# tree dockerfile/
    dockerfile/
    ├── Dockerfile
    ├── index.html
    └── nginx-1.16.1.tar.gz

    Dockerfile文件内容如下:

    [root@localhost dockerfile]# cat Dockerfile 
    FROM busybox:latest
    MAINTAINER "liwang<liwang@126.com>"
    WORKDIR /etc/
    ENV DOCUMENT_ROOT="/data/web/html"
    EXPOSE 80/tcp
    ADD http://nginx.org/download/nginx-1.16.1.tar.gz /etc
    RUN cd /etc/ && tar -zxvf nginx-1.16.1.tar.gz -C /tmp
    RUN mkdir -p ${DOCUMENT_ROOT}
    ADD index.html ${DOCUMENT_ROOT}
    VOLUME ${DOCUMENT_ROOT}
    CMD httpd -f -h ${DOCUMENT_ROOT}

    运行Dockerfile命令如下:

    [root@localhost dockerfile]# docker build -t myhttpd ./
    Sending build context to Docker daemon  1.036MB
    Step 1/11 : FROM busybox:latest
     ---> 020584afccce
    Step 2/11 : MAINTAINER "liwang<liwang@126.com>"
     ---> Using cache
     ---> 3537a5a13f27
    Step 3/11 : WORKDIR /etc/
     ---> Running in 6ffe9c85b719
    Removing intermediate container 6ffe9c85b719
     ---> 434913bba9b0
    Step 4/11 : ENV DOCUMENT_ROOT="/data/web/html"
     ---> Running in 04e7e3bae01a
    Removing intermediate container 04e7e3bae01a
     ---> cc03fd190474
    Step 5/11 : EXPOSE 80/tcp
     ---> Running in 44adb435af97
    Removing intermediate container 44adb435af97
     ---> 54d69d81360d
    Step 6/11 : ADD http://nginx.org/download/nginx-1.16.1.tar.gz /etc
    Downloading [==================================================>]  1.033MB/1.033MB
     ---> e3bf4b5c993e
    Step 7/11 : RUN cd /etc/ && tar -zxvf nginx-1.16.1.tar.gz -C /tmp
     ---> Running in a00836e16083
    nginx-1.16.1/
    nginx-1.16.1/auto/
    nginx-1.16.1/conf/
    nginx-1.16.1/contrib/
    nginx-1.16.1/src/
    nginx-1.16.1/configure
    .......
    Removing intermediate container a00836e16083
     ---> effc55a2bd3a
    Step 8/11 : RUN mkdir -p ${DOCUMENT_ROOT}
     ---> Running in 911d5b78d827
    Removing intermediate container 911d5b78d827
     ---> c78b410fc588
    Step 9/11 : ADD index.html ${DOCUMENT_ROOT}
     ---> fb7e61c9e4fe
    Step 10/11 : VOLUME ${DOCUMENT_ROOT}
     ---> Running in d38bccb71ddc
    Removing intermediate container d38bccb71ddc
     ---> 2ace0d71de1f
    Step 11/11 : CMD httpd -f -h ${DOCUMENT_ROOT}
     ---> Running in 07b43b1c3162
    Removing intermediate container 07b43b1c3162
     ---> 42006762e446
    Successfully built 42006762e446
    Successfully tagged myhttpd:latest

    资源限制

    启动memory压力测试镜像,给与容器分配最多占用256m内存-m 256m,并且在容器内部启用2个子进程--vm 2,并且每个子进程所占用的内存资源时50m
    [root@localhost yum.repos.d]# docker run --name stress -it -m 256m --rm lorel/docker-stress-ng:latest stress --vm 2 --vm-bytes 50m
    [root@localhost yum.repos.d]# docker stats
    CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
    712765609df2        stress              200.38%             103.1MiB / 256MiB   40.28%              656B / 0B           0B / 0B             5
    
    
    启用cpu压力测试,给与容器分配最多占用4个cpu,并且在容器内部启动8个子进程来对cpu做压测
    [root@localhost yum.repos.d]# docker run --name stress -it -m 256m --cpus 4 --rm lorel/docker-stress-ng:latest stress --vm 2 --vm-bytes 50m --cpu 8 
    CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
    2bf33001b07c        myos                0.00%               56KiB / 1.777GiB    0.00%               656B / 0B           0B / 0B             1
    8d0912451e7f        stress              400.98%             125.3MiB / 256MiB   48.93%              516B / 0B           0B / 0B    
    
    
    启动cpu压力测试,并且限制只能在0和2号cpu上运行
    [root@localhost yum.repos.d]# docker run --name stress -it --cpuset-cpus 0,2 --rm lorel/docker-stress-ng:latest stress --cpu 8 
    
    
    
    启动cpu共享压力测试,2个容器共享cpu资源
    [root@localhost yum.repos.d]# docker run --name stress -it --cpu-shares 512 --rm lorel/docker-stress-ng:latest stress --cpu 8 
    [root@localhost yum.repos.d]# docker run --name stress -it --cpu-shares 256 --rm lorel/docker-stress-ng:latest stress --cpu 8 
    [root@localhost yum.repos.d]# docker stats
    CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    c5ae34837074        stress              253.22%             15.81MiB / 1.777GiB   0.87%               656B / 0B           0B / 0B             9
    207bcffb19dc        stress2             125.53%             15.81MiB / 1.777GiB   0.87%               656B / 0B           0B / 0B        
  • 相关阅读:
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    64位WIN7系统 下 搭建Android开发环境
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
  • 原文地址:https://www.cnblogs.com/fengzi7314/p/11936871.html
Copyright © 2011-2022 走看看