Docker08-docker调优/管理/监控

容器=cgroup+namespace_rootfs+容器引擎

docker 实战 https://blog.csdn.net/woniu211111/article/details/108675525

docker compose https://blog.csdn.net/pushiqiang/article/details/78682323

rootfs

文件系统隔离
容器引擎:生命周期控制

namespace

主要用来访问隔离。原理是针对一类资源进行抽象,并将其封装在一起提供给一个容器使用,对于这类资源,
因为每个容器都有自己的抽象,而它们彼此之间是不可见的,所以就可以做到隔离

cgroup

cgroup 是 Linux 内核的一个重要特性,用于限制、管理和监控进程组的资源使用。在容器技术中,cgroup 被广泛用于限制容器的资源使用,如 CPU、内存、磁盘 I/O 和网络带宽等。通过合理配置 cgroup,可以有效地管理容器的资源使用,确保系统的稳定性和可预测性。

容器中的 cgroup 应用

CPU 限制:
通过 cgroup 可以为容器分配特定的 CPU 核心或 CPU 时间片。
这使得可以在多个容器之间公平地分配 CPU 资源,防止某个容器占用过多的 CPU 资源影响其他容器或系统。

内存限制:
cgroup 允许为容器设置内存限制,防止容器使用过多的系统内存,导致系统性能下降或因内存耗尽而崩溃。
通过 cgroup,可以限制容器的内存使用量,并在达到限制时触发内存回收或容器终止。

磁盘 I/O 控制:
使用 cgroup,可以限制容器对磁盘的输入输出操作。这使得可以控制容器的磁盘访问速率,
防止某个容器占用过多的磁盘 I/O 资源,影响其他容器的性能或系统的响应速度。

网络带宽控制:
虽然 Docker 容器默认不使用 cgroup 控制网络带宽,但是可以通过其他工具(如 tc 命令)
结合 cgroup 实现对容器的网络带宽控制。这使得可以限制容器的网络流量,防止某个容器占用过多的网络带宽,
影响其他容器或系统的网络通信。

cgroup 在容器中的实现
在容器技术中,cgroup 通常由容器运行时(如 Docker 或 Kubernetes)负责管理和应用。
当启动一个容器时,容器运行时会创建一个或多个 cgroup 来限制容器的资源使用。
容器运行时会根据容器的配置(如 CPU 限制、内存限制等)自动创建相应的 cgroup,并将容器的进程添加到这些 cgroup 中。

linux会为每个容器创建一个cgroup目录(/sys/fs/cgroup/cpu/docker/container_id),以容器的长ID命名
mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset
mkdir /sys/fs/cgroup/cpuset/child    # 创建cgroup
echo $$ > /sys/fs/cgroup/cpuset/child/tasks   # 通过将当前进程ID写入tasks文件,就可以将进程移动到这个cgroup

也可以将进程ID写入cgroup.procs
写入tasks文件,只会将指定进程放入cgroup
写入cgroup.procs,会将进程所属的线程也放入child中

清理占用的磁盘空间

docker system df       类似linux中的df,可查看docker镜像和容器的数量以及占用磁盘大小
docker system prune    用于清理磁盘,删除关闭的容器,删除无用的数据卷和网络,删除没有tag的镜像
docker system prune -a    清理更加彻底,可以将没有容器使用的镜像也删除

监控Docker

docker监控子命令

docker ps
docker top
docker stats
docker events

sysdig

Sysdig是一种功能强大的系统监控工具,也可以用于监控和调试容器化环境,包括 Docker。

# 运行sysdig
docker run -it--rm--name=sysdig privileged=true \
--volume=/var/run/docker.sock:/host/var/run/docker.sock \
--volume=/dev:/host/dev \
--volume=/proc:/host/proc:ro \
--volume=/boot:/host/boot:ro \
--volume=/lib/modules:/host/lib/modules:ro \
--volume=/usr:/host/usr:ro \
sysdig/sysdig

指定volume和privileged是为了使sysdig获得足够多的系统信息

通过docker exec -it sysdig bash进入容器,执行csysdig以交互方式启动sysdig

进入容器后,执行这个命令将以实时方式显示容器的CPU使用情况
sysdig -pc -c topcontainers_cpu

Docker日志管理

docker logs

将容器日志发送到STDOUT和STDERR

docker logs -f container_name
-f:持续输出docker 日志,类似 tail -f

docker logging driver

  • docker默认的 logging driver 是 json-file。
  • json-file会将容器的日志保存在json文件中。Docker负责格式化其内容并输出到STDOUT和STDERR
  • 在Host的容器目录中找到这个文件,容器路径为/var/lib/docker/containers/contariner_ID/contariner_ID-json.log。

