Docker使用笔记(二)Docker容器简单使用

在上一节讲了如何安装docker以及一些配置的更改,本节将会初步介绍docker容器的使用。

1、运行我们的第一个容器

现在, 让我们尝试启动第一个Docker容器。 我们可以使用docker run命令创建容器。docker run命令提供了Docker容
器的创建到启动的功能。

[05:37 shexuan@hulab ~]$ docker run --name bob_the_container -i -t ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
Trying to pull repository docker.io/library/ubuntu ...
latest: Pulling from docker.io/library/ubuntu
473ede7ed136: Pull complete
c46b5fa4d940: Pull complete
93ae3df89c92: Pull complete
6b1eed27cade: Pull complete
Digest: sha256:29934af957c53004d7fb6340139880d23fb1952505a15d69a03af0d1418878cb
Status: Downloaded newer image for docker.io/ubuntu:latest
root@9edcf79a4252:/#

上面命令启动运行了一个容器,并指定了多个参数:

  • run docker run用来启动一个容器;
  • --name 为我们运行的容器指定一个名字,不指定的话则系统会生成一个名称;
  • -i -i标志保证容器中STDIN是开启的, 尽管我们并没有附着到容器中。 持久的标准输入是交互式shell的“半边天”;
  • -t -t标志则是另外“半边天”, 它告诉Docker为要创建的容器分配一个伪tty终端;
  • /bin/bash 为运行的容器执行的第一个命令,这个命令启动了一个Bash shell。

在很多Docker命令中, 都可以用容器的名称来替代容器ID, 后面我们将会看到。 容器名称有助于分辨容器, 当构建容器和应用程序之间的逻辑连接时, 容器的名称也有助于从逻辑上理解连接关系。 具体的名称(如web、 db) 比容器ID和随机容器名好记多了。 我推荐大家都使用容器名
称, 以更加方便地管理容器。

容器的命名必须是唯一的。 如果试图创建两个名称相同的容器, 则命令将会失败。 如果要使用的容器名称已经存在, 可以先用docker rm命令删除已有的同名容器后, 再来创建新的容器。

最后,输入exit可以退出当前容器。
若想在退出容器后自动删除容器,还可以加上--rm参数。

如果由于某种错误而导致容器停止运行,还可以通过--restart标志,让Docker自动重新启动该容器。 --restart标志会检查容器的退出代码, 并据此来决定是否要重启容器。 默认的行为是Docker不会重启容器。

$ docker run --restart=always --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

在本例中, --restart标志被设置为always。 无论容器的退出代码是什么, Docker都会自动重启该容器。 除了always, 还可以将这个标志设为on-failure, 这样, 只有当容器的退出代码为非0值的时候, 才会自动重启。 另外, on-failure还接受一个可选的重启次数参数。

# 当容器退出代码为非0时, Docker会尝试自动重启该容器, 最多重启5次。
$ docker run --restart=on-failure:5 --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
2、重新启动已经停止的容器

在上面输入exit后bob_the_container容器已经停止了, 接下来我们能对它做些什么呢? 如果愿意, 我们可以用start命令重新启动一个已经停止的容器。

[21:03 shexuan@hulab ~]$ docker start bob_the_container
bob_the_container
# 也可以通过ID来指定容器
[21:09 shexuan@hulab ~]$ docker start 22e568aab98b
22e568aab98b

Docker容器重新启动的时候, 会沿用docker run命令时指定的参数来运行, 因此我们的容器重新启动后会运行一个交互式会话shell。 此外,也可以用docker attach命令, 重新附着到该容器的会话上。

# 先启动停止了的容器
[21:26 shexuan@hulab ~]$ docker start bob_the_container
bob_the_container
#  使用attach命令重新附着到该容器的会话上
[21:26 shexuan@hulab ~]$ docker attach bob_the_container
root@22e568aab98b:/#
3、创建守护式容器

除了这些交互式运行的容器(interactive container) , 也可以创建长期运行的容器。 守护式容器(daemonized container) 没有交互式会话, 非常适合运行应用程序和服务。
使用-d参数, Docker会将容器放到后台运行:

[21:33 shexuan@hulab ~]$ docker run --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
42b18316632c701e2ce266e49313cc274963b0bbb2241353da0f11526d403317

上面的命令创建了一个后台运行的容器,我们还在容器里运行了一个while 循环,该循环会一直打印hello world,知道该容器或进程停止运行。

使用docker ps我们可以看到一个正在运行的容器:

[21:33 shexuan@hulab ~]$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
42b18316632c        ubuntu              "/bin/sh -c 'while..."   4 minutes ago       Up 4 minutes                            daemon_dave

使用docker logs可以查看该容器的内部运行情况,或称日志:

[21:40 shexuan@hulab ~]$ docker logs daemon_dave
hello world
hello world
hello world
...
# 加上-f 参数来监控最新日志,这个参数类似于tail -f 命令的作用
[21:40 shexuan@hulab ~]$ docker logs -f daemon_dave
hello world
hello world
hello world
...
# 还可以使用--tail 参数来指定获取日志最后指定行数
[21:45 shexuan@hulab ~]$ docker logs --tail 3 daemon_dave
hello world
hello world
hello world
# 最后你还可以组合使用--tail和-f命令来获取容器的最新日志而不必读取整个日志文件
[21:52 shexuan@hulab ~]$ docker logs --tail 3 -ft daemon_dave
2018-11-06T02:53:01.314952000Z hello world
2018-11-06T02:53:02.316191000Z hello world
2018-11-06T02:53:03.317513000Z hello world
2018-11-06T02:53:04.318959000Z hello world
# -t参数会输出时间戳使得看起来更方便

