• Dockfile制作镜像


    讲一个简单的案例

    @哈希码用来校验,这样子会安全

    MAINTANIER可能将会被LABEL代替,仅仅说说明一下镜像信息罢了。

    1、首先是我们创建一个镜像

    [root@ELK-chaofeng08 ~]# mkdir /docker
    [root@ELK-chaofeng08 ~]# cd /docker
    [root@ELK-chaofeng08 docker]# vim Dockerfile

    输入以下内容:

    #Description: httpd image
    FROM busybox:latest
    MAINTAINER      "ChaoFeng <chaofeng@qq.com>"
    COPY index.html /data/web/html

    正文的第一行必须是FROM开头。#号表示注释。

    CPOY命令是复制一个文件,index.html这个文件必须与Dockerfile这个文件同级存放或者在子目录下也可以。

    不过我在这里踩坑了,因为我的COPY那一行写错了。

    正确的是:

    2、接下来我们创建index.html

    [root@ELK-chaofeng08 docker]# echo "How are you" > index.html
    [root@ELK-chaofeng08 docker]# cat index.html 
    How are you
    [root@ELK-chaofeng08 docker]# ls
    Dockerfile  index.html

    3、然后创建目标目录

    [root@ELK-chaofeng08 docker]# mkdir -pv /data/web/html
    mkdir: created directory ‘/data/web’
    mkdir: created directory ‘/data/web/html’

    4、开始制作镜像。

    制作的时候最好加上标签

    5、查看一下我们制作的新镜像

    6、启动一下看看。

    这个指令的用法是最常见的。

    [root@ELK-chaofeng08 docker]# docker run --name tinyweb1 --rm tinyhttpd:v0.1.1 cat /data/web/html/index.html
    How are you
    [root@ELK-chaofeng08 docker]# 

    后面的cat指令是EXEC的指令,也就是说我们一启动容器后不运行默认的命令,而是运行我们指定的cat命令,运行完毕后退出容器,我还设置了--rm参数,表示容器停止后就删除它。要学会这个用法

    看的出来我们成功了。

    二、如何复制一个目录呢?

    比如现在我们想把物理机下的/etc/yum.repos.d目录下的所有文件复制到容器内的/etc/yum.repos.d/的目录下

    1、先把物理机下的/etc/yum.repos.d这个目录复制到Dockerfile同级的目录下(子目录下也行)

    [root@ELK-chaofeng08 docker]# cp -r /etc/yum.repos.d ./
    [root@ELK-chaofeng08 docker]# ls
    Dockerfile  index.html  yum.repos.d

    2、编辑Dockerfile文件

    COPY可以用多个。COPY命令的用法原则是能用一条来代替就不要用多条,因为每一个COPY命令就会生成一个镜像层。层越多,联合挂载效率越低。

     3、开始制作

    4、查看一下新的镜像

    5、查看一下新的镜像下是否有新的文件

    说明成功了。

    三、ADD命令的用法,

    1、编辑Dockerfile文件

    2、制作新的镜像

    3、查看新的镜像

    4、查看新的镜像下的nginx的tar包

    成功了。

    四、ADD命令的解压功能。

    ADD命令不仅可以从互联网下载文件(压缩文件,普通文件等)并放入新的镜像内,还可以根据压缩文件的类型选择算法实现解压操作,如下所示:

    1、首先是压缩文件必须是放在本地才可以。

    我们以phpmyadmin文件为例

    2、编辑Dockerfile文件

    3、开始制作镜像

    4、查看新的镜像下的phpmyadmin的展开文件

    成功。

    注意:ADD命令可以从指定的URL向互联网下载各种类型的文件到新镜像,也可以将一个压缩文件解压放入新的镜像,但是不能同时既进行下载tar压缩文件又进行压缩tar文件到新镜像里面。

     五、指定WORKDIR目录路径

     

     六、指定存储卷

    不过只能指定docker自己管理的卷,不能指定我们绑定的外部卷的存储路径

    比如:

    七、暴露端口给外部的宿主机

    相当于自动帮我们生成一个DNAT端口。跟以前的-p参数一样的功能。

    不过用法也比较限制,只能动态绑定宿主机的动态端口到容器的固定端口。不能绑定指定宿主的ip和指定的端口。但是这有时候也是一种安全的机制。

    案例:

    因为第一次我们编辑了一个index.html文件,在/data/web/html目录下存放这,我们直接使用这个文件,。

    1、编辑dockerfile文件

    2、重新制作新的镜像

    3、查看这个新镜像

    4、启动这个新镜像

    5、我们去查看这个容器的ip

    6、访问一下这个容器的80端口

    非常好。成功

    像这种在配置文件中暴露的端口在外部是看不到的,这是半暴露状态,如果想要全部暴露,加上-P参数。比如:

    所以我们可以加上-P参数指定为暴露端口给外部

    7、加上-P参数

    8、再来查看一下

    我们就可以在外部访问了

    八、ENV和RUN命令解释,

    RUN命令是Dockerfile文件中的一个可以执行命令的参数,比如:

    1、编辑dockerfile文件

    2、制作新镜像

     

    3、启动新镜像查看

    成功了。

    在Dockerfile中定义的环境变量是可以用在容器启动以后引用的变量

     

    注意:RUN命令是可以运行多次的。后面的命令可以使用“”表示续行。所有的RUN操作是基于基础镜像的,因此要注意环境。

     九、CMD和ENTRYPOINT

      注意:json数组要使用双引号。

    ENTRYPOINT
    
    两种格式:
    
    ENTRYPOINT ["executable", "param1", "param2"]
    
    ENTRYPOINT command param1 param2 (shell中执行)
    配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。
    
    CMD
    
    支持三种格式
    
    CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
    CMD command param1 param2 在 /bin/bash 中执行,提供给需要交互的应用;
    CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数;
    指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

    ENTRYPOINT 和 CMD 的区别:ENTRYPOINT 指定了该镜像启动时的入口,CMD则指定了容器启动时的命令,当两者共用时,完整的启动命令像是 ENTRYPOINT + CMD 这样。使用 ENTRYPOINT 的好处是在我们启动镜像就像是启动了一个可执行程序,在 CMD 上仅需要指定参数;另外在我们需要自定义 CMD 时不容易出错。

    使用 CMD 的 Dockerfile:

    [root@sta2 test]# cat Dockerfile 
    FROM mysql
    CMD ["echo","test"]

    使用 ENTRYPOINT 的 Dockerfile:

    [root@sta2 entrypoint]#  cat  Dockerfile 
    FROM mysql
    ENTRYPOINT ["echo","test"]

    结论:ENTRYPOINT 不能覆盖掉执行时的参数,CMD 可以掉覆盖默认的参数。

    可以使用以下命令覆盖默认的参数,方便调试 Dockerfile 中的 bug:
    [root@sta2 entrypoint]# docker run -it --entrypoint=/bin/bash feiyu/entrypoint:1

    案例演示:

    制作一个nginx(重点掌握)

    1、先制作Dockerfile文件

    FROM nginx:1.14-alpine
    LABEL maintainer="Chaofeng <chaofeng@chaofeng.com>"

    ENV NGX_DOC_ROOT='/data/web/html/'

    ADD entrypoint.sh /bin/

    CMD ["/usr/sbin/nginx","-g","daemon off;"]

    ENTRYPOINT ["/bin/entrypoint.sh"]

    2、制作entrypoint.sh文件

    #!/bin/sh
    
    cat > /etc/nginx/conf.d/www.conf << EOF
    server{
            server_name ${HOSTNAME};
            listen ${IP:-0.0.0.0}:${PORT:-80};
            root ${NGX_DOC_ROOT:-/usr/share/nginx/html};
    }
    EOF
    
    exec "$@"

    3、给entrypoint.sh文件授权

    chmod +x entrypoint.sh

    4、制作docker镜像

    [root@ELK-chaofeng08 docker3]# docker build -t tinyweb:v0.3.2 ./
    Sending build context to Docker daemon  3.072kB
    Step 1/6 : FROM nginx:1.14-alpine
     ---> 66952fd0a8ef
    Step 2/6 : LABEL maintainer="Chaofeng <chaofeng@chaofeng.com>"
     ---> Using cache
     ---> 9b06b920ce9b
    Step 3/6 : ENV NGX_DOC_ROOT='/data/web/html/'
     ---> Using cache
     ---> 9346cf0174b9
    Step 4/6 : ADD entrypoint.sh /bin/
     ---> c8f80cdc1321
    Step 5/6 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
     ---> Running in 20bace9c162d
    Removing intermediate container 20bace9c162d
     ---> 4cbfa737e80f
    Step 6/6 : ENTRYPOINT ["/bin/entrypoint.sh"]
     ---> Running in babe021b35b9
    Removing intermediate container babe021b35b9
     ---> b474e7c54539
    Successfully built b474e7c54539
    Successfully tagged tinyweb:v0.3.2

    5、启动镜像

    [root@ELK-chaofeng08 docker3]# docker run --name tinyweb1 --rm -P tinyweb:v0.3.2

    6、在另一终端查看进程

    [root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh
    / # ps
    PID   USER     TIME  COMMAND
        1 root      0:00 nginx: master process /usr/sbin/nginx -g daemon off;
        8 nginx     0:00 nginx: worker process
        9 root      0:00 /bin/sh
       14 root      0:00 ps

    我们在Dockerfile文件中使用脚本的方式进行传值,我们执行ENTRYPOINT的时候使用的是数组的形式,意思就是把CMD的元素当作是一个个的参数传给ENTRYPOINT,首先是在创建完entrypoint.sh脚本的时候,执行最后一句exec操作,这是把当前nginx的进程作为主进程来执行,因此在这里的ps命令中看到nginx的主进程的PID号是1。

    我们设计成脚本的方式是比较好传值的,省去了修改某个参数时重新制作镜像的麻烦,为什么这么说呢?比如下面这个例子:

    [root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh
    / # netstat -tnl
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN    

    此时正好是运行在80端口。

    假如此时我想运行在8080端口怎么办呢?可以这样子来

    [root@ELK-chaofeng08 docker3]# docker run --name tinyweb1 --rm -P -e 'PORT=8080' tinyweb:v0.3.2

    使用-e参数,表示启动容器的时候使用作为环境变量传入

    再打开一个终端执行如下:

    [root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh
    / # netstat -tnl
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      

    不仅运行在了默认的80端口,还运行在了8080端口,非常的方便。这就是脚本传值的作用。这里还要理解entrypoint.sh有个“${PORT:-80}”是什么意思呢?就是如果环境中有默认的PORT的值,那么此时PORT就有值然后就使用默认的值,如果没有值,则使用80端口。那么至于为什么上面还会有80端口呢?这是因为nginx还有自己主配置文件的默认端口是80端口(不要搞混淆了)。

     十、HEALTHCHECK检测

    案例演示

    在dockerfile中加入如下内容:

    然后制作一个新的镜像并启动

    每隔默认的30s检测一次是否成功。

     十一、在docker build阶段传递参数ARG

    案例:

    修改dockerfile

    然后构建镜像时传值

    需要注意的是,我们之前学习的命令中传递环境变量参数的时候,使用的都是docker run操作,但是如果我们想在docker build阶段传入参数的值,则要是有docker build –build-tag参数了。

     十二、ONBUILD

     

  • 相关阅读:
    没有功能需求文档就拒绝开发吗?
    用Spring cloud Stream来开发基于MQ消息驱动的微服务
    在Linux上讲Java命令行的作为服务运行
    EF提供的三种查询方式
    C#中sealed关键字
    winform Chart控件 获取鼠标处坐标值方法
    Linq to Entity中连接两个数据库时要注意的问题
    linq中查询列表的使用及iqueryable和list集合之间的转换
    C语言关键字register、extern、static
    DllImport的具体用法
  • 原文地址:https://www.cnblogs.com/FengGeBlog/p/10571961.html
Copyright © 2020-2023  润新知