• Docker05 Docker容器


    目录

    参考书目: 黄靖钧. Docker从入门到实战[M]. 机械工业出版社, 2017.

    一、容器的概念

            Docker容器是镜像的运行实例。容器在镜像已有的文件层添加一层可读可写的文件层,使得容器就像是一个动态的镜像。所以,docker的内部结构必定与镜像结构十分相似。

    docker镜像结构

            如图所示,在docker容器中包含docekr镜像层以及在镜像层上建立的只读初始化层以及可读写层。在初始化层存储的大多是容器环境初始化时与容器相关的环境信息(容器主机名、主机host信息和域名服务文件)。可读写层用到了写时复制技术,虽然docker容器在可读写层可以看到数据卷的内容,但仅是挂载点,真实内容在宿主机上。

    二、容器的基本操作

    命令 说明
    attach 依附到正在运行的容器
    cp 从容器里面复制文件或者目录到宿主机文件系统或以STDOUT形式输出
    create 创建一个新的容器
    diff 检查容器的文件系统改动
    events 实时获得Docker服务器端的事件信息
    exec 在一个运行的容器里面运行命令
    export 导出容器的文件系统到一个归档文件
    kill 杀死一个运行中的容器
    logs 获取容器的日志
    pause 暂停容器内部的所有进程
    port 输出容器的端口信息
    ps 显示容器列表
    rename 重命名一个容器
    restart 重启容器
    rm 删除一个或者多个容器
    run 运行一个新容器
    start 运行一个或者多个非运行状态的容器
    stats 实时显示容器的资源使用情况
    stop 停止正在运行的容器
    top 显示容器内正在运行的进程
    unpause 恢复容器内部所有进程
    update 更新一个或多个容器的配置
    wait 阻塞指导容器停止,然后打印他的退出代码

    三、容器操作实例

    3.1 docker create

    # 创建一个容器
    gupan@ubuntu:~$ sudo docker create -it ubuntu
    Unable to find image 'ubuntu:latest' locally
    latest: Pulling from library/ubuntu
    a48c500ed24e: Pull complete 
    1e1de00ff7e1: Pull complete 
    0330ca45a200: Pull complete 
    471db38bcfbf: Pull complete 
    0b4aba487617: Pull complete 
    Digest: sha256:c8c275751219dadad8fa56b3ac41ca6cb22219ff117ca98fe82b42f24e1ba64e
    Status: Downloaded newer image for ubuntu:latest
    59df0946091d4b0408521404413e5a501977c1153667220ad28774ab290bf17a
    
    gupan@ubuntu:~$ sudo docker ps -a
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    59df0946091d        ubuntu              "/bin/bash"         2 minutes ago       Created                                 laughing_saha
    gupan@ubuntu:~$ 
    

    3.2 docker run

            启动容器有两种情况

    1. 原来没有这个容器,需要基于一个镜像启动新的容器
    2. 宿主机本来有一个容器,但是这个容器处于非运行状态,可以把这个容器启动起来

    使用docker run新建容器并启动,用这个容器来输出一句话

    # 使用docker run新建容器并启动,用这个容器来输出一句话
    gupan@ubuntu:~$ sudo docker run ubuntu /bin/echo "Hello World"
    Hello World
    
    # 查看容器状态
    gupan@ubuntu:~$ sudo docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
    9a2b868de95b        ubuntu              "/bin/echo 'Hello ..."   35 seconds ago      Exited (0) 33 seconds ago                       gallant_poitras
    59df0946091d        ubuntu              "/bin/bash"              10 minutes ago      Created                                         laughing_saha
    gupan@ubuntu:~$ 
    

    启动容器的内部运行步骤

    1. 检查本地是否存在这个镜像,如果没有就从仓库下载
    2. 如果有检查命令是否有参数冲突
    3. 利用本地镜像创建一个容器
    4. 挂载可读写层,启动容器的一系列配置(各种资源隔离操作)
    5. 在应用参数值时,如果入到参数有误,启动会终止
    6. 如果没有问题则执行应用程序,执行完毕终止容器

    案例:

    # -i 代表让容器的标准输出始终打开
    # -t 让Docker分配一个标准并绑定到容器标准输出上
    # -it 代表绑定到容器内部,因此在该终端下执行的动作会在容器内部执行
    gupan@ubuntu:~$ sudo docker run -it ubuntu bash
    root@374d959286b5:/# ps
       PID TTY          TIME CMD
         1 ?        00:00:00 bash
        10 ?        00:00:00 ps
    root@374d959286b5:/# 
    # 退出当前容器
    root@374d959286b5:/# exit
    exit
    gupan@ubuntu:~$ 
    

    后台运行容器

    d参数:代表后台运行

    sudo docker run -d nginx:alpine
    

    自动重启容器

            又是程序内部错误导致程序退出,从而波及容器进程,导致整个容器退出,所以需要让容器在意外退出时自动重启。docker提供的解决方法是在docker run后加 --restart=always

    gupan@ubuntu:~$ sudo docker run -d --restart=always ubuntu /bin/bash
    [sudo] password for gupan: 
    eea5acb7c2432250439780dca3d86d4155470f3cdf7dfd647b88798c83daa51d
    
    gupan@ubuntu:~$ sudo docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS               NAMES
    eea5acb7c243        ubuntu              "/bin/bash"              40 seconds ago      Restarting (0) 10 seconds ago                       brave_montalcini
    ab1ae8a9db39        nginx:alpine        "nginx -g 'daemon ..."   10 hours ago        Up 10 hours                     80/tcp              confident_ramanujan
    gupan@ubuntu:~$ 
    

    3.2 docker stop、docker kill

    3.2.1 docker stop

            正常情况下,docker stop会向容器发送一个SIGTERM信号,此时容器会正常退出,但有时候,容器会因各种原因对SIGTERM信号没有响应,这时候可以在docker stop后带上-t参数,指定超时多长时间后对SIGTERM信号没有响应就像向容器发送SIGKILL信号。该信号会杀死所有正在运行的容器进程

    sudo docker stop -t 3
    

    3.2.2 docker kill

            使用docker kill命令可以强制停止一个容器

    // docker kill命令语法
    docker kill <container id>
    
    // 案例
    gupan@ubuntu:~$ sudo docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                          PORTS               NAMES
    eea5acb7c243        ubuntu              "/bin/bash"              9 minutes ago       Restarting (0) 17 seconds ago                       brave_montalcini
    ab1ae8a9db39        nginx:alpine        "nginx -g 'daemon ..."   10 hours ago        Up 10 hours                     80/tcp              confident_ramanujan
    374d959286b5        ubuntu              "bash"                   10 hours ago        Exited (0) 10 hours ago                             wonderful_hermann
    6ad9de3fc9a9        ubuntu              "bash"                   10 hours ago        Exited (127) 10 hours ago                           gifted_wozniak
    36e9299c5b0b        ubuntu              "bash"                   10 hours ago        Exited (0) 10 hours ago                             wonderful_fermi
    9a2b868de95b        ubuntu              "/bin/echo 'Hello ..."   10 hours ago        Exited (0) 10 hours ago                             gallant_poitras
    59df0946091d        ubuntu              "/bin/bash"              10 hours ago        Created                                             laughing_saha
    
    gupan@ubuntu:~$ sudo docker kill eea5acb7c243
    eea5acb7c243
    gupan@ubuntu:~$ sudo docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
    eea5acb7c243        ubuntu              "/bin/bash"              14 minutes ago      Exited (0) 5 seconds ago                        brave_montalcini
    ab1ae8a9db39        nginx:alpine        "nginx -g 'daemon ..."   10 hours ago        Up 10 hours                 80/tcp              confident_ramanujan
    374d959286b5        ubuntu              "bash"                   10 hours ago        Exited (0) 10 hours ago                         wonderful_hermann
    6ad9de3fc9a9        ubuntu              "bash"                   10 hours ago        Exited (127) 10 hours ago                       gifted_wozniak
    36e9299c5b0b        ubuntu              "bash"                   10 hours ago        Exited (0) 10 hours ago                         wonderful_fermi
    9a2b868de95b        ubuntu              "/bin/echo 'Hello ..."   10 hours ago        Exited (0) 10 hours ago                         gallant_poitras
    59df0946091d        ubuntu              "/bin/bash"              11 hours ago        Created                                         laughing_saha
    gupan@ubuntu:~$ 
    

    停止所有进程:

    sudo docker kill $(docker ps -a -q)
    

    删除所有停止的进程:

    sudo docker rm $(docker ps -a -q)
    

    3.2.2 docker rm

    删除容器

    // 基本语法
    sudo docker rm <container id>
    
    -f :强制删除容器,即使容器正在运行,不加-f参数,只能删除停止的容器
    -l:删除容器和其他容器的关联,但会保留容器
    -v:删除容器的同时也删除数据卷,默认情况下容器和数据卷的生命周期是独立的
    

    3.2 docker inspect

    查看容器信息

    docker inspect的-f参数:

            docker inspect -f是按模板来使用的,更多关于模板的知识可以参照以下网址:https://golang.org/pkg/text/template/

    // 容器ubuntu中的信息
    gupan@ubuntu:~$ sudo docker inspect ubuntu
    [
        {
            "Id": "sha256:452a96d81c30a1e426bc250428263ac9ca3f47c9bf086f876d11cb39cf57aeec",
            "RepoTags": [
                "ubuntu:latest"
            ],
            "RepoDigests": [
                "ubuntu@sha256:c8c275751219dadad8fa56b3ac41ca6cb22219ff117ca98fe82b42f24e1ba64e"
            ],
            "Parent": "",
            "Comment": "",
            "Created": "2018-04-27T23:28:36.319694807Z",
            "Container": "e1a8ac8f61e4bd40dd223471e86b0328609182a3112dd45a435575753bbc7924",
            "ContainerConfig": {
                "Hostname": "e1a8ac8f61e4",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
                ],
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD ["/bin/bash"]"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:a43f69020c4ca7feb3cfb5fa5857a24b138efa953f6108975205c1f121c7c9cb",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": null,
                "OnBuild": null,
                "Labels": {}
            },
            "DockerVersion": "17.06.2-ce",
            "Author": "",
            "Config": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
                ],
                "Cmd": [
                    "/bin/bash"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:a43f69020c4ca7feb3cfb5fa5857a24b138efa953f6108975205c1f121c7c9cb",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": null,
                "OnBuild": null,
                "Labels": null
            },
            "Architecture": "amd64",
            "Os": "linux",
            "Size": 79620962,
            "VirtualSize": 79620962,
            "GraphDriver": {
                "Data": null,
                "Name": "aufs"
            },
            "RootFS": {
                "Type": "layers",
                "Layers": [
                    "sha256:65bdd50ee76a485049a2d3c2e92438ac379348e7b576783669dac6f604f6241b",
                    "sha256:ec75999a0cb1218bbfedeaf535afb516b739c0a2475f89d6c8bdf6ccfdf73c85",
                    "sha256:67885e448177114ca1d82161955ba7400139b5acc1e9cca633dfff163ccdb1b6",
                    "sha256:8db5f072feeccc451f94b357a1f596dd455859807917e7c98ed7264601043cbf",
                    "sha256:059ad60bcacfe9c03116f467f9e025f3519d1641358e0422bee478445d679313"
                ]
            }
        }
    ]
    
    
    // 获取容器中的Os的信息
    gupan@ubuntu:~$ sudo docker inspect -f "Os is :{{.Os}}" ubuntu
    Os is :linux
    gupan@ubuntu:~$ 
    
    // 获取容器中RootFS下Layers的信息
    gupan@ubuntu:~$ sudo docker inspect -f "Layers are :{{.RootFS.Layers}}" ubuntu
    Layers are :[sha256:65bdd50ee76a485049a2d3c2e92438ac379348e7b576783669dac6f604f6241b sha256:ec75999a0cb1218bbfedeaf535afb516b739c0a2475f89d6c8bdf6ccfdf73c85 sha256:67885e448177114ca1d82161955ba7400139b5acc1e9cca633dfff163ccdb1b6 sha256:8db5f072feeccc451f94b357a1f596dd455859807917e7c98ed7264601043cbf sha256:059ad60bcacfe9c03116f467f9e025f3519d1641358e0422bee478445d679313]
    gupan@ubuntu:~$ 
    

    四、进入容器内部

    4.1 docker attach

            这个命令应用于实时查看容器日志等操作

    // 基本语法
    sudo docker attach <container name>
    
    // 案例
    gupan@ubuntu:~$ sudo docker run -d --name testdemo ubuntu /usr/bin/top -b
    a1cad39488bec333d9ce9a964c18180b3bdf1db25d091768a2bb7b35c7ecce12
    gupan@ubuntu:~$ 
    
    
    // 在另一个终端依附到testdemo
    gupan@ubuntu:~$ sudo docker attach testdemo
    
    
    top - 02:49:57 up 1 day,  3:24,  0 users,  load average: 0.00, 0.00, 0.00
    Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
    %Cpu(s):  0.7 us,  0.0 sy,  0.0 ni, 99.0 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
    KiB Mem :   998408 total,   207460 free,   392320 used,   398628 buff/cache
    KiB Swap:  1046524 total,  1015828 free,    30696 used.   438424 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
         1 root      20   0   36484   3048   2700 R  0.0  0.3   0:00.02 top
    
    

    4.2 docker exec

            这个命令可以上ssh一样,直接进入到容器内部进行相关操作

    # 基本语法
    docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
    
    # docker exec命令行参数
    -d:后台运行
    -i:交互模式
    -t:分配一个tty
    -u:指定用户和用户组<nameuid>[:<groupid>]
    --privileged:参数会分配一个特权给tty界面,相当于拥有宿主机的root权限,慎用
    

    案例:

    在一个终端启动容器
    gupan@ubuntu:~$ sudo docker run -it --name test ubuntu bash
    root@0071d6bbab54:/# 
    
    在另一个终端使用docker exec进入容器
    gupan@ubuntu:~$ sudo docker exec -it test bash
    root@0071d6bbab54:/# 
    

    4.3 docker nsenter

           一个第三方工具,可以方便的进入容器,当然,功能不止于此,可以通过shell脚本将使用nsenter进入容器繁琐的操作简化。脚本地址:https://github.com/jpetazzo/nsenter/blob/master/docker-enter,使用方式为: ./docker-enter <container_name_or_ID>脚本内容如下:

    #!/bin/sh
    
    if [ -e $(dirname "$0")/nsenter ]; then
        # with boot2docker, nsenter is not in the PATH but it is in the same folder
        NSENTER=$(dirname "$0")/nsenter
    else
        NSENTER=nsenter
    fi
    
    if [ -e $(dirname "$0")/importenv ]; then
        # with boot2docker, importenv is not in the PATH but it is in the same folder
        IMPORTENV=$(dirname "$0")/importenv
    else
        IMPORTENV=importenv
    fi
    
    if [ -z "$1" ]; then
        echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]"
        echo ""
        echo "Enters the Docker CONTAINER and executes the specified COMMAND."
        echo "If COMMAND is not specified, runs an interactive shell in CONTAINER."
        exit
    fi
    
    PID=$(docker inspect --format "{{.State.Pid}}" "$1")
    [ -z "$PID" ] && exit 1
    shift
    
    if [ "$(id -u)" -ne "0" ]; then
        which sudo > /dev/null
        if [ "$?" -eq "0" ]; then
          LAZY_SUDO="sudo "
        else
          echo "Warning: Cannot find sudo; Invoking nsenter as the user $USER." >&2
        fi
    fi
    
    ENVIRON="/proc/$PID/environ"
    
    # Prepare nsenter flags
    OPTS="--target $PID --mount --uts --ipc --net --pid --"
    
    # env is to clear all host environment variables and set then anew
    if [ $# -lt 1 ]; then
        # No arguments, default to `su` which executes the default login shell
        $LAZY_SUDO "$IMPORTENV" "$ENVIRON" "$NSENTER" $OPTS su -m root
    else
        # Has command
        # "$@" is magic in bash, and needs to be in the invocation
        $LAZY_SUDO "$IMPORTENV" "$ENVIRON" "$NSENTER" $OPTS "$@"
    fi
    

    五、容器导入和导出

    5.1 导出容器

            导出容器是把容器导出到一个归档文件中,不管容器处于运行还是停止状态都可以导出容器,容器导出可以把文件的可读可写文件层也打包进去,但是不会把Volume的内容包括进来。

    # 案例:虽然看不懂
    # 在容器内部创建一个文件test
    gupan@ubuntu:~$ sudo docker exec -it test sh
    [sudo] password for gupan: 
    # touch test
    # exit
    
    # 导出容器
    gupan@ubuntu:~$ sudo docker export test > test.tar
    gupan@ubuntu:~$ ls
    Desktop                                             Documents  examples.desktop  Pictures  Templates  Videos
    docker-engine_17.05.0_ce-0_ubuntu-xenial_amd64.deb  Downloads  Music             Public    test.tar
    gupan@ubuntu:~$ 
    

    5.2 导入容器

            导入容器会变成一个镜像,启动这个镜像才可以恢复容器。

    # 导入容器语法
    docker import tar包包名(还可以采用网址的形式)
    
    # 但是用上述方法生成的镜像是没有标签的,如果想要生成标签,可以使用管道命令
    gupan@ubuntu:~$ cat test.tar | sudo docker import - gupan/test:latest
    [sudo] password for gupan: 
    sha256:aec228c185c9e570026610eb1b422d95423e4dba80f1e981243ee5e1291553ab
    gupan@ubuntu:~$ sudo docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    gupan/test          latest              aec228c185c9        26 seconds ago      69.8MB
    ubuntu              latest              452a96d81c30        2 weeks ago         79.6MB
    hello-world         latest              e38bc07ac18e        4 weeks ago         1.85kB
    nginx               alpine              ebe2c7c61055        4 weeks ago         18MB
    gupan@ubuntu:~$ 
    

    --message参数

            --message可以添加commit的信息

    --change参数

            --change可以在原有的Dockerfile后面追加指令

    gupan@ubuntu:~$ cat test.tar | sudo docker import --change "CMD cat /etc/hosts" - gupan/test:latest
    sha256:cc19a900cb5515e7213bc5e7098544810fc9c9d3ad4c12d9ec69bef3b64f46a5
    gupan@ubuntu:~$ sudo docker run gupan/test:latest
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    172.17.0.4	7d7369b6e7ea
    gupan@ubuntu:~$ 
    
  • 相关阅读:
    使用AnsyncTask异步类从网络上下载图片
    fibonacci分治求法
    JavaScript
    JavaScript
    JavaScript
    JavaScript
    yarn安装vue后,报“文件名、目录名或卷标语法不正确。”
    VIM-Plug安装插件时,频繁更新失败,或报端口443被拒绝等
    Node.js Windows Binary二进制文件安装方法
    Linux常用命令
  • 原文地址:https://www.cnblogs.com/gupan/p/9040418.html
Copyright © 2020-2023  润新知