【树莓派】树莓派上Docker部署实战:从零到可视化运维

【树莓派】树莓派上Docker部署实战:从零到可视化运维 1. 为什么要在树莓派上玩Docker如果你和我一样是个喜欢折腾的开发者或者极客手头肯定有那么一两块树莓派。这小玩意儿性能越来越强从最初的玩具到现在已经能正经跑不少服务了。但每次想在上面部署个应用比如一个博客、一个智能家居中枢或者一个代码仓库最头疼的就是环境配置。不同的软件依赖不同的库、不同的版本搞不好就冲突把系统弄得一团糟重装系统是家常便饭。这时候Docker的价值就凸显出来了。你可以把它理解成一个超级轻量级的“软件集装箱”。每个集装箱容器里都打包好了一个应用运行所需的一切——代码、运行时环境、系统工具、系统库。你的树莓派系统宿主机只需要提供最基础的运行环境比如Linux内核然后就可以像搭积木一样把一个个集装箱跑起来。它们彼此隔离互不干扰一个容器崩了不会影响其他容器更不会搞坏你的树莓派系统。这对于资源有限的树莓派来说简直是管理神器。而今天我们要做的不仅仅是把Docker装上就完事。装Docker本身不难难的是后续的管理和运维。难道每次都要敲一堆命令行去查看容器状态、启停服务、查看日志吗对于习惯了图形界面的我们来说这太不友好了。所以这次实战的核心目标是打造一个“从零到可视化运维”的一站式环境。我们将通过一个叫Portainer的神器为你的树莓派Docker环境装上一个直观、强大的图形化管理面板。以后你只需要在浏览器里点一点就能完成绝大多数容器管理工作这才是真正的“优雅”和“便捷”。2. 实战第一步为树莓派安装Docker引擎好了废话不多说我们直接上手。首先确保你的树莓派已经刷好了最新的 Raspberry Pi OS以前叫 Raspbian并且通过sudo raspi-config命令扩展了文件系统连上了网络。接下来的操作我们都在终端命令行里完成。2.1 最省心的安装方法官方一键脚本对于新手或者想快速搞定不想折腾的朋友我首推这个方法。Docker官方提供了一个非常方便的安装脚本它能自动检测你的系统并安装合适的版本。你只需要打开终端输入下面这行命令然后回车泡杯茶等着就行curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh我解释一下这两行命令在干嘛。第一行是用curl工具从 Docker 官网下载那个安装脚本并保存到当前目录文件名叫get-docker.sh。第二行就是用sh命令来执行这个脚本sudo表示用管理员权限运行因为安装软件需要。这个脚本会帮你完成所有事情更新软件源、添加 Docker 的官方 GPG 密钥和软件仓库、最后安装 Docker 引擎也就是docker-ce社区版。整个过程是全自动的你只需要在提示输入密码的时候输入一下树莓派的密码。安装完成后脚本通常还会把当前用户加入到docker用户组这样你以后运行 Docker 命令就不需要每次都加sudo了。不过为了保险起见我们手动加一下sudo usermod -aG docker $USER执行完这行命令后非常重要的一步你需要注销当前用户并重新登录或者直接重启树莓派这个用户组的变更才会生效。不然你直接运行docker version可能会提示权限错误。现在验证一下安装是否成功docker version如果看到类似下面的输出有 Client客户端和 Server服务端的版本信息那就恭喜你Docker 引擎已经稳稳地跑在你的树莓派上了。Client: Docker Engine - Community Version: 24.0.7 API version: 1.43 ... Server: Docker Engine - Community Engine: Version: 24.0.7 ...2.2 手动安装更可控的进阶方式一键脚本虽好但有时候我们想更清楚每一步在做什么或者网络环境特殊脚本可能跑不通。这时候就可以选择手动安装步骤稍微多一点但每一步都很清晰。首先更新一下系统的软件包列表确保我们获取的是最新的信息sudo apt update sudo apt upgrade -y接着安装一些让apt能通过 HTTPS 使用软件仓库所必需的依赖包sudo apt install -y \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-release然后我们需要添加 Docker 的官方 GPG 密钥。这个密钥就像一把“安全锁”确保我们后续从 Docker 仓库下载的软件包是官方发布的没有被篡改。注意树莓派是 ARM 架构我们要用对应的命令curl -fsSL https://download.docker.com/linux/raspbian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg接下来告诉系统去哪里找 Docker 的软件包。我们需要设置稳定版stable的仓库。这里命令有点长我拆解一下我们用echo命令生成一个仓库地址的配置字符串然后通过管道|传给tee命令让它把这个配置写入到/etc/apt/sources.list.d/docker.list这个文件里。这个文件是专门用来放第三方软件仓库地址的。echo \ deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/raspbian \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null命令里的$(dpkg --print-architecture)会自动获取你系统的架构比如 armhf 或 arm64$(lsb_release -cs)会自动获取你系统的代号比如 bullseye。这样写比硬编码更通用。仓库添加好了再次更新软件包列表让系统知道新加了 Docker 这个“软件商店”sudo apt update最后安装 Docker 引擎社区版以及命令行工具sudo apt install -y docker-ce docker-ce-cli containerd.io安装完成后同样可以运行docker version来验证。为了让 Docker 服务在树莓派启动时就自动运行我们还需要启用它sudo systemctl enable docker sudo systemctl start docker这样无论是用脚本还是手动Docker 都已经准备就绪。我个人实测下来在树莓派 4B 上整个安装过程大概也就几分钟非常快。3. 关键优化为Docker配置国内镜像加速Docker 安装好了但如果你直接去拉取下载镜像比如docker pull nginx可能会发现速度慢如蜗牛甚至直接超时失败。这是因为 Docker 默认的镜像仓库Docker Hub服务器在国外。对于国内用户这是一个必须解决的痛点。解决办法就是配置国内的镜像加速器。国内很多云服务商都提供了免费的 Docker 镜像加速服务比如阿里云、腾讯云、网易云等。这里我以阿里云为例因为它的加速器配置起来非常方便而且速度很稳定。首先你需要有一个阿里云账号没有的话免费注册一个。登录后进入“容器镜像服务”控制台可以在产品列表里搜。在左侧菜单找到“镜像工具” - “镜像加速器”。你会看到一个专属的加速器地址格式类似https://xxxx.mirror.aliyuncs.com这个地址每个人都不一样。拿到地址后回到树莓派的终端。我们需要创建一个 Docker 的守护进程配置文件sudo nano /etc/docker/daemon.json如果这个文件不存在nano编辑器会新建一个。将下面的内容粘贴进去注意把https://xxxx.mirror.aliyuncs.com替换成你从阿里云控制台复制的那个专属地址。你可以配置多个镜像加速器用逗号隔开Docker 会按顺序尝试。{ registry-mirrors: [ https://xxxx.mirror.aliyuncs.com ] }按CtrlO保存文件再按CtrlX退出 nano 编辑器。重要提示如果你之前已经存在daemon.json文件并且里面有其他配置比如之前设置过的日志驱动等你需要用文本编辑器打开在现有的大括号{}内添加registry-mirrors: [...]这一行注意格式和逗号确保整个 JSON 是有效的。配置完成后需要重启 Docker 服务让新的配置生效sudo systemctl daemon-reload sudo systemctl restart docker现在我们来测试一下加速效果。拉取一个常用的镜像比如hello-worlddocker pull hello-world你应该能感觉到下载速度明显变快了。可以通过下面命令查看当前 Docker 使用的镜像仓库地址docker info | grep -A 1 Mirrors如果输出中显示了你的阿里云加速地址那就说明配置成功了。这个步骤我强烈建议大家都做一下能为你后续使用 Docker 节省大量等待时间体验提升不止一个档次。4. 灵魂所在部署Portainer实现可视化运维命令行用熟了固然高效但一个直观的图形界面对于管理、监控和快速排错来说简直是降维打击。Portainer 就是一个专门为 Docker 和 Kubernetes 设计的轻量级管理 UI。它本身也是一个 Docker 容器部署起来极其简单。4.1 拉取并运行Portainer容器首先我们把 Portainer 的镜像拉取到本地docker pull portainer/portainer-ce:latest这里我拉取的是portainer-ce社区版它是完全免费且功能强大的。拉取完成后我们需要创建一个数据卷volume来持久化 Portainer 的配置数据比如你设置的账号、管理的端点信息等。这样即使 Portainer 容器被删除重建你的数据也不会丢失。docker volume create portainer_data接下来就是启动 Portainer 容器的核心命令了。这条命令参数稍多我逐一解释docker run -d \ --name portainer \ -p 9000:9000 \ --restartalways \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:latest-d让容器在后台运行detached mode。--name portainer给这个容器起个名字方便管理。-p 9000:9000端口映射。把容器内部的 9000 端口映射到树莓派宿主机的 9000 端口。这样我们才能通过浏览器访问。--restartalways设置重启策略。如果容器意外停止Docker 会自动重启它。即使树莓派重启这个容器也会自动启动非常省心。-v /var/run/docker.sock:/var/run/docker.sock这是最关键的一个挂载。/var/run/docker.sock是 Docker 守护进程Docker daemon的 Unix 套接字文件。把它挂载到容器内Portainer 就能通过这个“管道”与宿主机的 Docker 引擎直接通信从而管理所有容器、镜像、网络等。-v portainer_data:/data把我们刚才创建的数据卷挂载到容器内的/data目录用于保存数据。portainer/portainer-ce:latest指定要运行的镜像。执行完这条命令Portainer 容器就在后台跑起来了。你可以用docker ps命令查看一下它的运行状态。4.2 初始化配置与基础使用现在打开你电脑上的浏览器在地址栏输入http://你的树莓派IP地址:9000。比如你的树莓派内网 IP 是192.168.1.100那就输入http://192.168.1.100:9000。第一次访问会要求你创建一个管理员账号设置用户名和密码务必记住。接下来会让你选择连接的环境。因为我们是要管理树莓派本地的 Docker所以选择“Local”本地。下面还有 Docker Swarm 和 Kubernetes 的选项那是用于集群管理的我们单机环境用不到。点击 “Connect”恭喜你你就进入了 Portainer 的主界面。左侧是导航菜单非常清晰Dashboard仪表盘一目了然地看到宿主机的资源使用情况CPU、内存、存储、运行的容器/镜像/卷的数量。Containers容器这里列出所有容器。你可以点击容器名进入详情查看日志、统计信息、控制台还能进行启动、停止、重启、暂停、删除等操作完全不用敲命令。Images镜像管理所有本地镜像。可以在这里直接拉取新镜像填个镜像名就行或者删除不再需要的镜像释放空间。Volumes卷和Networks网络管理数据卷和网络创建、查看、删除都很方便。我举个最常用的例子部署一个 Nginx 网页服务器。在 Portainer 里你不需要记docker run那一长串参数。进入 “Containers” 页面点击 “Add container”。在 “Image” 栏输入nginx:latest给容器起个名字比如my-web。在 “Network ports configuration” 那里点开 “Publish a new network port”把容器端口80映射到主机端口比如8080。最后点击 “Deploy the container”。几秒钟后一个 Nginx 容器就跑起来了。你现在访问http://树莓派IP:8080就能看到 Nginx 的欢迎页面。整个过程鼠标点几下就完成了是不是比敲命令直观多了5. Docker核心命令与Portainer图形化操作对照虽然有了 Portainer但了解一些基础的 Docker 命令还是很有必要的特别是在排查问题或者编写自动化脚本的时候。下面我列一些最常用的命令并对应说明在 Portainer 里怎么实现同样的功能这样你能更深刻地理解两者的关系。5.1 镜像管理命令行操作拉取镜像docker pull nginx:alpine拉取轻量版的 nginx查看本地镜像docker images或docker image ls删除镜像docker rmi 镜像ID或镜像名如果镜像有容器在用需要先删容器Portainer 对应操作进入 “Images” 页面。页面顶部就有 “Pull an image” 的输入框直接输入nginx:alpine点 Pull 就行。所有本地镜像会以卡片或列表形式展示镜像大小、创建时间清清楚楚。想删除哪个勾选后点 “Remove” 即可。5.2 容器生命周期管理命令行操作运行新容器docker run -d --name my-nginx -p 8080:80 nginx:alpine查看运行中的容器docker ps查看所有容器包括已停止的docker ps -a停止容器docker stop my-nginx启动已停止的容器docker start my-nginx重启容器docker restart my-nginx删除已停止的容器docker rm my-nginx加-f可强制删除运行中的Portainer 对应操作所有操作都在 “Containers” 页面完成。每个容器卡片或行后面都有一排按钮图标分别对应启动三角、停止方块、重启循环、删除垃圾桶。点击容器名可以进入详情页这里的功能更强大你可以看到容器的实时资源消耗图表CPU、内存、网络IO可以查看实时日志并支持搜索过滤甚至可以打开一个网页版的终端Console直接进入容器内部执行命令就像用docker exec -it一样。5.3 查看日志与进入容器命令行操作查看日志docker logs my-nginx加-f可以实时跟踪加--tail 20只看最后20行进入容器终端docker exec -it my-nginx /bin/sh对于 alpine 镜像用/bin/sh其他常用/bin/bashPortainer 对应操作在容器详情页有独立的 “Logs” 标签页日志自动分页可以轻松上下滚动查看还有自动刷新和下载日志的选项。旁边就是 “Console” 标签页点击 “Connect” 就直接打开一个可交互的 Shell无需记忆复杂的exec命令参数。通过对比你会发现Portainer 把这些命令封装成了直观的按钮和界面。对于日常管理比如看看哪个容器占内存多了快速查一下错误日志或者临时改个配置文件用 Portainer 的效率远高于反复敲命令。它尤其适合管理多个容器组成的应用栈比如一个 Web 应用需要数据库、缓存、后端服务等多个容器在 Portainer 里可以清晰地看到它们的关联和状态。6. 进阶实战用Docker Compose部署一个完整应用栈到目前为止我们都是单个容器地部署。但在真实项目中一个应用往往由多个服务容器组成比如一个 WordPress 博客就需要 WordPress 容器和 MySQL 数据库容器它们之间还需要网络互通。手动用docker run一个个启动管理起来很麻烦。这时候Docker Compose 就该上场了。Docker Compose 允许你用一个 YAML 格式的配置文件通常叫docker-compose.yml来定义和运行多个容器组成的应用。Portainer 也完美支持通过 Compose 文件来部署应用这让复杂应用的部署变得像填空一样简单。6.1 安装Docker Compose首先我们需要在树莓派上安装 Docker Compose。由于树莓派是 ARM 架构我们最好使用 pipPython 包管理工具来安装兼容性最好的版本。确保你的树莓派上安装了 Python3 和 pip3sudo apt install -y python3 python3-pip然后使用 pip3 安装 Docker Composesudo pip3 install docker-compose安装完成后验证一下docker-compose --version6.2 编写一个简单的Compose文件我们来部署一个经典的组合Nginx MySQL PHPMyAdmin。在树莓派上创建一个目录比如~/myapp然后在这个目录里创建docker-compose.yml文件mkdir ~/myapp cd ~/myapp nano docker-compose.yml将以下内容粘贴进去version: 3.8 services: nginx: image: nginx:alpine container_name: web-server ports: - 80:80 volumes: - ./html:/usr/share/nginx/html depends_on: - mysql networks: - app-network mysql: image: mysql:8.0 container_name: db restart: always environment: MYSQL_ROOT_PASSWORD: my-secret-pw MYSQL_DATABASE: myapp_db volumes: - mysql_data:/var/lib/mysql networks: - app-network phpmyadmin: image: phpmyadmin/phpmyadmin container_name: db-admin restart: always ports: - 8080:80 environment: PMA_HOST: mysql UPLOAD_LIMIT: 128M depends_on: - mysql networks: - app-network volumes: mysql_data: networks: app-network: driver: bridge我来解释一下这个文件定义了三个服务容器nginx,mysql,phpmyadmin。nginx使用轻量版镜像将宿主机的./html目录挂载到容器的网页根目录这样我们可以在宿主机直接修改网页文件。它依赖mysql服务。mysql设置了 root 密码和初始数据库。使用了一个命名卷mysql_data来持久化数据库文件这样即使容器删除数据也不会丢。phpmyadmin一个管理 MySQL 的 Web 工具。通过环境变量PMA_HOST指定它要连接的数据库主机名就是mysqlCompose 会自动用服务名作为容器的主机名实现服务发现。所有服务都连接到一个自定义的桥接网络app-network这样它们可以通过服务名互相访问与宿主机网络隔离更安全。6.3 在Portainer中部署Compose应用传统方式是在命令行进入docker-compose.yml所在目录运行docker-compose up -d。但在 Portainer 里我们可以用更图形化的方式。进入 Portainer在左侧导航找到 “Stacks”。Stack 在 Portainer 里就代表一个由 Compose 文件定义的应用集合。点击 “Add stack”。给这个 Stack 起个名字比如my-full-app。最关键的一步在 “Web editor” 标签页中将我们刚才编写的docker-compose.yml文件内容完整地粘贴进去。Portainer 的编辑器还支持语法高亮很友好。粘贴好后直接点击页面下方的 “Deploy the stack”。Portainer 会解析这个 Compose 文件然后依次拉取镜像如果本地没有、创建网络、创建卷最后启动所有容器。部署完成后你回到 “Containers” 页面会看到三个容器已经整齐地运行起来了并且它们的名字都带有 Stack 名前缀便于识别。点击 “Stacks” 页面中的my-full-app你可以看到这个 Stack 的整体状态可以一键停止、启动或删除整个应用栈。现在你可以在浏览器访问http://树莓派IP看到 Nginx 的默认页面你可以在~/myapp/html目录放自己的index.html。http://树莓派IP:8080访问 PHPMyAdmin用 root 和密码my-secret-pw登录管理你的 MySQL 数据库。通过这个实战你就能体会到 Docker Compose 配合 Portainer 的强大之处。复杂的多容器应用只需要一个配置文件就能描述清楚并且可以一键部署、统一管理。这对于在树莓派上搭建家庭媒体中心如 Jellyfin、自动化工具如 Home Assistant等复杂环境是必不可少的技能。7. 日常维护与问题排查心得把环境搭起来只是开始要让它在树莓派上稳定运行还需要一些维护技巧。这里分享几个我踩过坑后总结的经验。监控资源占用树莓派的内存和存储空间有限。务必经常通过 Portainer 的 Dashboard 或使用命令行docker stats查看容器们的资源消耗。如果某个容器内存泄漏可能会拖垮整个系统。对于不常用的容器及时停止它。日志是救星当容器运行出现问题时第一反应就是看日志。Portainer 的日志查看器比命令行更友好支持搜索和实时跟踪。对于 Web 服务我习惯将应用的访问日志和错误日志也通过-v挂载到宿主机指定目录方便用其他工具分析。镜像清理Docker 用久了会积累很多无用的镜像和停止的容器占用宝贵的 SD 卡空间。定期清理很重要。在 Portainer 的 “Images” 页面可以很直观地按大小排序删除那些旧的、无用的镜像。对于容器可以用命令行docker system prune -a谨慎使用它会删除所有已停止的容器、所有未被使用的网络、所有悬空的镜像和构建缓存但在执行前最好在 Portainer 里确认一下哪些是真的不需要了。备份数据卷你的应用数据比如数据库文件、配置文件如果保存在 Docker 卷Volume里一定要定期备份。卷的数据通常位于/var/lib/docker/volumes/下但直接操作比较麻烦。更推荐的方式是运行一个临时容器挂载需要备份的卷和宿主机备份目录然后用tar命令打包。或者使用 Portainer 的卷管理功能虽然不能直接下载卷内容但可以清楚地看到卷和容器的绑定关系提醒你不要误删。网络问题排查如果容器之间无法通信首先检查它们是否在同一个自定义网络中在 Portainer 的 “Networks” 里查看。然后可以进入容器内部用 Portainer 的 Console用ping命令测试服务名如ping mysql是否能解析为 IP 地址。这能快速定位是网络配置问题还是应用本身的问题。最后关于树莓派本身的建议强烈推荐使用高质量的 MicroSD 卡甚至考虑用 USB SSD 来作为系统盘能极大提升 Docker 容器 IO 性能和寿命。同时为树莓派配备一个稳定的电源和良好的散热是保证其 7x24 小时稳定运行的基础。我的树莓派 4B 跑了十多个容器包括数据库、反向代理、监控工具等已经稳定运行了大半年可视化运维带来的便利让我几乎忘了它们的存在直到需要调整配置或更新版本时Portainer 的界面才让我感受到这一切是多么的轻松。