6271 字
31 分钟
Docker 日志管理:轮转、限制与集中查看
2026-11-15

容器跑起来之后,日志就是你的眼睛:服务为什么挂了、请求为什么报错、程序到底有没有按预期在跑,全靠日志说话。但日志也是个双刃剑——不管它,它能悄悄把磁盘写满,让整台机器的服务一起陪葬;管得太死,真出事的时候又发现什么都没留下。这篇把 Docker 日志从「怎么看」到「怎么管」一次讲透:先讲 docker logs 的全参数用法,再讲日志到底存在哪、json-file 驱动是怎么回事,然后是轮转配置的两种写法(全局 daemon.json 和单容器 compose),最后是磁盘写满的应急处理和用 Dozzle 在网页上集中看日志的部署与安全加固。

如果你还没装好 Docker,先看 《如何在Linux部署Docker&Compose》;容器已经在自动更新的,也可以配合 《如何在Linux自动更新Docker容器》 一起看——更新后容器起不来时,第一件事就是查日志。

docker logs 全参数用法#

docker logs 是最常用的查日志命令,但很多人只会最基础的 docker logs 容器名,把全部历史日志一股脑刷屏。其实它有一整套参数,组合好了定位问题非常快。

基础与实时跟踪:-f#

Terminal window
# 查看容器全部日志(标准输出 + 标准错误)
docker logs nginx
# 实时跟踪新日志,类似 tail -f,Ctrl+C 退出(不会停掉容器)
docker logs -f nginx

-f(--follow)是最常用的参数:先把已有日志打出来,然后挂着等新日志。调试「请求进来之后发生了什么」时,先开一个终端 docker logs -f 挂着,再去发请求,日志实时滚动,问题一目了然。

只看最后 N 行:—tail#

Terminal window
# 只看最后 100 行
docker logs --tail 100 nginx
# 和 -f 组合:先显示最后 50 行,再实时跟踪
docker logs -f --tail 50 nginx

容器跑了几个月,日志可能有几十万行,直接 docker logs 会刷屏半天。养成习惯:先 --tail 看尾巴,确认大概是什么问题,再决定要不要翻历史。

按时间范围查:—since / —until#

Terminal window
# 看最近 10 分钟的日志
docker logs --since 10m nginx
# 看最近 1 小时的日志
docker logs --since 1h nginx
# 看某个时间点之后的日志(RFC3339 格式)
docker logs --since 2026-11-15T08:00:00 nginx
# 两个组合:看 08:00 到 09:00 这一小时的日志
docker logs --since 2026-11-15T08:00:00 --until 2026-11-15T09:00:00 nginx
# 看某个时间点之前的日志
docker logs --until 30m nginx

--since / --until 接受两种格式:相对时长(10m、1h、24h)和绝对时间戳(RFC3339,如 2026-11-15T08:00:00)。「用户说昨晚 9 点左右网站打不开」这种场景,--since + --until 把时间窗一卡,日志量立刻从几十万行缩到几百行。

显示时间戳:-t#

Terminal window
docker logs -t --tail 20 nginx

输出会变成这样,每行前面多出日志产生的时间:

2026-11-15T00:12:31.123456789Z 192.168.1.10 - - "GET / HTTP/1.1" 200 612

-t(--timestamps)显示的是日志条目的时间戳(UTC 时间,注意换算时区)。应用本身日志不带时间、或者想和别的系统日志对时间线时,这个参数非常有用。

显示驱动附加信息:—details#

Terminal window
docker logs --details nginx

--details 会把日志驱动附加的额外信息(attributes)一并显示出来,比如通过 docker run --log-opt labels=xxx 打上的标签信息。日常用得不多,排查「这条日志到底从哪个环境来的」时能派上用场。

组合场景速查#

场景命令
刚部署完,实时盯启动过程docker logs -f --tail 50 容器名
服务突然挂了,看死前发生了什么docker logs --tail 200 容器名
用户报某个时间段出问题docker logs --since 时间 --until 时间 容器名
日志太多,先粗筛关键词docker logs --since 1h 容器名 2>&1 | grep -i error
把日志存下来慢慢看docker logs --since 24h 容器名 > app.log 2>&1
WARNING

