• 正文
  • 相关推荐
申请入驻 产业图谱

七个会拖垮树莓派的 Docker 使用误区!

20小时前
208
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

我平时经常在树莓派上使用 Docker,用来搭建官方软件仓库里没有的各类服务。容器方便快速测试,但使用久了难免出现各种故障。下面分享实用方法,让容器能够稳定长期运行。

配置得当的 Docker 容器可以持续稳定运行。想要保证稳定性,就要将容器互相隔离,各自使用独立的配置文件、文件夹和端口;日常维护中,建议开启自动重启、更新与备份功能。

这些运维理念大家都有所了解,但在 Docker 环境里具体该如何实现,很多人并不清楚。下面我会逐一讲解细节,保障服务器井然有序地运转。

 

放任容器异常关停

始终设置重启策略,让容器自动恢复运行。

先从常见问题说起。一次我准备在智能电视上观看电影《功之怒》,却发现无法访问 Plex 影音服务器里的影片。检查后发现,对应的 Docker 容器已经停止运行。

默认设置下,容器程序报错崩溃,或是重启树莓派后,Docker 都不会自动重启容器。需要全天候运行的服务,必须手动设置重启规则。

想要开机自动启动、故障后自动重启,在配置中添加代码:

restart: always

调试阶段不想强制重启,可以改用这条规则。除手动关停外,其余情况都会自动重启容器:

restart: unless-stopped

这套设置基本可以保障 Plex 服务稳定运行。如果是核心业务服务,还可以配置异常提醒,服务下线时及时收到通知。

 

将所有服务写入同一个配置文件

每个容器一个服务,每个服务一个compose文件。

Docker Compose 采用文本配置,简单直观,如今已是主流使用方式。我刚上手时,误以为把所有容器整合在一个文件里更好管理,事实证明这个想法并不正确。

集中式配置反而会增加维护难度:

无法单独对某个容器进行版本更新

配置参数容易混淆,引发端口、存储卷冲突

单个容器配置出错,会导致全部服务启动失败

分开管理才是最优方案,每项服务单独创建配置文件。

我日常会为每个容器新建专属文件夹,Immich 相册、qbittorrent 下载工具都分开存放,每个文件夹只保留自身服务的 compose.yaml 配置。

注意: 有时候将多个服务合并到一个Docker文件中是有道理的。例如,当容器需要共享卷或共享虚拟网络以实现特定目标时。

 

囤积容器垃圾

定期清理未使用的容器、镜像和卷。

Docker 没有可视化的资源管理界面,老旧镜像、停用容器和缓存碎片很容易不断累积。

要更好地了解情况,运行这个命令:

docker system df

或者获取更详细的信息:

docker system df -v

例如,你可能有以下残留物:

没有被任何东西引用的旧镜像。

不再使用的已停止容器。

旧设置留下的非活跃虚拟网络。

被遗弃的卷。

构建缓存残留。

容器垃圾会导致树莓派变慢,因为它必须扫描所有这些东西。

如果它不能给你带来快乐,就丢掉它。当我完成测试并达到想要保留的稳定设置后,我会用这个命令清理:

docker system prune

有更细粒度的清理命令,但我觉得上面的语法容易记住,日常使用完全够用。

https://docs.docker.com/engine/manage-resources/pruning/

 

允许容器独占资源

始终为树莓派上运行的容器定义资源限制(CPU、RAM)。

多数容器运行时资源占用合理,不会超额消耗硬件资源。但像 PostgreSQL 这类数据库程序,常会大量占用树莓派 5 的处理器与内存。

无限制运行的容器会拖累整机性能,部署服务越多,故障概率越高。严重时系统会弹出内存不足提示,随意终止进程释放空间,造成运行紊乱。

提前划定资源使用上限,约束高负载容器。用例子更容易解释,这里是一个配置,相关部分(6-14行):

services:  stress-test:    image: jfleach/docker-arm-stress-ng:latest    privileged: true        cpus: 0.5    mem_limit: 512m    memswap_limit: 512m        logging:      driver: "local"      options:        max-size: 50m        max-file: 3        command: >      --cpu 4      --vm 2      --vm-bytes 800m      --vm-populate      --timeout 60s      --verbose

从这个命令可以看出,我已经成功限制了这个容器的资源使用:

docker stats

让我们来看看这些限制的作用:

处理器 – cpus: 0.5 表示容器最多允许使用0.5个CPU核心。

内存 – mem_limit: 512m, memswap_limit: 512m 表示容器最多可以使用512MB RAM。在树莓派上要正确生效,这两行都是必需的。

日志 – 可以用来限制日志占用的磁盘空间。

driver: local – 指定使用系统的日志轮转功能。

max-size: 50m – 表示主日志文件最多占用50MB磁盘空间。

max-file: 3 – 在删除旧文件之前轮转3个日志文件。

可根据自身需求调整参数。不必给所有容器统一加限制,避免产生性能瓶颈,仅针对高占用程序单独约束即可。

提示:Docker在树莓派上开箱即用时不会准确报告内存使用情况。如果你需要这个功能,打开 /boot/firmware/cmdline.txt,在那行长命令的末尾添加这些参数:

cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

 

制造端口冲突

为每个容器映射唯一的主机端口,以避免冲突。

配置Docker容器时,通常会定义一个网络端口来连接服务。许多服务会创建一个Web面板,默认为端口80。如果你有三个不同的服务都设置为使用端口80,你的树莓派怎么知道该提供哪一个?

为了防止冲突,为每个容器映射不同的端口,使它们不会重叠。例如,下面是Pi-Hole广告拦截器Docker配置的相关部分:

pihole:    container_name: pihole    image: pihole/pihole:latest    ports:      - "53:53/tcp"      - "53:53/udp"      - "80:80/tcp"      - "443:443/tcp"

当我看到 80:80 和 443:443 时,我的第一反应就是修改它们。这些是常用端口,可能会与其他容器冲突,比如我的Caddy网页服务器。要重新映射端口,你只需要修改冒号(:)左边的数字,像这样:

6060:80/tcp6443:443/tcp

现在,我的Pi-Hole网页面板可以通过端口6060访问。确实不太好记,但初始设置后我很少去那里,一个书签就轻松解决了。

 

使用过时的镜像

定期更新你的容器镜像,保持安全和最新。

容器与系统相互隔离,常规系统更新无法同步升级容器内部程序。长时间不更新,Home Assistant 这类服务会存在安全漏洞,容易遭到网络攻击

让我们讨论几种让容器更新更可持续的方法。

如何更新Docker容器?

导航到你存储Docker compose.yaml文件的文件夹。然后,运行以下命令来更新容器:

docker compose pulldocker compose up

第一个命令下载最新镜像,第二个命令使用更新后的镜像重启容器。如果你更喜欢定期更新所有容器而不必手动一个个操作,你可以创建一个脚本,每月自动运行一次这些命令。

或者,你也可以从Portainer操作(Portainer是一个图形化容器管理器,本身也可以作为容器运行)。进入服务的"容器详情"页面,点击"重建"按钮来更新容器。

何时使用"latest"标签?

我经常使用"latest"标签(例如 image: wg-easy:latest),这样更新容器时总是拉取最新版本。但有些情况下,我运行的是关键任务服务,比如生产服务器上的,我需要更稳定的版本。

当需要稳定性时,将Docker配置固定到特定的镜像版本。例如,我的WireGuard VPN服务器的容器配置使用了这个镜像标签:

image: ghcr.io/wg-easy/wg-easy:14

":14"标签告诉Docker获取最后一个v14版本,我知道它已经成熟,只接收安全更新。如果我用了"latest"标签,它会获取最新的v15版本,该版本仍在进行重大更新,可能会破坏我的设置。

 

忘记保存用户数据

配置卷,让你的数据保存在容器之外。

许多容器需要存储数据,比如设置或用户文件,就像任何其他程序一样。但如果你不告诉它怎么做,你的东西最终会消失。在Docker配置中,"volumes"部分告诉容器把文件保存在哪里。

推荐这套稳妥的存储方案:

每个容器存储在自己独立的项目文件夹中。

用户文件的卷相对于项目文件夹进行映射。

例如,我有一个 ~/containers 文件夹来存放所有Docker相关内容。里面有一个子文件夹给我的项目 paperless-ngx,一开始只包含它的Docker配置。

下面是compose.yaml中的相关部分:

paperless-ngx:    image: ghcr.io/paperless-ngx/paperless-ngx:latest    volumes:      - data:/usr/src/paperless/data      - media:/usr/src/paperless/media      - ./export:/usr/src/paperless/export      - ./consume:/usr/src/paperless/consume

文档说明上面两个卷('data'和'media')是应用默认值,用于基本功能,所以为了教学目的我们忽略它们。然而,下面两个卷('export'和'consume')指的是用户文件,比如我的扫描文档,以及它们应该保存在哪里。没有这几行,当容器宕机时,文件就会烟消云散!

顺便说一下,通过在前面加上"./",我是在告诉Docker把这些卷映射到当前文件夹——而不是Linux文件系统中其他随机位置,比如 /etc 或 /usr。这意味着我的paperless-ngx所有用户文件都会保存在与其Docker配置相同的地方。

为什么这样更简单?因为当我需要备份所有容器时,我只需压缩 ~/containers 文件夹,就完成了。

如果我需要从备份恢复,我启动容器,它已经在一个文件夹里拥有了重新工作所需的一切。这也是我喜欢使用Docker的另一个原因:我所有的工作都是可复现的,所以我不需要完美的记忆力就能把东西恢复到以前的样子。

掌握正确的使用方式,就能搭建稳固可靠的容器服务,即便无人值守也可以持续平稳运行。

Tip:对于刚接触树莓派的新手来说,面对英文文档、零散教程和复杂配置,很容易无从下手。pidoc.cn就是为解决这些痛点而生的树莓派中文一站式学习平台,界面清晰、内容系统、更新及时,堪称新手入门的“保姆级” 网站,让零基础用户也能轻松上手树莓派。

 

官方网站:https://edatec.cn/zh/cm0

淘宝店铺:https://edatec.taobao.com/

相关推荐