zoukankan      html  css  js  c++  java
  • 构建docker镜像

    一、基于容器生成镜像

    基于容器生成镜像,实际上就是在某一个容器中添加一些功能,然后再生成新的镜像,例如下面这是linux上已经存在的镜像:

    [vagrant@localhost ~]$ docker image ls
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    centos              latest              470671670cac        10 days ago         237MB
    hello-world         latest              fce289e99eb9        13 months ago       1.84kB

    现在,在centos镜像的容器中添加vim功能然后生成新的镜像:

    1、运行centos镜像

    需要使用交互式的运行命令:

    [vagrant@localhost ~]$ docker run -it centos
    [root@68804cc4767f /]# 

    2、安装vim

    注意此时已经进入到容器内部,在容器内安装vim:

    [root@68804cc4767f /]# yum install -y vim

    3、查看容器

    这样完成vim的安装,退出该容器,并且查看刚刚创建的容器:

    [vagrant@localhost ~]$ docker container ls -a
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
    68804cc4767f        centos              "/bin/bash"         3 minutes ago       Exited (0) 21 seconds ago                       interesting_wu

    4、提交容器

    提交刚刚做过改变的容器,使其成为新的镜像:

    [vagrant@localhost ~]$ docker commit interesting_wu shenjianping0307/centos-vim
    sha256:731f454d1dd9420fed08eeec499285908d69d33541acc22b7eb4a454b4e9b9e8
    
    #注意
    #其中interesting_wu 为容器的Name
    #centos-vim为镜像的名称

    5、查看镜像

    [vagrant@localhost ~]$ docker image ls
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    shenjianping0307/centos-vim   latest              731f454d1dd9        2 minutes ago       298MB
    centos                        latest              470671670cac        10 days ago         237MB

    6、基础镜像与新建镜像的比较

    基础镜像是centos,自己制作的镜像的centos-vim,它们之间有什么区别呢?自己制作的镜像实际上就是在基础镜像的基础上添加了一层,也就是vim。

    [vagrant@localhost ~]$ docker history 470671670cac  #base镜像layer
    IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
    470671670cac        10 days ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
    <missing>           10 days ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
    <missing>           13 days ago         /bin/sh -c #(nop) ADD file:aa54047c80ba30064…   237MB      
             
    [vagrant@localhost ~]$ docker history 731f454d1dd9  #新建镜像layer
    IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
    731f454d1dd9        6 minutes ago       /bin/bash                                       60.4MB              
    470671670cac        10 days ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
    <missing>           10 days ago         /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B                  
    <missing>           13 days ago         /bin/sh -c #(nop) ADD file:aa54047c80ba30064…   237MB   

    二、基于Dockerfile生成镜像

    (一)Dockerfile初体验

     首先先删掉之前创建的centos-vim镜像

    [vagrant@localhost ~]$ docker image rm 731f454d1dd9
    Untagged: shenjianping0307/centos-vim:latest
    Deleted: sha256:731f454d1dd9420fed08eeec499285908d69d33541acc22b7eb4a454b4e9b9e8
    Deleted: sha256:6626f7fa820cd657070d377576e7deda5e6285f949c506fb2c045735499989e3

    1、创建Dockerfile文件

    [vagrant@localhost ~]$ mkdir centos-vim    #创建文件夹
    [vagrant@localhost ~]$ cd centos-vim/  #进入文件夹
    [vagrant@localhost centos-vim]$ vim Dockerfile #编写Dockerfile

    Dockerfile中的文件内容为:

    FROM centos
    RUN yum install -y vim

    2、生成镜像

    [vagrant@localhost centos-vim]$ docker build -t shenjianping0307/centos-vim .
    
    #说明
    #1、-t是tag标签的意思
    #2、.表示在当前目录下执行Dockerfile

    3、查看镜像

    [vagrant@localhost centos-vim]$ docker image ls
    REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
    shenjianping0307/centos-vim   latest              0a5f18d9f786        56 seconds ago      298MB
    centos                        latest              470671670cac        10 days ago         237MB

    (二)详解Dockerfile 

    1、FROM

    FROM关键字用于该镜像的基础镜像

    FROM scratch   #不依赖于任何的基础镜像,从头开始
    FROM centos   #依赖于centos基础镜像
    FROM ubuntu:14.04 #依赖于指定版本的ubuntu的基础镜像

    2、LABEL

    对镜像的一些说明信息

    LABEL maintainer "xxx@g.mail"  #作者信息
    LABEL version = "1.0"  #版本信息
    LABEL description = "This is description" #描述信息

    3、RUN

    执行的命令,每执行一次就会生成一层layer

    RUN yum update && yum install -y vim 
    
    #反斜线表示换行,无用分层,合并多条命令

    4、WORKDIR

    设定工作目录,类似于cd

    WORKDIR /a  #如果没有会自动创建a目录
    WORKDIR test
    RUN pwd  #输出是/a/test

    注意:尽量使用WORKDIR,避免使用RUN cd命令,尽量使用绝对目录。

    5、ADD、COPY

    这两个命令都是将本地文件加入到镜像中,那么它们的区别是什么呢?

    ADD不仅可以将本地文件添加到镜像中,并且可以对文件进行解压,COPY是达不到这点的。

    ADD t1.txt /   #将本地文件t1.txt添加到镜像根目录中
    ADD t1.tar.gz #添加到根目录并且解压
    
    WORKDIR /root
    ADD t1 test/    #将t1添加至 /root/test/ 下
    
    WORKDIR /root
    COPY t1 test/    #将t1添加至 /root/test/ 下

    大部分情况下,COPY由于ADD,除了ADD有解压缩的功能除外。ADD和COPY都是添加本地文件,如果获取远程文件,可通过RUN curl 或者RUN wget完成。

    6、ENV

    设置环境变量

    ENV MYSQL_VERSION 5.6  #设置常量
    RUN apt-get install -y mysql-server = "${MYSQL_VERSION}" 
    && rm -rf /var/lib/apt/lists/*  #引用常量

    使用ENV利于维护性。

    7、RUN、CMD、ENTRYPOINT

    • RUN 执行命令并创建新的Image Layer
    • CMD 设置容器启动后默认执行的命令和参数(如果docker run指定了其它命令,CMD命令被忽略;定义多个CMD,只会执行最后一个)
    • ENTRYPOINT 设置容器启动时运行的命令

    在此之前需要说明一下Shell格式和EXec格式的命令

    ENV MYSQL_VERSION 5.6  #设置常量
    RUN apt-get install -y mysql-server = "${MYSQL_VERSION}" 
    && rm -rf /var/lib/apt/lists/*  #引用常量
    
    Shell和Exec格式
    
    Shell格式
    RUN apt-get install -y vim
    CMD echo "hello docker"
    ENTRYPOINT echo "hello docker"
    
    Exec格式
    RUN ["apt-get", "install", "-y", "vim"]
    CMD ["/bin/echo", "hello docker"]
    ENTRYPOINT ["/bin/echo", "hello docker"]
    View Code

    这里分别以Shell格式和Exec格式命令来进行制作镜像

    (1)Shell格式的Dockerfile

    FROM centos
    ENV name Docker
    CMD echo "Hello $name"

    然后进行制作镜像:

    [vagrant@localhost test-command]$ docker build -t shenjianping0307/centos-cmd .
    Sending build context to Docker daemon  2.048kB
    Step 1/3 : FROM centos
     ---> 470671670cac
    Step 2/3 : ENV name Docker
     ---> Running in 0a09ef3c9ff3
    Removing intermediate container 0a09ef3c9ff3
     ---> e5aca6e78cba
    Step 3/3 : CMD echo "Hello $name"
     ---> Running in bf73cf74e082
    Removing intermediate container bf73cf74e082
     ---> 4f11efce0c70
    Successfully built 4f11efce0c70
    Successfully tagged shenjianping0307/centos-cmd:latest
    View Code

    显然执行这个镜像是可以成功的:

    [vagrant@localhost test-command]$ docker run shenjianping0307/centos-cmd
    Hello Docker

    (2)Exec格式的Dockerfile

    FROM centos
    ENV name Docker
    ENTRYPOINT ["/bin/echo","hello $name"]

    然后制作镜像:

    [vagrant@localhost test-command]$ docker build -t shenjianping0307/centos-entrypoint .
    Sending build context to Docker daemon  2.048kB
    Step 1/3 : FROM centos
     ---> 470671670cac
    Step 2/3 : ENV name Docker
     ---> Using cache
     ---> e5aca6e78cba
    Step 3/3 : ENTRYPOINT ["/bin/echo","hello $name"]
     ---> Running in 406fca203d44
    Removing intermediate container 406fca203d44
     ---> 12eab087ba3c
    Successfully built 12eab087ba3c
    Successfully tagged shenjianping0307/centos-entrypoint:latest
    View Code

    可以看到这个执行的结果是失败的:

    [vagrant@localhost test-command]$ docker run shenjianping0307/centos-entrypoint
    hello $name

    它没有将$name这个变量给替换出来,因为Exec执行的命令单纯的就是echo命令,没有在shell的环境下。

    那么可以怎样修改就使得结果可行呢?修改Dockerfile文件:

    FROM centos
    ENV name Docker
    ENTRYPOINT ["/bin/bash","-c","echo hello $name"]  #-c指定后面的都是命令参数

    然后生成镜像,再执行就ok了。

    总结:

    #CMD
    a、容器启动时的默认执行命令
    b、如果docker run 后有其他命令,CMD命令将被忽略
    c、如果有多个CMD命令,只会执行最后一个CMD
    
    #ENTRYPOINT
    a、让容器以应用程序或者服务形式运行(比如启动数据库服务等)
    b、不会被忽略,一定会执行
    #覆盖掉CMD命令
    [vagrant@localhost test-command]$ docker run -it  shenjianping0307/centos-cmd /bin/bash   
    [root@72379708f335 /]# 
    
    #ENTRYPOINT一定会执行
    [vagrant@localhost test-command]$ docker run -it shenjianping0307/centos-entrypoint-new /bin/bash
    hello Docker
    View Code

    (三)容器命令

    1、后台运行(-d参数)

    [root@localhost vagrant]# docker run -d hello-world
    9ab69b8a51ea4a103f9fdf5230dfb09314958d3dd1797739eeb4a61cfea1adf3

    通过-d参数指定容器后台运行,返回容器的ID

    2、exec

    这个命令可以对已经正在运行的容器进行操作,包括进入到容器内部进行查看日志等信息(这个命令就是对运行中的容器执行某个命令)

    [root@localhost vagrant]# docker exec -it 9ab69b8a51ea4a103f9fdf5230dfb09314958d3dd1797739eeb4a61cfea1adf3 /bin/bash

    3、停止容器运行(stop)

    [vagrant@localhost ~]$ docker stop 9ab6

    4、查看正在运行的容器

    [vagrant@localhost ~]$ docker ps

    5、查看已经退出的容器

    [vagrant@localhost ~]$ docker ps -a

    6、获取容器的ID

    [vagrant@localhost ~]$ docker ps -aq
    88b0da62d57d

    7、删掉所有退出状态的容器

    [vagrant@localhost ~]$ docker rm $(docker ps -aq)

    8、容器命名(--name)

    如果不规定容器名称就会随机分配一个名称,但是可以通过--name参数指定名称

    [vagrant@localhost ~]$ docker run -d --name=hello hello-world  #容器的名称就是hello,后续可以通过docker start hello;docker stop hello来操作容器

    9、容器信息(inspect)

    容器的一些信息,包括ID,created,网络等信息。

    [vagrant@localhost ~]$ docker inspect 88b0da62d57d
    [
        {
            "Id": "88b0da62d57dd4bdace11fa32713be90209a4e5024d855875a2a197238fae917",
            "Created": "2020-01-29T13:08:32.740086073Z",
            "Path": "/hello",
            "Args": [],
            "State": {
                "Status": "exited",
                "Running": false,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 0,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2020-01-29T13:08:34.240609354Z",
                "FinishedAt": "2020-01-29T13:08:34.162986756Z"
            },
            "Image": "sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e",
            "ResolvConfPath": "/var/lib/docker/containers/88b0da62d57dd4bdace11fa32713be90209a4e5024d855875a2a197238fae917/resolv.conf",
            "HostnamePath": "/var/lib/docker/containers/88b0da62d57dd4bdace11fa32713be90209a4e5024d855875a2a197238fae917/hostname",
            "HostsPath": "/var/lib/docker/containers/88b0da62d57dd4bdace11fa32713be90209a4e5024d855875a2a197238fae917/hosts",
            "LogPath": "/var/lib/docker/containers/88b0da62d57dd4bdace11fa32713be90209a4e5024d855875a2a197238fae917/88b0da62d57dd4bdace11fa32713be90209a4e5024d855875a2a197238fae917-json.log",
            "Name": "/blissful_easley",
            "RestartCount": 0,
            "Driver": "overlay2",
            "Platform": "linux",
            "MountLabel": "",
            "ProcessLabel": "",
            "AppArmorProfile": "",
            "ExecIDs": null,
            "HostConfig": {
                "Binds": null,
                "ContainerIDFile": "",
                "LogConfig": {
                    "Type": "json-file",
                    "Config": {}
                },
                "NetworkMode": "default",
                "PortBindings": {},
                "RestartPolicy": {
                    "Name": "no",
                    "MaximumRetryCount": 0
                },
                "AutoRemove": false,
                "VolumeDriver": "",
                "VolumesFrom": null,
                "CapAdd": null,
                "CapDrop": null,
                "Capabilities": null,
                "Dns": [],
                "DnsOptions": [],
                "DnsSearch": [],
                "ExtraHosts": null,
                "GroupAdd": null,
                "IpcMode": "private",
                "Cgroup": "",
                "Links": null,
                "OomScoreAdj": 0,
                "PidMode": "",
                "Privileged": false,
                "PublishAllPorts": false,
                "ReadonlyRootfs": false,
                "SecurityOpt": null,
                "UTSMode": "",
                "UsernsMode": "",
                "ShmSize": 67108864,
                "Runtime": "runc",
                "ConsoleSize": [
                    0,
                    0
                ],
                "Isolation": "",
                "CpuShares": 0,
                "Memory": 0,
                "NanoCpus": 0,
                "CgroupParent": "",
                "BlkioWeight": 0,
                "BlkioWeightDevice": [],
                "BlkioDeviceReadBps": null,
                "BlkioDeviceWriteBps": null,
                "BlkioDeviceReadIOps": null,
                "BlkioDeviceWriteIOps": null,
                "CpuPeriod": 0,
                "CpuQuota": 0,
                "CpuRealtimePeriod": 0,
                "CpuRealtimeRuntime": 0,
                "CpusetCpus": "",
                "CpusetMems": "",
                "Devices": [],
                "DeviceCgroupRules": null,
                "DeviceRequests": null,
                "KernelMemory": 0,
                "KernelMemoryTCP": 0,
                "MemoryReservation": 0,
                "MemorySwap": 0,
                "MemorySwappiness": null,
                "OomKillDisable": false,
                "PidsLimit": null,
                "Ulimits": null,
                "CpuCount": 0,
                "CpuPercent": 0,
                "IOMaximumIOps": 0,
                "IOMaximumBandwidth": 0,
                "MaskedPaths": [
                    "/proc/asound",
                    "/proc/acpi",
                    "/proc/kcore",
                    "/proc/keys",
                    "/proc/latency_stats",
                    "/proc/timer_list",
                    "/proc/timer_stats",
                    "/proc/sched_debug",
                    "/proc/scsi",
                    "/sys/firmware"
                ],
                "ReadonlyPaths": [
                    "/proc/bus",
                    "/proc/fs",
                    "/proc/irq",
                    "/proc/sys",
                    "/proc/sysrq-trigger"
                ]
            },
            "GraphDriver": {
                "Data": {
                    "LowerDir": "/var/lib/docker/overlay2/c2e06ee78c34f087122e5d228f0992262a6ecc04c696722a5704a4b777b91dda-init/diff:/var/lib/docker/overlay2/d9962cd997ab1fe909b3ba671af6f3a1b422ba7d49145b04736c5727d847c52d/diff",
                    "MergedDir": "/var/lib/docker/overlay2/c2e06ee78c34f087122e5d228f0992262a6ecc04c696722a5704a4b777b91dda/merged",
                    "UpperDir": "/var/lib/docker/overlay2/c2e06ee78c34f087122e5d228f0992262a6ecc04c696722a5704a4b777b91dda/diff",
                    "WorkDir": "/var/lib/docker/overlay2/c2e06ee78c34f087122e5d228f0992262a6ecc04c696722a5704a4b777b91dda/work"
                },
                "Name": "overlay2"
            },
            "Mounts": [],
            "Config": {
                "Hostname": "88b0da62d57d",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": true,
                "AttachStderr": true,
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
                ],
                "Cmd": [
                    "/hello"
                ],
                "Image": "hello-world",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": null,
                "OnBuild": null,
                "Labels": {}
            },
            "NetworkSettings": {
                "Bridge": "",
                "SandboxID": "d38a7ac6dd5469d8964a81f16021bbc06ac87266eafc2c20bec29845898ff0e0",
                "HairpinMode": false,
                "LinkLocalIPv6Address": "",
                "LinkLocalIPv6PrefixLen": 0,
                "Ports": {},
                "SandboxKey": "/var/run/docker/netns/d38a7ac6dd54",
                "SecondaryIPAddresses": null,
                "SecondaryIPv6Addresses": null,
                "EndpointID": "",
                "Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "IPAddress": "",
                "IPPrefixLen": 0,
                "IPv6Gateway": "",
                "MacAddress": "",
                "Networks": {
                    "bridge": {
                        "IPAMConfig": null,
                        "Links": null,
                        "Aliases": null,
                        "NetworkID": "738605add8227bd6f264a8c21a14dff43d797f1d0bba0a3ff5ce069d319fc127",
                        "EndpointID": "",
                        "Gateway": "",
                        "IPAddress": "",
                        "IPPrefixLen": 0,
                        "IPv6Gateway": "",
                        "GlobalIPv6Address": "",
                        "GlobalIPv6PrefixLen": 0,
                        "MacAddress": "",
                        "DriverOpts": null
                    }
                }
            }
        }
    ]
    详细信息

    三、实战

    (一)运行Web程序

    1、新建Web文件夹

    [vagrant@localhost ~]$ mkdir Web

    2、建立app.py文件以及Dockerfile文件

    [vagrant@localhost ~]$ cd Web/
    [vagrant@localhost Web]$ touch app.py
    [vagrant@localhost Web]$ touch Dockerfile
    [vagrant@localhost Web]$ ls
    app.py  Dockerfile

    3、app.py中写入web程序

    from flask import Flask
    app = Flask(__name__)
    @app.route('/')
    def test():
       return "test"
    if __name__ == "__main__":
       app.run(host="0.0.0.0",port=5000)

    4、编写Dockerfile文件

    FROM python:2.7   #基础镜像
    LABEL maintainer="shenjianping0307@gmail.com"  #作者信息
    RUN pip install flask  #运行环境所需要的包
    COPY app.py /app/    #将本地文件拷贝到镜像app目录下中 /app/app.py
    WORKDIR /app    #进入到工作目录,相当于cd  /app/ ,否则CMD命令找不到可执行文件app.py
    EXPOSE 5000    #暴露端口
    CMD ["python","app.py"]  #运行文件,相当于python app.py

    5、生成镜像

    [vagrant@localhost Web]$ docker build -t shenjianping0307/app .

    (二)stress工具 

    1、容器中安装stress

    • 下载ubuntu镜像
    [root@localhost Web]# docker pull ubuntu
    • 运行ubuntu镜像
    [root@localhost Web]# docker run -it ubuntu
    root@fd1ab8e81c64:/# 
    • 容器中安装stress工具
    root@fd1ab8e81c64:/# apt-get update && apt-get install -y stress

    安装完毕后可以看到安装成功:

    root@fd1ab8e81c64:/# which stress
    /usr/bin/stress

    另外,可以看看stress的命令:

    root@fd1ab8e81c64:/# stress --help
    Usage: stress [OPTION [ARG]] ...
     -?, --help         show this help statement
         --version      show version statement
     -v, --verbose      be verbose
     -q, --quiet        be quiet
     -n, --dry-run      show what would have been done
     -t, --timeout N    timeout after N seconds
         --backoff N    wait factor of N microseconds before work starts
     -c, --cpu N        spawn N workers spinning on sqrt()
     -i, --io N         spawn N workers spinning on sync()
     -m, --vm N         spawn N workers spinning on malloc()/free()
         --vm-bytes B   malloc B bytes per vm worker (default is 256MB)
         --vm-stride B  touch a byte every B bytes (default is 4096)
         --vm-hang N    sleep N secs before free (default none, 0 is inf)
         --vm-keep      redirty memory instead of freeing and reallocating
     -d, --hdd N        spawn N workers spinning on write()/unlink()
         --hdd-bytes B  write B bytes per hdd worker (default is 1GB)
    View Code
    • 进行测试
    root@fd1ab8e81c64:/#  stress --vm 1 --verbose
    
    #注意:
    #--vm表示起的进程有几个  默认的大小是256M
    #--verbose 详细的日志

    2、Dockerfile制作stress工具

    • 创建Dockerfile文件
    [root@localhost vagrant]# mkdir ubuntu-stress
    [root@localhost vagrant]# cd ubuntu-stress/
    [root@localhost ubuntu-stress]# touch Dockerfile  #创建Dockerfile文件
    • 写入内容
    FROM ubuntu
    RUN apt-get update && apt-get -y install stress
    ENTRYPOINT ["/usr/bin/stress"]
    CMD []     #参数,例如--vm之类的
    • 生成镜像
    [root@localhost ubuntu-stress]# docker build -t shenjianping0307/ubuntu-stress .
    • 运行镜像
    [root@localhost ubuntu-stress]# docker run -it shenjianping0307/ubuntu-stress --vm 1 
    stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
  • 相关阅读:
    设计模式---工厂模式和抽象工厂模式
    设计模式---简单工厂模式
    设计模式---设计模式的分类及六大原则
    分布式---Raft算法
    分布式---Paxos算法
    分布式---CAP和BASE理论
    分布式---分布式事务
    分布式---分布式锁
    css
    react生命周期
  • 原文地址:https://www.cnblogs.com/shenjianping/p/12238356.html
Copyright © 2011-2022 走看看