docker logs 看到的是容器的标准输出(stdout)和标准错误(stderr)。如果应用把日志写进了容器内部的文件(比如 /var/log/app.log),docker logs 是看不到的——这也是后面排障小节里最常见的「没输出」原因。

进阶技巧:过滤、统计与导出#

参数之外,再配合 shell 的文本工具,docker logs 还能玩出不少花样:

Terminal window
# 只看标准错误(1 是 stdout,2 是 stderr;docker logs 默认两者都输出)
docker logs 容器名 2>/dev/null # 只要标准输出
docker logs 容器名 1>/dev/null # 只要标准错误
# 统计最近一小时 ERROR 出现了多少次
docker logs --since 1h 容器名 2>&1 | grep -c "ERROR"
# 按状态码粗筛访问日志(以 Nginx 为例,看所有 5xx)
docker logs --since 24h nginx 2>&1 | grep '" 5'
# 导出某天的完整日志留档
docker logs --since 2026-11-14T00:00:00 --until 2026-11-14T23:59:59 容器名 > nginx-1114.log 2>&1

这里有个容易踩的小坑:docker logs 输出时,容器写到 stderr 的内容在终端里也是走 stderr 通道的,所以管道给 grep 之前记得加 2>&1,否则错误日志会漏掉一大半。很多应用恰恰是把正常日志写 stdout、把错误日志写 stderr,只过滤一半等于白查。

容器日志到底存在哪#

理解日志的存放位置,才能理解轮转和磁盘占用的问题出在哪。

在默认的 json-file 日志驱动下,每个容器的日志都存在宿主机上一个固定的文件里:

/var/lib/docker/containers/<容器ID>/<容器ID>-json.log

查看某个容器日志文件的实际大小:

Terminal window
# 先拿到容器完整 ID
docker inspect -f '{{.Id}}' nginx
# 再看对应日志文件
ls -lh /var/lib/docker/containers/<容器ID>/<容器ID>-json.log

也可以一条命令直接定位:

Terminal window
docker inspect -f '{{.LogPath}}' nginx

json-file 驱动的工作原理很朴素:Docker 守护进程把容器的 stdout/stderr 一行一行包装成 JSON(每行包含日志内容、来源是 stdout 还是 stderr、时间戳),追加写进这个文件。docker logs 本质上就是把这个文件读出来、拆掉 JSON 包装再打印。

朴素的代价是:默认不做任何轮转。只要容器还在输出,这个文件就只会变大,永远不会自己变小。一个话痨容器(比如开了 debug 级别日志的服务)几天写出几十 GB 日志,是非常真实的事故——这正是下一节要解决的问题。

日志轮转:全局配置 daemon.json#

给所有容器统一设置日志上限,改的是 Docker 守护进程的配置文件 /etc/docker/daemon.json:

{
"log-driver": "json-file",
"log-opts": {
"max-size": "20m",
"max-file": "3"
}
}

两个参数的含义:

  • max-size: 20m:单个日志文件最大 20MB,写满了就滚动到下一个文件;
  • max-file: 3:最多保留 3 个文件(当前文件 + 2 个历史文件)。

也就是说每个容器最多占用约 60MB 磁盘,写得再多也封顶,老日志自动丢弃。

改完之后要重启 Docker 守护进程才生效:

Terminal window
systemctl restart docker

验证配置是否被守护进程接受(改错 JSON 语法会导致 Docker 起不来,重启后先确认服务状态):

Terminal window
systemctl status docker
docker info | grep -A2 "Logging Driver"
WARNING

最关键的坑:daemon.json 的日志配置只对「新建的容器」生效。 已经在跑的老容器,创建时用的是旧配置,重启 Docker、甚至重启容器本身都不会改变它的日志设置——必须把容器删除重建(docker compose up -d --force-recreate 或先 docker rm 再重新创建),新配置才套得上。所以改完 daemon.json 别急着以为万事大吉,逐个确认重要容器的实际配置:

Terminal window
docker inspect -f '{{.HostConfig.LogConfig}}' 容器名

输出里能看到该容器实际生效的 max-size 和 max-file,没有就说明它还是无限制状态。另外提醒一句:systemctl restart docker 会影响所有容器,没有配 live-restore 的话容器会被全部重启,请挑低峰期操作。

日志轮转:单容器配置(Compose)#