docker还支持其他多种logging driver,例如

  • none 是 disable 容器日志功能。
  • syslog 和 jourald 是 Linux 上的两种日志管理服务。
  • awslogs、splunk 和 gcplogs 是第三方日志托管服务。
docker info | grep "Logging Driver"  # 查看logging driver

修改 Docker 容器的日志驱动器(log driver)

# 在启动容器时指定日志驱动器
docker run -it --name my_container --log-driver syslog ubuntu
# 也可以指定日志选项(log options):
docker run -it --name my_container --log-driver syslog \
--log-opt syslog-address=tcp://192.168.0.42:123 ubuntu

#编辑 Docker 的配置文件设置默认的日志驱动器,这样启动的所有容器都会使用该日志驱动器。
vim /etc/docker/daemon.json:
{
  "log-driver": "syslog",
  "log-opts": {
    "syslog-address": "tcp://192.168.0.42:123"
  }
}

systemctl restart docker

# 对于已经运行的容器,无法直接修改其日志驱动器。你需要停止并重新创建容器,指定新的日志驱动器。

日志监控-ELK

见Elastic stack篇

日志监控-Fluentd

Fluentd是一个开源的数据收集器,支持上百种plugin,可以连接各种数据源和数据输出组件
可以用Filebeat将Fluentd收集的容器日志转发给Elasticsearch
fluent-plugin-elasticsearch插件可以让Fluentd直接将日志发送给Elasticsearch

使用Fluentd、Filebeat、Fluentd、Elasticsearch、Kibana监控容器日志

创建docker compose文件

# 创建一个 Docker Compose 文件 docker-compose.yml,配置 Fluentd、Elasticsearch、Kibana 和容器。

version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.13.1
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
    volumes:
      - esdata:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
      - "9300:9300"

  kibana:
    image: docker.elastic.co/kibana/kibana:7.13.1
    container_name: kibana
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch
    environment:
      ELASTICSEARCH_URL: http://elasticsearch:9200

  fluentd:
    image: fluent/fluentd:latest
    container_name: fluentd
    build:
      context: ./fluentd
    volumes:
      - ./fluentd/conf:/fluentd/etc
    ports:
      - "24224:24224"
      - "24224:24224/udp"
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:7.13.1
    container_name: filebeat
    volumes:
      # filebeat的配置文件
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml
      # 这个挂载用于让 Filebeat 可以监视 Docker 容器日志
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      # 允许与Docker引擎通信。将套接字挂载到容器中,Filebeat可以获取有关 Docker 容器的信息。
      - /var/run/docker.sock:/var/run/docker.sock
    command: ["-e", "-strict.perms=false", "-E", "output.elasticsearch.hosts=['elasticsearch:9200']"]
    depends_on:
      - elasticsearch

  myapp:
    image: yourappimage
    container_name: myapp
    logging:
      driver: fluentd
      options:
        fluentd-address: localhost:24224
        tag: docker.myapp

# 指定容器卷
volumes:
  esdata:
    driver: local

配置 Fluentd

创建 fluentd 目录并在该目录中创建 Dockerfile 和配置文件 fluent.conf。

vim /path/to/fluentd/Dockerfile

FROM fluent/fluentd:v1.12-1
USER root
RUN ["gem", "install", "fluent-plugin-elasticsearch", "--no-rdoc", "--no-ri", "--version", "4.0.7"]
COPY fluent.conf /fluentd/etc/fluent.conf
USER fluent

vim /path/to/fluentd/fluent.conf

<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<filter docker.**>
  @type parser
  format json
  key_name log
  reserve_data true
</filter>

<match **>
  @type elasticsearch
  host elasticsearch
  port 9200
  logstash_format true
  include_tag_key true
  tag_key @log_name
  flush_interval 1s
</match>

配置 Filebeat

创建 filebeat 目录并在该目录中创建 filebeat.yml 配置文件。

vim /path/to/filebeat/filebeat.yml

