zoukankan      html  css  js  c++  java
  • Docker之使用Dockerfile创建定制化镜像(四)

    Dockerfile简介

    镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么哪些无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。

    Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,
    因此每一条指令的内容,就是描述该层应当如何构建

    Dockerfile编写注意项

    • # 备注
    • 指令参数,指令的大小写不敏感
    • 第一个非注释行必须是FROM指令
    • 编写Dockerfile必须在一个目录下进行,这个目录称之为 工作目录(WORKSPACE)
    • Dockerfile文件命令的首字母必须大写
    • 制作镜像所要用的文件必须放在工作目录或者工作目录的子目录之下,不能放在父目录
    • 可以通过隐藏文件 .dockeringnore 来指定不要放入到镜像中的文件,一行是一个文件,可以用通配符
    • 基于dockerfile做镜像,本质上还是基于一个现有的镜像做新镜像

    Dockerfile指令详解

    1. FROM

    作用:FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令

    格式:

    FROM <registry>:[tag]

    FROM <registry>@<digest>

    FROM 示例:

    第一步:创建工作目录及dockerfile

    [root@ken ~]# mkdir /ken
    [root@ken ~]# cd /ken
    [root@ken ken]# touch Dockerfile

    第二步:写入from指令

    docker.io:注册表

    nginx:仓库

    latest:版本号

    [root@ken ken]# cat Dockerfile
    FROM docker.io/nginx:latest

    2. LABEL

    作用:设定一些元数据

    格式:

    LABEL 信息

    LABEL示例:

    LABEL author "ken"

    3. COPY

    作用:将工作目录下的文件复制到所做得镜像中的文件系统中

    格式:

    复制单个文件:COPY <src> <dest>

    复制多个文件:COPY [<src> <src> <src>… <dest>]

    COPY示例:

    COPY passwd /data/

    注意:

    • 源文件路径用相对路径,目标一般用绝对路径
    • 也可以通配符
    • 源文件必须在工作目录或者工作目录的子目录中
    • 目标路径可以不存在,会自动创建
    • 如果源文件是一个目录,会自动递归复制目录下的文件到目标位置,但是目录自身不会复制
    • 如果复制多个文件,或者源文件中用了通配符,那么目标路径必须以 / 为结尾

    4. ADD

    作用:和COPY类似,可以实现将文件和目录加载镜像中,但是区别是可以实现将tar包解压,也可以实现从网络下载文件到镜像

    注意:下载的tar无法解压

    格式

    ADD <src> <dest>

    ADD [“<src>” “<src>” “<src>” “<dest>”]

    ADD示例:

    ADD nginx-1.14.0.tar.gz /data/

    5. WORKDIR

    作用:相当于执行cd命令。切换目录,为后续的RUN、CMD、ENTRYPOINT 指令配置工作目录。

    格式:

    WORKDIR 容器目录

    WORKDIR示例:

    WORKDIR /pack/nginx/

    6. VOLUME

    作用:指定数据卷的挂载点

    格式:

    VOLUME 容器目录

    VOLUME示例:

    VOLUME /data/mysql/mysql3306/data

    7. EXPOSE

    作用:设置Docker容器内部暴露的端口号,如果需要外部访问,还需要启动容器时增加-p或者-P参数进行分配。

    格式:

    EXPOSE PORT/[PROTOCOL]

    EXPOSE示例:

    EXPOSE 80/tcp

    9. ENV

    作用:设置环境变量

    格式:

    ENV var value

    ENV var1=value1 var2=value2 …

    注意:

    通过ENV所定义的变量是可以传递到容器之中,但是,在创建容器的时候,如果手动指定了变量的值,那么这个值会覆盖掉镜像中原有的值

    ENV示例:

    ENV  pkgname=nginx-1.14.0.tar.gz root=/data/mysql/mysql3306/data

    10. RUN

    作用:基于镜像构建容器时候要执行命令

    阶段:第一阶段,也就是构建镜像的时候执行

    格式:

    RUN 命令

    RUN示例:

    RUN tar xf $root$pkgname

    11. CMD

    作用:定义容器启动以后要默认运行的程序,pid为1的程序

    阶段:第二阶段,也就是将镜像构成成容器的时候执行

    注意:可以在启动容器的时候用指定的命令替换掉镜像所要执行的命令

    CMD指定容器启动是执行的命令,每个Dockerfile只能有一条CMD命令,如果指定了多条,只有最后一条会被执行。如果你在启动容器的时候也指定的命令,那么会覆盖Dockerfile构建的镜像里面的CMD命令

    格式:

    CMD <命令>   相当于执行的是/bin/sh -c 命令,也相当于执行exec来运行命令

    CMD [“<命令>”, “<参数>”, “<参数>”]

    CMD [“<参数>”, “<参数>”]   <<< 需要借助于ENTRYPOINT指令

    CMD示例:

    CMD mkdir /ken

    12. ENTRYPOINT

    作用:定义容器启动以后要默认运行的程序,pid为1的程序

    注意:

    在运行RUN的时候所执行的命令无法覆盖ENTRYPOINT中的命令

    RUN 后面的命令会被以参数的方式追加到原本要执行的命令的末尾,而不是替换

    基于一个镜像,在创建容器的时候,通过传递不同的参数实现创建不同的容器

    每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个起效

    格式:

    ENTRYPOINT  [“执行命令”,”参数1″,”参数2″…]

    ENTRYPOINT示例:

    ENTRYPOINT [ "curl", "-s", "http://10.220.5.138" ]

    例如如下CMD和ENTRYPOINT的结合

    FROM nginx
    label auther=ken
    ARG name=ken
    ENV path=/ken/
    COPY test /data/
    ADD https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/audiocd-kio-devel-4.10.5-3.el7.i686.rpm $path
    WORKDIR  $path
    RUN mkdir $name
    VOLUME $path
    EXPOSE 80
    RUN mkdir /test1
    CMD ["-g","daemon off;"]
    ENTRYPOINT ["nginx"]
    

    13. ARG

    作用:定义变量,这个变量是用在第一阶段(构建镜像——build)

    格式:

    ARG 变量名=变量值

    ARG示例:

    ARG name=ken

    补充:Dockerfile中ENV 和 ARG的区别

    在指定docker build 过程中传参数,要用ARG

    在执行docker run的过程中传参数,要用ENV

    ARG构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的
    环境变量,在将来容器运行时是不会存在这些环境变量的

    14. USER

    作用:指定运行容器时的用户名和UID,后续的RUN指令也会使用这里指定的用户

    该用户必须存在于容器的用户空间中(容器的文件系统的中的/etc/passwd中)

    格式:

    USER <UID>|<USERNAME>

    USER示例:

    user ken

     

    15. HEALTHCHECK

    作用:docker daemon检查docker容器是否正常,如果异常会将该容器stop

    将容器stop的条件

    1)主进程停止了

    2)主进程工作在了后台

    格式:

    HEALTHCHECK [options] CMD

    options

    –interval=#s|m          指定健康检查的时间间隔(例如:30s,30m)

    –timeout=#s|m           指定等待响应的超时时间

    –start-period=#s|m      指定容器启动多久以后才可以做监控检查

    –retries=#              指定重试次数

    返回值

    0:success

    1:unhealth

    HEALTHCHECK示例:

    HEALTHCHECK --interval=5m --timeout=1s --retries=3 CMD curl http://10.220.5.138/ken.html || exit 1

    16. SHELL

    可以用来指定系统中默认的shell类型

    格式:

    SHELL [“/bin/sh”, “-c”]    (linux系统中)

    SHELL示例:

    SHELL ["/bin/sh","-c"]

    17. STOPSIGNAL

    向容器中pid为1的进程发送一个信号,通过这个信号来关闭这个主进程

    默认是15信号

    格式:

    STOPSIGNAL 数值

    STOPSIGNAL示例:

    STOPSIGNAL 9

    18. ONBULID

    作用:定义一个触发器,指定的命令在构建镜像时并不执行,用来实现当基于这个这个镜像做新镜像的时候要执行的命令

    格式:

    ONBUILD 其他指令

    ONBUILD示例:

    ONBUILD COPY ken /app/

    Dokcerfile完整演示创建nginx镜像

    根据上面各个指令的介绍,我就直接用上面写的dockerfile进行演示。整个dockerifle内容如下。

     
    [root@ken ~]# vim /ken/Dockerfile 
    FROM docker.io/nginx:latest
    LABEL author "ken"
    COPY ./passwd /data/
    WORKDIR /pack/nginx/
    ENV  pkgname=nginx-1.14.0.tar.gz  root=/data/mysql/mysql3306/data/
    COPY nginx-1.14.0.tar.gz $root
    VOLUME $root
    EXPOSE 80/tcp
    RUN tar xf $root$pkgname
    CMD nginx -g "daemon off;"
     

    第一步:构建镜像

    build:是指根据dockerfile制作镜像

    -t:指定一个tag标签

    .:表示上下文。你也可以理解为dockfile所在的目录,但是并不是准确的

    如果下方出现successfully就表示镜像已经构建成功了

     
    [root@ken ken]# docker build -t ken:v1-0 .
    Sending build context to Docker daemon 1.021 MB
    Step 1/10 : FROM docker.io/nginx:latest
     ---> 568c4670fa80
    Step 2/10 : LABEL author "ken"
     ---> Using cache
     ---> 80e4e5846fd9
    Step 3/10 : COPY ./passwd /data/
     ---> Using cache
     ---> 685a7ceb74b3
    Step 4/10 : WORKDIR /pack/nginx/
     ---> Using cache
     ---> 0fc65f8c36df
    Step 5/10 : ENV pkgname nginx-1.14.0.tar.gz root /data/mysql/mysql3306/data/
     ---> Using cache
     ---> 3f6038473472
    Step 6/10 : COPY nginx-1.14.0.tar.gz $root
     ---> Using cache
     ---> 0cbff6223d5b
    Step 7/10 : VOLUME $root
     ---> Using cache
     ---> b74ac1c36c31
    Step 8/10 : EXPOSE 80/tcp
     ---> Using cache
     ---> 6863a87a61a2
    Step 9/10 : RUN tar xf $root$pkgname
     ---> Using cache
     ---> b32ac636a389
    Step 10/10 : CMD nginx -g "daemon off;"
     ---> Running in 02308825301d
     ---> 4a91d70a57eb
    Removing intermediate container 02308825301d
    Successfully built 4a91d70a57eb
     

    第二步:查看镜像

    可以发现构建的名为ken标签为v1-0的镜像已经存在了

    [root@ken ken]# docker image ls
    REPOSITORY                                      TAG                 IMAGE ID            CREATED             SIZE
    ken                                             v1-0                4a91d70a57eb        21 minutes ago      116 MB

    第三步:启动容器

    可以发现基于我们刚才的创建的镜像的容器已经顺利跑起来了。

     
    [root@ken ken]# docker run -d --name ken3 -d ken:v1-0 
    11f492a28b943e619b0ed5d6b19f212f1c9cc47f9bdbe132845e7a7129e5b419                    
    [root@ken ken]# docker container ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
    11f492a28b94        ken:v1-0            "/bin/sh -c 'nginx..."   16 seconds ago      Up 11 seconds       80/tcp              ken3
     

    第四步:登录容器

    可以发现我们这个启动的容器里面已经有我们指定的工作目录

    复制过来的passwd文件

    已经下载并传送到/data下了

     
    [root@ken ken]# docker exec -it ken3 bash
    root@11f492a28b94:/pack/nginx# ls /data/
    mysql/  passwd  
    root@11f492a28b94:/pack/nginx# ls /data/
    mysql/  passwd  
     oot@11f492a28b94:/pack/nginx# ls /data/mysql/mysql3306/data/nginx-1.14.0.tar.gz 
    /data/mysql/mysql3306/data/nginx-1.14.0.tar.gz
     

    这样基于dockerfile自主创建镜像的过程就演示完了,快去自己制作一个属于自己的镜像吧。

    基于centos部署LAMP镜像

    第一步:拉取centos7镜像

    并按照如下的dockerfile初始化镜像

    FROM centos:7
    ENV container docker
    RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == 
    systemd-tmpfiles-setup.service ] || rm -f $i; done); 
    rm -f /lib/systemd/system/multi-user.target.wants/*;
    rm -f /etc/systemd/system/*.wants/*;
    rm -f /lib/systemd/system/local-fs.target.wants/*; 
    rm -f /lib/systemd/system/sockets.target.wants/*udev*; 
    rm -f /lib/systemd/system/sockets.target.wants/*initctl*; 
    rm -f /lib/systemd/system/basic.target.wants/*;
    rm -f /lib/systemd/system/anaconda.target.wants/*;
    VOLUME [ "/sys/fs/cgroup" ]
    CMD ["/usr/sbin/init"]

    第二步:编写制作LAMP架构的dockerfile

    FROM local/c7-systemd
    COPY local.repo /etc/yum.repos.d/
    COPY wordpress /var/www/html/
    RUN yum -y install httpd mariadb-server php php-mysql; yum clean all; systemctl restart mariadb httpd;systemctl enable mariadb httpd.service
    EXPOSE 80 3306
    CMD ["/usr/sbin/init"]
    

    1.使用第一步创建出来的镜像

    2.把local.repo文件发送到镜像中,因为镜像文件没有mariad数据库

    local.repo文件内容

    [local]
    name=local
    enabled=1
    gpgcheck=0
    baseurl=https://mirrors.aliyun.com/centos/7/os/x86_64/
    

    3.把配置好的wordpress安装包复制到网站根目录下

    4.下载LAMP架构

    5.暴露80 和3306 端口

    6.启动

    第三步:运行容器

    [root@ken-node3 centos]# docker run -d -v /sys/fs/cgroup/:/sys/fs/cgroup/   -p 888:80 --privileged  centos-wordpress:v1
    

    –privileged 让容器能够获得更多特权,否则在容器内部不能使用systemctl,会报如下的错

    Failed to get D-Bus connection: Operation not permitted

    第四步:进入容器创建数据库

    [root@ken-node3 centos]# docker exec -it f80ed6fb67b3 bash
    [root@f80ed6fb67b3 /]# ls /var/www/html/
    index.php                  wp-activate.php       wp-config-sample.php  wp-links-opml.php  wp-register.php
    license.txt                wp-admin              wp-config.php         wp-load.php        wp-settings.php
    readme.html                wp-app.php            wp-content            wp-login.php       wp-signup.php
    wordpress                  wp-blog-header.php    wp-cron.php           wp-mail.php        wp-trackback.php
    wordpress-3.3.1-zh_CN.zip  wp-comments-post.php  wp-includes           wp-pass.php        xmlrpc.php
    [root@f80ed6fb67b3 /]# mysql
    Welcome to the MariaDB monitor.  Commands end with ; or g.
    Your MariaDB connection id is 2
    Server version: 5.5.60-MariaDB MariaDB Server
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    
    MariaDB [(none)]> create database ken;
    Query OK, 1 row affected (0.00 sec)
    
    MariaDB [(none)]> grant all on *.* to ken@'localhost' identified by '123';
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [(none)]> exit
    Bye
    

    第五步:浏览器访问

  • 相关阅读:
    scrapy爬取某网站,模拟登陆过程中遇到的那些坑
    Linux平台安装MongoDB
    Oracle HAVING子句
    oracle查找重复记录-转
    PLSQL存储过程(基础篇)-转
    oracle for update和for update nowait的区别
    Oracle两个数据库互相访问,DBLink使用-转
    中国人素质低的根本原因
    威胁李嘉诚是愚蠢的
    回归农村,这才是我想要的生活
  • 原文地址:https://www.cnblogs.com/it-peng/p/11388232.html
Copyright © 2011-2022 走看看