全局配置管所有容器,但有些容器你想区别对待:核心服务想多留点日志(max-file 给大些),一次性的小工具干脆少留。这时在 docker-compose.yml 里给单个服务写 logging 段,它会覆盖全局 daemon.json 的设置:

services:
app:
image: myapp:latest
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"

这个服务就会按单文件 50MB、保留 5 个来轮转,总上限约 250MB,不受全局 20m×3 的影响。

用 docker run 时对应的是 --log-opt 参数,效果一样:

Terminal window
docker run -d \
--log-driver json-file \
--log-opt max-size=20m \
--log-opt max-file=3 \
nginx

两种写法的分工很简单:daemon.json 定基线,保证任何容器都不会写爆磁盘;compose 的 logging 段做个别调整,给需要特殊对待的服务开小灶。

轮转参数的几个细节#

  • 单位:max-size 支持 k(KB)、m(MB)、g(GB),比如 500k、20m、1g 都合法,不带单位默认是字节,千万别手滑写成纯数字。
  • 到底占多少:一个容器的日志上限约等于 max-size × max-file。20m × 3 = 60MB,单机跑二三十个容器,最坏情况也就 2GB 以内,心里要有这本账;如果某个服务日志量特别大又想多留历史,把它单独调大,而不是把全局基线放宽。
  • 轮转不是删除:写满一个文件后,旧文件会被改名留作历史(如 -json.log.1、-json.log.2),docker logs 读取时会自动把这几个文件拼起来看,所以轮转不会让近期日志「断片」,只是更早的会被挤掉。
  • 正在写的容器能改吗:不能热改。容器的日志配置在创建那一刻就定死了,任何修改——不管是改 daemon.json 还是改 compose 文件——都必须重建容器才生效,这一点前面已经强调过,这里再重复一遍,因为它是本篇最容易翻车的地方。

其他日志驱动对比#

json-file 不是唯一选择。Docker 还内置了几种日志驱动,适用场景各不相同:

驱动日志去向docker logs 能看吗适用场景
json-file宿主机本地 JSON 文件✅ 能默认驱动,单机小规模部署,配好轮转就够用
local宿主机本地文件(Docker 优化格式)✅ 能json-file 的改良版:自带轮转和压缩,磁盘占用更小,官方推荐的新选择
journald宿主机的 systemd journal✅ 能(经 journal 读取)宿主机用 systemd 且已有 journal 收集习惯,想和系统日志统一管理
syslog宿主机的 syslog 服务❌ 不能已有 syslog/远程日志服务器的老牌环境
none直接丢弃❌ 不能输出量巨大且完全不需要日志的容器,或日志已由应用自己处理

几点说明:

  • local 驱动值得多看一眼:它就是为解决 json-file 的毛病设计的,默认就带轮转(max-size 默认 20m、max-file 默认 5),还做了压缩和更高效的读写。新部署的机器可以直接把 daemon.json 的 log-driver 换成 local,省去手动配轮转。
  • journald 的好处是能按容器名过滤查看,坏处是日志和系统日志混在一起,且 journal 本身也有自己的轮转策略要管。用了 journald 之后,除了 docker logs,还可以直接在宿主机上按容器名查:
Terminal window
journalctl CONTAINER_NAME=nginx -f
  • local 驱动多提一句:它的日志文件不在前面说的 -json.log 路径下,格式也是二进制优化过的,不能直接用文本工具去翻文件,老老实实用 docker logs 看就行。它省下的主要是磁盘 I/O 和空间,对日志量大的机器收益明显。
  • syslog 驱动下 docker logs 完全失效,日志只在 syslog 里,换机器排障时容易两眼一抹黑。
WARNING

none 驱动是个大坑预警:设成 none 后容器日志被直接丢弃,docker logs 执行不报错、但什么都输出不了。哪天你发现某个容器「日志功能坏了」,先用 docker inspect -f '{{.HostConfig.LogConfig.Type}}' 容器名 查一下它到底用的什么驱动——十有八九是创建时被设成了 none,或者是从别人那抄的 compose 文件里带着这个设置。

磁盘被日志写满:排障全流程#

这是 Docker 新手最容易吃的一次亏:服务器突然各种服务报错、数据库连不上、SSH 登录都变慢,最后发现是根分区 100% 满了,而凶手往往就是某个容器的日志。按这个流程走,十分钟能定位并止血。