filebeat.inputs:
- type: container
  paths:
    - /var/lib/docker/containers/*/*.log
  processors:
    - add_docker_metadata: ~

output.elasticsearch:
  hosts: ["http://elasticsearch:9200"]
  username: "elastic"
  password: "changeme"

启动服务并访问 Kibana

在包含 docker-compose.yml 文件的目录中运行以下命令启动所有服务
docker-compose up -d

访问 http://<your-docker-host>:5601 进入 Kibana

日志监控-Graylog

编写docker compose文件

编写docker compose文件,配置mongo、es、graylog

version: '3'
services:
# MongoDB 作为 Graylog 的存储后端
  mongo:
    image: mongo:4.2
    container_name: mongo
    networks:
      - graylog

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
    container_name: elasticsearch
    environment:
      - http.host=0.0.0.0
      - transport.host=127.0.0.1
      - network.host=0.0.0.0
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.type=single-node   # 单节点部署
    ulimits:
      memlock:
        soft: -1
        hard: -1
    mem_limit: 1g
    networks:
      - graylog

  graylog:
    image: graylog/graylog:4.0
    container_name: graylog
    environment:
      - GRAYLOG_PASSWORD_SECRET=cocDW72...UeL7wj
      - GRAYLOG_ROOT_PASSWORD_SHA2=87de99fk...h68s2dc
      - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/
      - GRAYLOG_TIMEZONE=Asia/Shanghai
      - GRAYLOG_ROOT_TIMEZONE=Asia/Shanghai
#    entrypoint: /usr/bin/tini -- wait-for-it elasticsearch:9200 -- /docker-entrypoint.sh # 容器启动命令
    networks:
      - graylog
    depends_on:
      - mongo
      - elasticsearch
    ports:
      - "9000:9000"        # Graylog的Web界面端口
      - 5044:5044          # Filebeat工具提供端口
      - 12201:12201        # Graylog接收GELF消息的TCP端口
      - 12201:12201/udp    # Graylog接收GELF消息的UDP端口
      - 1514:1514          # Graylog接收Syslog消息的TCP端口
      - 1514:1514/udp      # Graylog接收Syslog消息的UDP端口
    volumes:
      - graylog_data:/usr/share/graylog/data

  filebeat:
    image: docker.elastic.co/beats/filebeat:7.15.0
    user: root
    container_name: filebeat
      # filebeat的配置文件
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml
      # 这个挂载用于让 Filebeat 可以监视 Docker 容器日志
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      # 允许与Docker引擎通信。将套接字挂载到容器中,Filebeat可以获取有关 Docker 容器的信息。
      - /var/run/docker.sock:/var/run/docker.sock
    command: ["-e", "-strict.perms=false", "-E", "output.elasticsearch.hosts=['elasticsearch:9200']"]
    networks:
      - graylog
    depends_on:
      - elasticsearch

networks:
  graylog:
    driver: bridge

# 定义数据卷,这里会使用Docker的默认数据存储目录
volumes:
  graylog_data:
    driver: local

生成随机密码

# 生成password_secret密码
apt install -y pwgen
pwgen -N 1 -s 16

-N   获取1个密码,默认是20*8组成的阵列
-s   指定密码长度,不指定默认8位

# 生成GRAYLOG_ROOT_PASSWORD_SHA2的密码,从标准输入读取原数据进行sha256sum处理
echo -n "Enter Password: " && head -1 </dev/stdin | tr -d '\n' | sha256sum | cut -d" " -f1

tr -d '\n'    删除标准输入中的回车
sha256sum     不指定文件,默认从标准输入读取
cut -d" "     以空格作为sha256sum输出的分割符号
-f1           获取第一段分割

启动 Graylog、Elasticsearch 和 MongoDB

在包含 docker-compose.yml 文件的目录中运行以下命令启动所有服务:
docker-compose up -d

访问 Graylog

浏览器访问 http://127.0.0.1:9000 进入 Graylog 
用户名: admin
密码: 使用 GRAYLOG_ROOT_PASSWORD_SHA2 环境变量中指定的密码哈希

登录到 Graylog 后,配置输入以接收来自容器的日志。
进入 “System” > “Inputs”。
选择 GELF UDP 作为输入类型。
配置输入,选择启动输入,绑定到 0.0.0.0,并使用默认端口 12201。

配置容器日志驱动

指定应用容器配置日志驱动,将日志发送到 Graylog。

docker run -d --name my_nginx \
  --log-driver=gelf \
  --log-opt gelf-address=udp://127.0.0.1:12201 \
  --log-opt tag="nginx" \
  nginx

Docker管理工具

portainer单机版

docker run -d -p 9000:9000 \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
--name prtainer-test \
docker.io/portainer/portainer

访问方式:http://IP:9000

portainer 远程管理
远程管理使用2375端口,需要开启端口
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  # 原配置文件

修改后,选择其中一种
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H 0.0.0.0:2375
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock

docker-machine

docker-machine
base=https://github.com/docker/machine/releases/download/v0.16.0 &&  
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&  
sudo mv /tmp/docker-machine /usr/local/bin/docker-machine &&
chmod +x /usr/local/bin/docker-machine

docker-compose

docker-compose
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

配置Docker

修改docker默认的存储位置

docker info | grep 'Docker Root Dir'    # 查看现在的存储位置
docker stop $(docker ps -q)             # 停止所有容器
systemctl stop docker                   # 停止docker服务
mv /var/lib/docker /path/to/newdir      # 移动原数据到新路径
vim /etc/docker/daemon.json
{
  "data-root": "/path/to/newdir"
}
systemctl restart docker                # 重启docker
posted @   立勋  阅读(34)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示