容器监控

Docker自带的监控子命令

ps

docker ps 是我们早已熟悉的命令了,方便我们查看当前运行的容器。前面已经有大量示例,这里就不赘述了。

[root@docker ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                   NAMES
9f8bc2c3a5c7   nginx          "/docker-entrypoint.…"   3 seconds ago    Up 2 seconds    80/tcp                                  sad_faraday
1e0b0631cf70   httpd:centos   "/bin/sh -c '/usr/sb…"   23 minutes ago   Up 23 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp       myweb
4b78f371fc06   centos:ssh     "/usr/sbin/sshd -D"      32 minutes ago   Up 32 minutes   0.0.0.0:2022->22/tcp, :::2022->22/tcp   sshtest

top

查看容器的进程

[root@docker ~]# docker top --help

Usage:  docker top CONTAINER [ps OPTIONS]

Display the running processes of a container

Aliases:
  docker container top, docker top

示例:

[root@docker ~]# docker top sshtest    #sshtest是容器名
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                5220                5198                0                   21:31               ?                   00:00:00            /usr/sbin/sshd -D

命令后面还可以跟上 Linux 操作系统 ps 命令的参数显示特定的信息,比如 -au。

[root@docker ~]# docker top sshtest -au
USER                PID                 %CPU                %MEM                VSZ                 RSS                 TTY                 STAT                START               TIME                COMMAND
root                5220                0.0                 0.0                 76532               7080                ?                   Ss                  21:31               0:00                /usr/sbin/sshd -D

stats

列出容器资源使用率

[root@docker ~]# docker stats --help

Usage:  docker stats [OPTIONS] [CONTAINER...]

Display a live stream of container(s) resource usage statistics

Aliases:
  docker container stats, docker stats

Options:
  -a, --all             Show all containers (default shows just running)
      --format string   Format output using a custom template:
                        'table':            Print output in table format with column headers (default)
                        'table TEMPLATE':   Print output in table format using the given Go template
                        'json':             Print in JSON format
                        'TEMPLATE':         Print output using the given Go template.
                        Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates
      --no-stream       Disable streaming stats and only pull the first result
      --no-trunc        Do not truncate output

示例:

[root@docker ~]# docker stats
CONTAINER ID   NAME          CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O         PIDS
9f8bc2c3a5c7   sad_faraday   0.00%     5.141MiB / 15.36GiB   0.03%     866B / 0B        8.19kB / 26.6kB   5
1e0b0631cf70   myweb         0.06%     38.39MiB / 15.36GiB   0.24%     1.64kB / 609B    0B / 0B           213
4b78f371fc06   sshtest       0.00%     2.258MiB / 15.36GiB   0.01%     9.7kB / 7.99kB   8.19kB / 23.6kB   1

默认会显示一个实时变化的列表,展示每个容器的 CPU 使用率,内存使用量和可用量,网络和磁盘的 IO 数据。

注意:容器启动时如果没有特别指定内存 limit,stats 命令会显示 host 的内存总量,但这并不意味着每个 container 都能使用到这么多的内存。

cAdvisor

cAdvisor 是 google 开发的容器监控工具。

[root@docker ~]# docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest

也可以使用镜像hub.c.163.com/xbingo/cadvisor:latest。

通过 http://[Host_IP]:8080 访问 cAdvisor。首次打开比较慢,系统需要收集数据并绘制图表。

总结:

  • 缺点:操作界面略显简陋,而且需要在不同页面之间跳转,并且只能监控一个 host。
  • 优点:可以将监控到的数据导出给第三方工具,由这些工具进一步加工处理。

结论:我们把 cAdvisor 定位为一个监控数据收集器,并导出数据给第三方工具,而非展示数据。


容器日志

Docker logs

对于一个运行的容器,Docker 会将日志发送到 容器标准输出设备(STDOUT)和标准错误设备(STDERR),STDOUT 和 STDERR 实际上就是容器的控制台终端。

举个例子,用下面的命令运行 httpd 容器:

[root@docker ~]# docker run -p 80:80 httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[Tue Oct 08 14:28:10.312876 2024] [mpm_event:notice] [pid 1:tid 1] AH00489: Apache/2.4.62 (Unix) configured -- resuming normal operations
[Tue Oct 08 14:28:10.316058 2024] [core:notice] [pid 1:tid 1] AH00094: Command line: 'httpd -D FOREGROUND'

我们在启动日志的时候没有用 -d 参数,httpd 容器以前台方式启动,日志会直接打印在当前的终端窗口。

如果加上 -d 参数以后台方式运行容器,我们就看不到输出的日志了。

[root@docker ~]# docker run -d -p 80:80 httpd
a8286845e6f8afc09fdcdf0b94248239963e3ad04495e927a68a2148814c65fd

这种情况下如果要查看容器的日志,有两种方法:

  1. attach 到该容器。
  2. 用 docker logs 命令查看日志。

先来看 attach 的方法。运行 docker attach 命令。

[root@docker ~]# docker attach a8286845e6f8

attach 到了 httpd 容器,但并没有任何输出,这是因为当前没有新的日志信息。

为了产生一条新的日志,可以在 host 的另一个命令行终端执行 curl localhost。

终端B:

[root@docker ~]# curl localhost
<html><body><h1>It works!</h1></body></html>
[root@docker ~]# curl localhost
<html><body><h1>It works!</h1></body></html>

这时,attach 的终端就会打印出新的日志。

终端A:

[root@docker ~]# docker attach a8286845e6f8
172.17.0.1 - - [08/Oct/2024:14:30:24 +0000] "GET / HTTP/1.1" 200 45
172.17.0.1 - - [08/Oct/2024:14:30:25 +0000] "GET / HTTP/1.1" 200 45

attach 的方法在实际使用中不太方便,因为:

  1. 只能看到 attach 之后的日志,以前的日志不可见。
  2. 退出 attach 状态比较麻烦(Ctrl+p 然后 Ctrl+q 组合键),一不小心很容器将容器杀掉(比如按下 Ctrl+C)。

查看容器日志推荐的方法是用 docker logs 命令。

[root@docker ~]# docker logs a8286845e6f8
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[Tue Oct 08 14:28:33.168712 2024] [mpm_event:notice] [pid 1:tid 1] AH00489: Apache/2.4.62 (Unix) configured -- resuming normal operations
[Tue Oct 08 14:28:33.168801 2024] [core:notice] [pid 1:tid 1] AH00094: Command line: 'httpd -D FOREGROUND'
[Tue Oct 08 14:29:37.160729 2024] [mpm_event:notice] [pid 1:tid 1] AH00491: caught SIGTERM, shutting down
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[Tue Oct 08 14:30:08.379226 2024] [mpm_event:notice] [pid 1:tid 1] AH00489: Apache/2.4.62 (Unix) configured -- resuming normal operations
[Tue Oct 08 14:30:08.379375 2024] [core:notice] [pid 1:tid 1] AH00094: Command line: 'httpd -D FOREGROUND'
172.17.0.1 - - [08/Oct/2024:14:30:24 +0000] "GET / HTTP/1.1" 200 45
172.17.0.1 - - [08/Oct/2024:14:30:25 +0000] "GET / HTTP/1.1" 200 45
[Tue Oct 08 14:31:35.664386 2024] [mpm_event:notice] [pid 1:tid 1] AH00491: caught SIGTERM, shutting down
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[Tue Oct 08 14:31:41.995159 2024] [mpm_event:notice] [pid 1:tid 1] AH00489: Apache/2.4.62 (Unix) configured -- resuming normal operations
[Tue Oct 08 14:31:41.995339 2024] [core:notice] [pid 1:tid 1] AH00094: Command line: 'httpd -D FOREGROUND'
172.17.0.1 - - [08/Oct/2024:14:30:24 +0000] "GET / HTTP/1.1" 200 45
172.17.0.1 - - [08/Oct/2024:14:30:25 +0000] "GET / HTTP/1.1" 200 45

docker logs 能够打印出自容器启动以来完整的日志,并且 -f 参数可以继续打印出新产生的日志,效果上与 Linux 命令 tail -f 一样。


Docker-compose

Docker Compose 可以轻松、高效地管理容器,它是一个用于定义和运行多容器的管理工具。

它通过一个单独的 docker-compose.yml 模板文件(YAML 格式)定义一组相关联资源集。

Compose 中有两个重要的概念:

  • 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。

Compose 项目由 Python 编写(后用Go语言重写),实现上调用了 Docker 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理。

命令说明

[root@docker ~]# docker compose -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker compose [OPTIONS] COMMAND

Define and run multi-container applications with Docker

Options:
      --all-resources              Include all resources, even those not used by services
      --ansi string                Control when to print ANSI control characters ("never"|"always"|"auto") (default "auto")
      --compatibility              Run compose in backward compatibility mode
      --dry-run                    Execute command in dry run mode
      --env-file stringArray       Specify an alternate environment file
  -f, --file stringArray           Compose configuration files
      --parallel int               Control max parallelism, -1 for unlimited (default -1)
      --profile stringArray        Specify a profile to enable
      --progress string            Set type of progress output (auto, tty, plain, quiet) (default "auto")
      --project-directory string   Specify an alternate working directory
                                   (default: the path of the, first specified, Compose file)
  -p, --project-name string        Project name

Commands:
  attach      Attach local standard input, output, and error streams to a service's running container
  build       Build or rebuild services
  config      Parse, resolve and render compose file in canonical format
  cp          Copy files/folders between a service container and the local filesystem
  create      Creates containers for a service
  down        Stop and remove containers, networks
  events      Receive real time events from containers
  exec        Execute a command in a running container
  images      List images used by the created containers
  kill        Force stop service containers
  logs        View output from containers
  ls          List running compose projects
  pause       Pause services
  port        Print the public port for a port binding
  ps          List containers
  pull        Pull service images
  push        Push service images
  restart     Restart service containers
  rm          Removes stopped service containers
  run         Run a one-off command on a service
  scale       Scale services
  start       Start services
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop services
  top         Display the running processes
  unpause     Unpause services
  up          Create and start containers
  version     Show the Docker Compose version information
  wait        Block until the first service container stops
  watch       Watch build context for service and rebuild/refresh containers when files are updated

Run 'docker compose COMMAND --help' for more information on a command.

version

[root@docker ~]# docker compose version
Docker Compose version v2.27.0

Compose 模板

模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多。但大家不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的。

默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。

模板文件结构

  • version:用来定义模板文件的版本,不同版本的模板,格式也不一样。
  • 资源列表:用来定义资源清单,包括service、secret、network、volume等。
  • 注释行: # 开头的注释行。

示例:使用版本2模板,定义一个使用httpd镜像的services。

version: "2"

services:
  webapp:
    image: httpd

实战-Wordpress

# 删除之前的环境
[root@docker ~]# docker rm -f $(docker ps -aq)

# 通过docker compose实现多个容器一起启动
[root@docker ~]# mkdir wordpress
[root@docker ~]# cd wordpress/
[root@docker wordpress]# vim docker-compose.yml
services:
  blog:                                  #服务名字,相当于docker run的时候指定的一个名称
      image: wordpress:latest            #必选,镜像的名字
      restart: always
      links:
            - db
      ports:                            #可选,等价于 docker run 里的 -p 选项指定端口映射
            - "80:80"
      environment:           #可选,等价于 docker run 里的 --env 选项设置环境变量
            - WORDPRESS_DB_HOST=db
            - WORDPRESS_DB_USER=root
            - WORDPRESS_DB_PASSWORD=huawei
            - WORDPRESS_DB_NAME=wordpress

  db:
      image: mysql:latest
      restart: always
      environment:
            - MYSQL_ROOT_PASSWORD=huawei
            - MYSQL_DATABASE=wordpress
            
[root@docker wordpress]# docker compose config -q    #检测语法

后端运行

[root@docker wordpress]# docker compose up -d
[+] Running 3/3
 ✔ Network wordpress_default   Created     0.0s                                                                                 
 ✔ Container wordpress-db-1    Started     0.3s                                                                                 
 ✔ Container wordpress-blog-1  Started     0.6s                                                                           

查看现象

[root@docker wordpress]# docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED              STATUS              PORTS                               NAMES
85b438b2ff89   wordpress:latest   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp, :::80->80/tcp   wordpress-blog-1
3c340ed1e299   mysql:latest       "docker-entrypoint.s…"   About a minute ago   Up About a minute   3306/tcp, 33060/tcp                 wordpress-db-1

综合实验

构建WordPress

通过WordPress和mysql镜像构建WordPress应用。

下载镜像:

[root@docker ~]# docker pull mysql
[root@docker ~]# docker pull wordpress

创建mysql容器,并创建wordpress数据库:

[root@docker ~]# docker run -d -p 3306:3306 \
-v /mysql:/var/lib/mysql:z \
--name mysql \
-e MYSQL_ROOT_PASSWORD=huawei \
-e MYSQL_DATABASE=wordpress \
mysql
6dd12147c9156055042587950e23d543cca47617c3a82bef14c58ffe90580301

[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
6dd12147c915   mysql     "docker-entrypoint.s…"   15 seconds ago   Up 14 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql

创建WordPress容器:

[root@docker ~]# docker inspect mysql|grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
[root@docker ~]# docker run -d -p 80:80 -v /www:/var/www/html:z \
--name wordpress \
-e WORDPRESS_DB_HOST=172.17.0.2 \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_PASSWORD=huawei \
-e WORDPRESS_DB_NAME=wordpress \
wordpress
63fa3a61f9bae2a03f3c0c21b574cca75c9a58c5c2645a6f702179c63f5f06eb

说明:

-e WORDPRESS_DB_HOST=... (defaults to the IP and port of the linked mysql container)

-e WORDPRESS_DB_USER=... (defaults to “root”)

-e WORDPRESS_DB_PASSWORD=... (defaults to the value of the MYSQL_ROOT_PASSWORD environment variable from the linked mysql container)

-e WORDPRESS_DB_NAME=... (defaults to “wordpress”)

更多推荐