• 构建自定义镜像并优化dockerfile文件


    一.系统环境

    服务器版本 docker软件版本 CPU架构
    CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64

    二.前言

    创建容器需要镜像,镜像可以从各种Docker镜像仓库中下载,但是有时候镜像仓库里下载的镜像并不能满足我们的要求,这时我们可以构建自定义镜像满足我们的要求。

    构建镜像需要我们编写Dockerfile,Dockerfile是由一组指令组成的文件,其每条指令对应Linux中的一条命令,Docker程序通过读取Dockerfile中的指令最终生成镜像。

    三.镜像构建步骤

    一般镜像构建步骤如下:

    1. 按照需求编写一个dockerfile文件
    2. docker build -f dockerfile 构建成为一个新镜像
    3. docker run 运行新镜像
    4. docker push 推送新镜像到镜像仓库给别人下载使用

    四.dockerfile文件常用指令

    4.1 dockerfile文件常用指令

    FROM 基础镜像

    MAINTAINER 镜像是谁写的,一般是姓名加邮箱

    RUN 镜像构建的时候需要运行的命令

    ADD 往基础镜像里加入文件,会自动解压文件

    COPY 类似ADD,将我们文件拷贝到镜像中

    WORKDIR 镜像的工作目录

    VOLUME 挂载的目录,在一些程序里,需要持久化一些数据,比如数据库中存储数据的文件夹就需要单独处理,可以通过数据卷来处理这些问题。

    EXPOSE 指定向外暴露的端口

    CMD 指定这个容器启动的时候要运行的命令,如果有多个CMD指令,则只有最后一个生效

    ENTRYPOINT 指定这个容器启动的时候要运行的命令,可以追加命, 这个会与CMD弄混淆

    ONBUILD 当构建一个被继承dockerfile 这个时候就会运行ONBUILD

    ENV 构建的时候设置环境变量

    4.2 RUN、CMD、ENTRYPOINT的区别

    RUN 会在现有的基础上新添一层layer,创建一个新的image。例如,它通常用于安装软件包。
    CMD 设置默认命令或参数,可以在 docker 容器运行时从命令行覆盖。
    ENTRYPOINT 配置将作为可执行文件运行的容器。

    RUN有两种形式:

    RUN <command> (shell form),比如:RUN apt-get update && apt-get install -y
    RUN ["executable", "param1", "param2"] (exec form),比如:RUN ["apt-get", "install", "python3"]
    

    CMD有三种形式:

    CMD ["executable","param1","param2"] (exec form, preferred)
    
    CMD ["param1","param2"] ,比如:CMD echo "Hello world" 
    
    CMD command param1 param2 (shell form)
    

    ENTRYPOINT有两种形式:

    ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred),比如:ENTRYPOINT ["/bin/echo", "Hello"]
    
    ENTRYPOINT command param1 param2 (shell form)
    

    五.构建centos镜像

    5.1 构建一个可以使用ifconfig和ip a命令的centos镜像

    查询ifconfig命令和ip a命令属于哪个安装包

    [root@k8smaster ~]# rpm -qf `which ifconfig`
    net-tools-2.0-0.22.20131004git.el7.x86_64
    
    [root@k8smaster ~]# rpm -qf `which ip a`
    /usr/bin/which: no a in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
    iproute-3.10.0-87.el7.x86_64
    

    创建Dockerfile文件

    [root@k8smaster ~]# cat Dockerfile 
    #FROM指定基础镜像为hub.c.163.com/library/centos:latest
    FROM hub.c.163.com/library/centos:latest
    #MAINTAINER指定作者为LZ
    MAINTAINER LZ
    #RUN命令安装net-tools,iproute
    RUN yum -y install net-tools
    RUN yum -y install iproute
    #CMD指定这个容器启动的时候要运行的命令为/bin/bash
    CMD ["/bin/bash"]
    

    根据Dockerfile文件构建镜像

    docker build构建镜像,-t centos:v1表示生成镜像的名字 .当前目录,会自动找到Dockerfile文件

    [root@k8smaster ~]# docker build -t centos:v1 .
    Sending build context to Docker daemon  634.6MB
    Step 1/5 : FROM hub.c.163.com/library/centos:latest
     ---> 328edcd84f1b
    ......
    Successfully tagged centos:v1
    

    查看最新构建成功的镜像

    [root@k8smaster ~]# docker images
    REPOSITORY                                                        TAG        IMAGE ID       CREATED              SIZE
    centos                                                            v1         95a27e59cc5b   About a minute ago   486MB
    

    查看镜像centos:v1的创建历史

    [root@k8smaster ~]# docker history centos:v1
    IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
    95a27e59cc5b   2 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    c446bac1eae1   2 minutes ago   /bin/sh -c yum -y install iproute               148MB     
    2f8fe7e8adfe   3 minutes ago   /bin/sh -c yum -y install net-tools             145MB     
    1812802531f1   3 minutes ago   /bin/sh -c #(nop)  MAINTAINER LZ                0B        
    328edcd84f1b   4 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      4 years ago     /bin/sh -c #(nop)  LABEL name=CentOS Base Im…   0B        
    <missing>      4 years ago     /bin/sh -c #(nop) ADD file:63492ba809361c51e…   193MB     
    

    --rm生成临时容器,在容器里ifconfig和ip a命令都可以使用了

    [root@k8smaster ~]# docker run -it --rm --name=test centos:v1
    [root@2519d33cd64c /]# ifconfig 
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.17.0.4  netmask 255.255.0.0  broadcast 172.17.255.255
            ether 02:42:ac:11:00:04  txqueuelen 0  (Ethernet)
            RX packets 7  bytes 578 (578.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            loop  txqueuelen 1  (Local Loopback)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    [root@2519d33cd64c /]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
        link/ipip 0.0.0.0 brd 0.0.0.0
    123: eth0@if124: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    [root@2519d33cd64c /]# exit
    exit
    

    删除新构建的镜像

    [root@k8smaster ~]# docker rmi centos:v1
    Untagged: centos:v1
    Deleted: sha256:95a27e59cc5b19c0c72d065e43e30627ee5ca46a71d3cf8cfed4ffa266809fae
    Deleted: sha256:c446bac1eae161480d0b823fcfc7a4c6e8d4c58a4502750539ac796931acd6b0
    Deleted: sha256:77d5ccf992f3e869abfb19b47f832f6e106c6724aabfd034e50525ef11fe8603
    Deleted: sha256:2f8fe7e8adfe10d2536238adfbadc75e8cc51e3b32fef3486ee5dfcf81b56a32
    Deleted: sha256:d736137a9b93443939b0ed77024b28d6908e9352297c7e578fce4ba0c2f8c54c
    Deleted: sha256:1812802531f138dd688219ebc5777fc1bffd51e2db52e1e99fee0a84cce322f5
    

    5.2 优化5.1构建的镜像

    下载yum源

    [root@k8smaster ~]# wget ftp://ftp.rhce.cc/k8s/*
    --2021-12-31 15:51:29--  ftp://ftp.rhce.cc/k8s/*
               => “.listing”
    正在解析主机 ftp.rhce.cc (ftp.rhce.cc)... 101.37.152.41
    ......
    
    [root@k8smaster ~]# ls
    CentOS-Base.repo   epel.repo    k8s.repo    docker-ce.repo  
    

    把4个repo文件打包压缩

    #归档压缩文件,并删除原文件
    [root@k8smaster ~]# tar zcf repo.tar.gz *.repo --remove-files
    
    [root@k8smaster ~]# ls
    repo.tar.gz       
    

    查看压缩包里的文件列表

    [root@k8smaster ~]# tar tf repo.tar.gz 
    CentOS-Base.repo
    docker-ce.repo
    epel.repo
    k8s.repo
    

    编写Dockerfile文件
    注意:多写一个RUN命令会多生成一层(layer),镜像会变大,有的docker版本不能写为RUN yum -y install net-tools iproute

    #ADD repo.tar.gz /etc/yum.repos.d/ ADD命令可以把文件从物理机拷贝到容器里,COPY也可以,但是ADD可以自动解压文件,COPY不行
    #ADD只能拷贝当前目录下的文件,不能写为ADD /opt/repo.tar.gz /etc/yum.repo.d/,这样会报错:找不到文件
    [root@k8smaster ~]# cat Dockerfile1 
    FROM hub.c.163.com/library/centos:latest
    MAINTAINER LZ
    #删除基础镜像里自带的repo文件
    Run rm -rf /etc/yum.repos.d/*
    #把宿主机里的repo.tar.gz文件拷贝到/etc/yum.repos.d/目录下,并自动解压缩
    ADD repo.tar.gz /etc/yum.repos.d/
    #安装net-tools和iproute,并清除yum安装缓存
    RUN yum -y install net-tools && \
        yum -y install iproute && \
        yum clean all
    CMD ["/bin/bash"]
    

    构建镜像

    #-f 指定构建镜像的Dockerfile文件
    [root@k8smaster ~]# docker build -t centos:v2 . -f Dockerfile1
    Sending build context to Docker daemon  634.6MB
    Step 1/6 : FROM hub.c.163.com/library/centos:latest
    ......
    Successfully tagged centos:v2
    

    查看新构建的镜像,新镜像比5.1章节构建的镜像体积小

    [root@k8smaster ~]# docker images
    REPOSITORY                                                        TAG        IMAGE ID       CREATED          SIZE
    centos                                                            v2         8077d58cb9b4   32 seconds ago   216MB
    

    查看镜像创建历史

    [root@k8smaster ~]# docker history centos:v2
    IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
    8077d58cb9b4   56 seconds ago       /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    3c33ca486f1f   56 seconds ago       /bin/sh -c yum -y install net-tools &&     y…   23.6MB    
    2331e6a96f1f   About a minute ago   /bin/sh -c #(nop) ADD file:53e452249ee7bf44e…   6.04kB    
    227b560a5ae3   About a minute ago   /bin/sh -c rm -rf /etc/yum.repos.d/*            0B        
    8309f6dd578f   About a minute ago   /bin/sh -c #(nop)  MAINTAINER LZ                0B        
    328edcd84f1b   4 years ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      4 years ago          /bin/sh -c #(nop)  LABEL name=CentOS Base Im…   0B        
    <missing>      4 years ago          /bin/sh -c #(nop) ADD file:63492ba809361c51e…   193MB     
    

    5.3 构建centos镜像,在构建文件中指定运行用户,环境变量,数据卷

    编写Dockerfile文件,在构建文件中指定运行用户,环境变量,数据卷

    [root@k8smaster ~]# cat Dockerfile2
    FROM centos:v2
    MAINTAINER LZ
    #创建用户lz
    RUN useradd lz
    #以lz用户运行
    USER lz
    #设定环境变量xx=147,yy=258
    ENV xx=147
    ENV yy=258
    #定义数据卷
    VOLUME ["/test","/test1"]
    CMD ["/bin/bash"]
    

    构建镜像

    [root@k8smaster ~]# docker build -t uevc:v1 . -f Dockerfile2
    Sending build context to Docker daemon  634.6MB
    Step 1/8 : FROM centos:v2
     ---> 8077d58cb9b4
    ......
    Step 8/8 : CMD ["/bin/bash"]
     ---> Running in 94d69df83e22
    Removing intermediate container 94d69df83e22
     ---> e8416a912217
    Successfully built e8416a912217
    Successfully tagged uevc:v1
    

    查看新创建的镜像

    [root@k8smaster ~]# docker images
    REPOSITORY                                                        TAG        IMAGE ID       CREATED         SIZE
    uevc                                                              v1         e8416a912217   6 seconds ago   216MB
    

    创建临时容器

    [root@k8smaster ~]# docker run -it --rm uevc:v1
    #查看定义的环境变量
    [lz@1f8b1eb2cabb /]$ echo $xx $yy
    147 258
    
    #可以看到容器默认是以lz用户登录的
    [lz@1f8b1eb2cabb /]$ ls /test /test1/
    /test:
    
    /test1/:
    
    [lz@1f8b1eb2cabb /]$ exit
    exit
    

    创建临时容器,以root用户运行容器

    #以指定用户运行
    [root@k8smaster ~]# docker run -it --rm -u root uevc:v1
    [root@60ca5ee61798 /]# id
    uid=0(root) gid=0(root) groups=0(root)
    [root@60ca5ee61798 /]# 
    [root@60ca5ee61798 /]# exit
    exit
    

    创建临时容器,-e xx=qwe -e yy=asd会覆盖镜像里定义的环境变量

    #环境变量以 -e指定的为准
    [root@k8smaster ~]# docker run -it --rm -u root -e xx=qwe -e yy=asd uevc:v1
    [root@2f727b99e12f /]# echo $xx $yy
    qwe asd
    [root@2f727b99e12f /]# 
    [root@2f727b99e12f /]# exit
    exit
    

    5.4 构建可以ssh的centos镜像

    查看ssh的运行进程

    [root@k8smaster ~]# ps -ef | grep ssh
    root        943      1  0 10:53 ?        00:00:00 /usr/sbin/sshd -D
    root       1552    943  0 10:53 ?        00:00:00 sshd: root@pts/0
    root      56191   1613  0 16:05 pts/0    00:00:00 grep --color=auto ssh
    

    查看ssh的安装包

    [root@k8smaster ~]# rpm -qf `which ssh `
    openssh-clients-7.4p1-11.el7.x86_64
    
    [root@k8smaster ~]# rpm -qf `which sshd`
    openssh-server-7.4p1-11.el7.x86_64
    
    [root@k8smaster ~]# rpm -qa | grep ssh
    openssh-clients-7.4p1-11.el7.x86_64
    libssh2-1.4.3-10.el7_2.1.x86_64
    openssh-server-7.4p1-11.el7.x86_64
    openssh-7.4p1-11.el7.x86_64
    sshpass-1.06-2.el7.x86_64
    

    查看ssh-keygen的帮助

    [root@k8smaster ~]# ssh-keygen --help
    unknown option -- -
    usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
                      [-N new_passphrase] [-C comment] [-f output_keyfile]
           ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
           ssh-keygen -i [-m key_format] [-f input_keyfile]
           ssh-keygen -e [-m key_format] [-f input_keyfile]
           ssh-keygen -y [-f input_keyfile]
           ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]
           ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]
           ssh-keygen -B [-f input_keyfile]
           ssh-keygen -D pkcs11
           ssh-keygen -F hostname [-f known_hosts_file] [-l]
           ssh-keygen -H [-f known_hosts_file]
           ssh-keygen -R hostname [-f known_hosts_file]
           ssh-keygen -r hostname [-f input_keyfile] [-g]
           ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]
           ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]
                      [-j start_line] [-K checkpt] [-W generator]
           ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]
                      [-O option] [-V validity_interval] [-z serial_number] file ...
           ssh-keygen -L [-f input_keyfile]
           ssh-keygen -A
           ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]
                      file ...
           ssh-keygen -Q -f krl_file file ...
    

    编写Dockerfile文件

    [root@k8smaster ~]# cat Dockerfile_ssh
    FROM centos:v2
    MAINTAINER LZ
    #安装openssh,创建ssh公钥私钥,给root用户修改密码为qweasd,UseDNS no表示去掉远程ssh连接时的DNS域名解析
    RUN yum -y install openssh-server openssh-clients && \
        ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
        ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key && \
        ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key && \
        echo qweasd | passwd --stdin root && \
        sed -i '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
    #暴露22号端口    
    EXPOSE 22
    #运行ssh
    CMD ["/usr/sbin/sshd","-D"]
    

    构建镜像

    [root@k8smaster ~]# docker build -t centos:ssh . -f Dockerfile_ssh
    Sending build context to Docker daemon  634.6MB
    Step 1/5 : FROM centos:v2
     ---> 8077d58cb9b4
    ......
    Step 5/5 : CMD ["/usr/sbin/sshd","-D"]
     ---> Running in bdd4b00e3402
    Removing intermediate container bdd4b00e3402
     ---> 86e7b8ecb3ab
    Successfully built 86e7b8ecb3ab
    Successfully tagged centos:ssh
    

    使用centos:ssh镜像运行容器

    [root@k8smaster ~]# docker run -dit --restart=always --name=centos_ssh centos:ssh
    d12172a25af5726cfc209d0ff3af803fbc403b617df04a013f4cae85423d4d44
    

    查看容器IP为172.17.0.5

    [root@k8smaster ~]# docker exec centos_ssh ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    29: eth0@if30: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    直接ssh连接容器,root密码为qweasd

    [root@k8smaster ~]# ssh 172.17.0.5
    The authenticity of host '172.17.0.5 (172.17.0.5)' can't be established.
    ECDSA key fingerprint is SHA256:wbRiKPZgpVAg/plN+HixD2GHPx37fzbKBajpU8m5wpY.
    ECDSA key fingerprint is MD5:d0:33:07:03:f8:aa:fc:b5:41:d3:77:2b:75:c9:fe:2e.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '172.17.0.5' (ECDSA) to the list of known hosts.
    root@172.17.0.5's password: 
    
    #成功连接到容器
    [root@d12172a25af5 ~]# grep DNS /etc/ssh/sshd_config 
    UseDNS no
    
    [root@d12172a25af5 ~]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    29: eth0@if30: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    
    [root@d12172a25af5 ~]# exit
    logout
    Connection to 172.17.0.5 closed.
    

    六.构建nginx镜像

    6.1 构建一个自定义index.html文件的Nginx镜像

    创建nginx的首页文件

    [root@k8smaster ~]# cat index.html 
    <p>
    hello gogogoogo<br>
    <p/>
    

    编写nginx的Dockerfile文件

    [root@k8smaster ~]# cat Dockerfile_nginx
    FROM centos:v2
    MAINTAINER LZ
    #安装Nginx
    RUN yum -y install nginx
    #复制index.html文件到/usr/share/nginx/html/下
    COPY index.html /usr/share/nginx/html/
    #暴露80端口
    EXPOSE 80
    #运行Nginx
    CMD ["nginx","-g","daemon off;"]
    

    构建nginx镜像

    [root@k8smaster ~]# docker build -t nginx:v1 . -f Dockerfile_nginx
    Sending build context to Docker daemon  634.6MB
    Step 1/6 : FROM centos:v2
     ---> 8077d58cb9b4
    ......
    Successfully built 5ea781a8ccd8
    Successfully tagged nginx:v1
    

    运行nginx容器,当修改容器里的配置文件,需要重启容器才能生效

    [root@k8smaster ~]# docker run -dit --restart=always --name=nginx -p 8080:80 nginx:v1
    57322f1ce0c62d7c906b875da60fada3e6381a1b988ed28a14f906ffb21db2f2
    

    访问nginx

    [root@k8smaster ~]# curl http://192.168.110.137:8080
    <p>
    hello gogogoogo<br>
    <p/>
    

    七.参考文档

    https://codewithyury.com/docker-run-vs-cmd-vs-entrypoint/#:~:text=In a nutshell&text=CMD sets default command and,will run as an executable

  • 相关阅读:
    JNA 简单示例
    WPF中使用VisiFire制作chart报表
    ActiveMQ CMS 开发环境编译
    c# 程序打包发布
    WPF 程序未处理异常 的捕获
    制作简易浏览器
    C#.NET 支持文件拖放
    C/S代码一例
    Delphi 2010 TStreamReader 和TStreamWriter
    Json数据使用及学习方法
  • 原文地址:https://www.cnblogs.com/renshengdezheli/p/16645144.html
Copyright © 2020-2023  润新知