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:~$ 
原文地址:https://www.cnblogs.com/gupan/p/9040418.html