在上面我们简要介绍了如何使用docker logs来查看守护式容器的内部运行情况,获取其日志文件:

  • -f -f参数类似于tail -f,会不断刷新输出最新日志;
  • --tail输出日志的最后几行;
  • --tail number -f 输出最后指定行数日志并不断刷新输出最新日志;
  • -t 给日志加上时间戳。

最后,可以使用docker stop停止运行守护式容器:

[22:04 shexuan@hulab ~]$ docker stop daemon_dave
daemon_dave

docker stopdocker kill都可以停止运行守护式容器,但是略有区别:

  • docker stop,支持“优雅退出”。先发送SIGTERM信号,在一段时间之后(10s)再发送SIGKILL信号。Docker内部的应用程序可以接收SIGTERM信号,然后做一些“退出前工作”,比如保存状态、处理当前请求等;
  • docker kill,发送SIGKILL信号,应用程序直接退出。

更多docker日志配置可查看更改docker的日志引擎为 journald。

4、查看容器内部进程及统计信息

除了容器的日志, 也可以查看容器内部运行的进程。 要做到这一点, 要使用docker top命令:

[22:31 shexuan@hulab ~]$ docker top daemon_dave
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                10317               10299               0                   22:31               ?                   00:00:00            /bin/sh -c while true; do echo hello world; sleep 1; done
root                10466               10317               0                   22:31               ?                   00:00:00            sleep 1

该命令执行后, 可以看到容器内的所有进程(主要还是我们的while循环) 、 运行进程的用户及进程ID。

除了查看进程信息外,还可以通过docker stats来查看一个或多个容器的统计信息:

[22:37 shexuan@hulab ~]$ docker stats daemon_dave
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
daemon_dave         0.13%               952 KiB / 251.6 GiB   0.00%               648 B / 648 B       0 B / 0 B           2

我们能看到一个守护式容器的列表, 以及它们的CPU、 内存、 网络I/O及存储I/O的性能和指标。 这对快速监控一台主机上的一组容器非常有用。

5、在容器中创建新的进程

通过docker exec命令可以在容器内部额外启动新进程。 可以在容器内运行的进程有两种类型: 后台任务和交互式任务。 后台任务在容器内运行且没有交互需求, 而交互式任务则保持在前台运行。

[22:55 shexuan@hulab ~]$ docker exec -d daemon_dave touch /etc/new_config_file

这里的-d标志表明需要运行一个后台进程, -d标志之后, 指定的是要在内部执行这个命令的容器的名字以及要执行的命令。 上面例子中的命令会在daemon_dave容器内创建了一个空文件, 文件名为/etc/new_config_file。 通过docker exec后台命令, 可以在正在运行的容器中进行维护、 监控及管理任务。

我们也可以在daemon_dave容器中新打开一个shell的交互式任务:

[22:55 shexuan@hulab ~]$ docker exec -t -i daemon_dave /bin/bash
root@42b18316632c:/#

和启动容器时候一样,这里的-i -t为我们执行的进程创建了TTY并捕捉STDIN。最后的/bin/bash为一个新创建的shell。

run, attach, exec的区别:

  • docker run通常是在新创建的容器中所使用的命令。 它适用于在没有其他容器运行的情况下,您想要创建一个容器,并且要启动它,然后在其上运行一个进程;
  • docker exec适用于在现有容器中运行命令的情况。如果您已经拥有了一个正在运行的容器,并希望更改该容器或从中获取某些内容,那么使用“docker exec”命令就非常合适了;
  • docker attach也是相当于继续运行已有的容器,但是并不会另外启动一个进程,而是以初始docker run启动命令的会话上。
6、深入了解容器信息

除了通过docker ps命令获取容器的信息, 还可以使用docker inspect来获得更多的容器信息。

[00:49 shexuan@hulab ~]$ docker inspect daemon_dave
[
    {
        "Id": "42b18316632c701e2ce266e49313cc274963b0bbb2241353da0f11526d403317",
        "Created": "2018-11-06T02:33:42.333222931Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while\ntrue; do echo hello world; sleep 1; done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 10317,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2018-11-06T03:31:21.144011748Z",
            "FinishedAt": "2018-11-06T03:05:00.01247215Z"
        },
        "Image": "sha256:ea4c82dcd15a33e3e9c4c37050def20476856a08e59526fbe533cc4e98387e39",
...
]

docker inspect命令会对容器进行详细的检查, 然后返回其配置信息, 包括名称、命令、网络配置、基础镜像以及很多有用的数据。

也可以用-f或者--format标志来选定查看结果:

[00:53 shexuan@hulab ~]$ docker inspect --format='{{ .State.Running }}' daemon_dave
false

docker inspect支持同时指定多个容器, 并显示每个容器的输出结果。

7、删除容器

如果容器已经不再使用(已停止使用), 可以使用docker rm命令来删除它们。如果想删除正在运行的容器,可以加上-f参数。

[00:58 shexuan@hulab ~]$ docker rm daemon_dave
daemon_dave

目前, 还没有办法一次删除所有容器,但是可以通过下面的小技巧来一次性删除所有容器:

[01:02 shexuan@hulab ~]$ docker rm `sudo docker ps -a -q`
9f0b544d3573
22e568aab98b

上面的docker ps命令会列出现有的全部容器, -a标志代表列出所有容器, 而-q标志则表示只需要返回容器的ID而不会返回容器的其他信息。这样我们就得到了容器ID的列表, 并传给了docker rm命令, 从而达到删除所有容器的目的。

参考:
《第一本docker书》

你可能感兴趣的:(Docker使用笔记(二)Docker容器简单使用)