滚滚向前滚

导航

 

目录

参考书目: 黄靖钧. 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:~$ 
posted on 2018-05-15 12:41  滚滚向前滚  阅读(324)  评论(0编辑  收藏  举报