第一步:确认磁盘真的满了,满在哪#

Terminal window
# 看分区使用率,确认哪个分区满了(一般是 / 或 /var)
df -h
# 看 /var/lib/docker 占了多少
du -sh /var/lib/docker

第二步:定位大文件#

Terminal window
# 按容器列出占用,排序找最大的
du -sh /var/lib/docker/containers/* | sort -rh | head -20
# 或者直接找所有超过 100MB 的日志文件
find /var/lib/docker -name "*-json.log" -size +100M -exec ls -lh {} \;

一般到这一步凶手就现形了:某个 -json.log 文件几个 GB 甚至几十 GB。

想知道它属于哪个容器,用文件路径里的容器 ID 反查:

Terminal window
docker ps -a --no-trunc | grep <容器ID前几位>

第三步:应急清空日志(truncate,不能 rm)#

确认这个日志不需要保留后(或者先 tail 拷一份样本出来),用 truncate 把文件清零:

Terminal window
truncate -s 0 /var/lib/docker/containers/<容器ID>/<容器ID>-json.log

或者等价写法:

Terminal window
cat /dev/null > /var/lib/docker/containers/<容器ID>/<容器ID>-json.log
WARNING

千万不要直接 rm 删这个日志文件! 容器进程和 Docker 守护进程还握着这个文件的句柄,rm 只是删掉了目录项,进程会继续往那个「已经不存在」的文件里写,磁盘空间一点都不会释放(用 lsof | grep deleted 能看到它还占着),直到容器重启句柄才释放。更糟的是,新日志从此写进黑洞,docker logs 也再看不到新内容。truncate -s 0 是把同一个文件清零,句柄不变,空间立刻释放,容器继续正常写日志——这才是正确姿势。

多说一句怎么判断「凶手是不是日志」:磁盘写满时报错往往很迷惑——数据库可能报连接失败或只读错误,Web 服务返回 502,甚至 Docker 本身拉镜像、建容器都会失败,因为这些操作全都要往磁盘写东西。如果一台机器突然「所有服务一起出问题」,第一反应就应该是去看 df -h,而不是逐个服务去猜。反过来,单个服务出问题、磁盘还很空,那就老老实实查应用本身,别在磁盘上浪费时间。

清完后再 df -h 确认空间回来,服务一般会自己恢复;个别已经崩掉的容器手动重启一下:

Terminal window
docker restart 容器名

第四步:事后补上轮转配置#

止血只是第一步,不补配置,过几天同样的事情还会再发生一遍:

  1. 按前文给 daemon.json 加上 log-opts(max-size 20m、max-file 3);
  2. 重启 Docker 让配置生效;
  3. 把出事的那个容器删除重建(记住:只对新建容器生效),确认新容器的 LogConfig 里已经带上轮转参数;
  4. 顺手检查其他老容器,逐个重建或者在 compose 里补 logging 段。

加一道保险:定期巡检大日志#

轮转配置难免有漏网之鱼(比如别人部署的容器、临时测试起的容器),可以再加一个简单的巡检脚本,定期扫一遍超大日志文件,提前发现苗头:

#!/bin/bash
# /opt/scripts/check-docker-logs.sh:找出超过 500MB 的容器日志并记录
find /var/lib/docker/containers -name "*-json.log" -size +500M \
-exec ls -lh {} \; >> /var/log/docker-logs-check.log 2>&1

挂到 crontab 每周跑一次,或者配合你已有的监控,在文件出现时就告警:

0 9 * * 1 /opt/scripts/check-docker-logs.sh

思路和自动更新一样:重复性的检查交给定时任务,人才有精力处理真正需要判断的问题。等哪天巡检日志里真出现了一行记录,说明又有容器在偷偷攒日志,按前面的流程处理即可。

Dozzle:网页端集中看日志#

容器一多,SSH 上去一个个 docker logs 就很折腾了。Dozzle 是一个轻量的日志查看 Web 界面:实时流式显示所有容器的日志、支持搜索过滤、多容器一键切换,镜像本身只有十几 MB,是个人服务器上最顺手的日志工具。

Compose 部署#

services:
dozzle:
image: amir20/dozzle:latest
container_name: dozzle
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "127.0.0.1:8080:8080"
Terminal window
docker compose up -d

注意端口写法是 127.0.0.1:8080:8080——只绑定本机回环地址,外网直接访问不到,原因在下一节细说。

界面能干什么#

  • 实时日志流:打开就是所有容器的列表,点进任意容器,日志像 docker logs -f 一样实时滚动,不用手动刷新;
  • 多容器切换:左侧列表一键切换,还能同屏对比看几个容器的日志,排查「A 服务调 B 服务失败」这类跨容器问题特别方便;
  • 搜索与过滤:在日志流里直接关键词搜索、高亮命中行,比在终端里翻 grep 直观得多;
  • 历史回看:往上滚动就能加载更早的日志,带时间戳显示;
  • 几乎零配置:它直接读 Docker 的日志,你现有的容器什么都不用改,装上就能看。

Dozzle 只是「看」日志的工具,它不存储、不转储日志——容器删了,日志在 Dozzle 里也就没了,这一点和 docker logs 的行为一致。

再介绍两个实用的可选项。第一,只展示部分容器:机器上容器多了,列表会很长,可以用过滤参数只盯你关心的那些,过滤语法和 docker ps --filter 一致:

command: --filter label=com.centurylinklabs.watchtower.enable=true

或者按名字过滤:

command: --filter name=nginx --filter name=app

第二,挂在反向代理的子路径下:如果想把 Dozzle 放在 https://你的域名/logs/ 这种子路径而不是独立端口/子域名,给它设置基础路径:

environment:
- DOZZLE_BASE=/logs

反向代理把 /logs/ 转发到 Dozzle 的 8080 端口即可,页面里的静态资源路径会自动带上这个前缀,不会出现页面打开了但样式和脚本 404 的问题。

安全加固(重中之重)#

Dozzle 好用,但它的能力来源是那块 /var/run/docker.sock,这也是它最大的风险点,必须认真对待。

先说清楚 docker.sock 是什么:它是 Docker 守护进程的控制接口,谁能访问它,谁就能创建任意容器、挂载宿主机任意目录、以 root 权限在宿主机上执行命令——等于宿主机的 root 权限。Dozzle 挂的是只读(:ro),这能防止通过 Dozzle 本身修改容器状态,是必须保留的设置;但即便如此,能看所有容器的全部日志本身就很敏感:日志里经常混着数据库密码、API Token、用户隐私数据。

所以部署时请务必做到这三点:

  1. 不要直接暴露公网。 端口只绑 127.0.0.1(像上面 compose 里那样),然后通过反向代理(Nginx/Caddy)加 HTTPS 访问,或者干脆只在内网/通过 SSH 隧道访问:
Terminal window
# 在自己电脑上开隧道,然后浏览器访问 http://localhost:8080
ssh -L 8080:127.0.0.1:8080 root@你的服务器
  1. 开启 Dozzle 自带的登录认证。 给容器加两个环境变量即可启用用户名密码登录:
environment:
- TZ=Asia/Shanghai
- DOZZLE_USERNAME=admin
- DOZZLE_PASSWORD=换成你的强密码
  1. 反向代理再加一层。 如果确实需要从公网访问,在 Nginx 层再加 Basic Auth 或 IP 白名单,和 Dozzle 自带认证叠加,双保险。
WARNING

把 Dozzle 裸奔在公网上(8080:8080 不绑回环、不设密码)是真实世界里被入侵的常见入口之一:扫描器全天候在扫这个端口,一旦被人打开,你所有容器的日志——包括里面可能出现的密钥和隐私——都一览无余,对方还能从日志里摸清你的全部服务结构。花在加固上的这三分钟,绝对不能省。

排障:docker logs 没输出怎么办#

docker logs 执行成功、退出码正常,但就是一片空白。按可能性从高到低排查:

1. 应用把日志写进了文件,没走 stdout/stderr。 这是最常见的原因。docker logs 只能拿到容器主进程的标准输出和标准错误;很多传统应用默认把日志写到 /var/log/xxx.log 这类文件里,自然看不到。验证方法:进容器里看看有没有日志文件在长大:

Terminal window
docker exec -it 容器名 sh -c 'ls -lt /var/log/ | head'

解决办法是改应用的日志配置让它输出到 stdout;实在改不了,可以在启动命令里把日志文件软链到标准输出,这也是很多官方镜像的做法:

RUN ln -sf /dev/stdout /var/log/app.log \
&& ln -sf /dev/stderr /var/log/app-error.log

2. 日志驱动被设成了 none。 前面提过,none 驱动直接丢弃日志。检查并重建容器换回 json-file 或 local:

Terminal window
docker inspect -f '{{.HostConfig.LogConfig.Type}}' 容器名

3. 容器已经删除了。 日志文件是跟着容器走的,容器被 docker rm(或者被自动更新工具重建失败后清掉)之后,日志文件一并删除,事后无从查起。这也是为什么 《如何在Linux自动更新Docker容器》 里建议重要服务先开「只监控」观察期、更新前先看日志:真出了事,旧容器的日志还在才有据可查。需要长期留存的日志,应该让应用输出到挂载出来的数据卷文件里,或者接入集中日志系统,而不是只依赖 docker logs。

4. 用了 —since 却把时间算错了。 不加参数明明有日志,一加 --since 就空白,多半是时间对不上:docker logs 的绝对时间按 UTC 理解,而你脑子里想的是北京时间,差着 8 小时,窗口自然卡空了。不确定时先用相对时长(--since 30m)验证,或者用 date -u 看一眼服务器的 UTC 时间再换算。

5. 顺带一提:输出被缓冲了。 有些语言(典型如 Python)的 stdout 在非终端环境下是块缓冲,程序在跑、日志却攒着不吐出来,看起来像没输出,过一阵又突然刷出一大片。这不是 Docker 的问题:Python 加 -u 参数或环境变量 PYTHONUNBUFFERED=1 即可,其他语言同理查各自的无缓冲设置。

再往后:什么时候需要集中日志系统#

本篇讲的都是单机范围内的日志管理:一台机器、几十个容器,docker logs 加 Dozzle 完全够用。但如果你的情况变成下面这样,就该考虑把日志集中收集到专门的系统里了:

  • 机器变多:三五台服务器各跑各的容器,出一次问题要挨个 SSH 上去翻日志,效率太低;
  • 日志要长期留存:审计、复盘需要查几个月前的日志,而本机轮转早就把它们挤掉了;
  • 需要告警:想在日志出现特定错误(比如支付失败、异常堆栈)时第一时间收到通知,而不是等用户来报障。

常见的集中方案有 Loki + Promtail + Grafana(轻量,和监控面板能合一)、ELK(Elasticsearch + Logstash + Kibana,功能强但吃资源)等。它们的共同思路是:在每台机器上跑一个采集小组件,把容器日志实时转发到中心存储。个人规模建议从 Loki 起步,资源占用小、和 Docker 的配合也成熟。不过记住一句话:集中系统是锦上添花,单机的轮转配置永远是地基——采集组件挂掉的时候,本机日志如果没封顶,照样能把磁盘写满,地基的活儿一天都不能省。

小结#

  • docker logs 的日常组合是 -f 跟踪、--tail 限量、--since/--until 卡时间窗、-t 带时间戳,先缩小范围再细看;
  • 默认 json-file 驱动不轮转,这是磁盘写满事故的头号来源,必须配轮转:daemon.json 全局设 max-size: 20m + max-file: 3 定基线,compose 的 logging 段给个别容器开小灶;
  • 牢记 daemon.json 改完只对新建容器生效,老容器要重建,并用 docker inspect 逐个验证;
  • 磁盘真被写满时,流程是 df/du/find 定位 → truncate -s 0 清零止血(绝不能直接 rm)→ 补轮转配置防复发;
  • 容器多了用 Dozzle 在网页上集中看日志,但 docker.sock 事关宿主机 root 权限:只读挂载、端口绑 127.0.0.1、开登录认证,三件套缺一不可;
  • docker logs 没输出,先怀疑应用没往 stdout 写,其次查日志驱动是不是 none,最后确认容器是不是已经被删了。

日志管理的核心就一句话:平时给它封顶,出事时靠它查命。轮转配置花十分钟一次配好,往后每次排障都会感谢现在的自己。

Docker 日志管理:轮转、限制与集中查看
https://blog.anexns.com/posts/docker-logging/
作者
Anexns
发布于
2026-11-15
许可协议
CC BY-NC-SA 4.0