引言
Docker 依然是个人用户最佳的容器管理方案。
对于绝大多数问题,RTFM,或者让你的 agent 代劳。
安装
安装 Docker Engine + Docker Compose 即可,不建议使用 Docker Desktop。Windows 用户请直接在 WSL2 中安装 Docker(虽然 Windows 版 Docker Desktop 默认使用基于 WSL 2 的引擎,但没要多此一举,徒增不稳定性)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh ./get-docker.sh --dry-run
代理与镜像
代理
为 Docker Daemon 配置代理
daemon.json 默认位置 /etc/docker/daemon.json
参考 https://docs.docker.com/engine/daemon/proxy/#daemon-configuration
主要对镜像拉取生效。
为 Docker CLI 配置代理
参考 https://docs.docker.com/engine/cli/proxy/
Docker CLI 代理,实际上并不是给 docker 命令本身设置代理,而是通过 CLI 配置向容器传递代理环境变量,比如 Dockerfile 中的 RUN pip install 就会走 Docker CLI 代理。
添加可用镜像站
大部分 Docker Hub 镜像站已经失效 / 不够稳定 / 仓库不够新,直接用代理,或者自己搭一个 Docker Hub 镜像。
Docker CLI
官方 cheatsheet 比我的嘟囔有用。
建议用 Docker Compose 创建和管理容器,可维护性更好。
权限
如果当前用户不在docker的用户组中(大概率不在):
- 对于个人 NAS、homelab 和 workstation,可以考虑将当前用户加入 docker 组
sudo usermod -aG docker "$USER"
newgrp docker
运行 docker ps 验证当前用户是否已拥有足够权限
- 对于多用户服务器,建议在每一句命令前加上
sudo.
拉取镜像
docker pull <image-name>
创建并运行容器,参考 https://docs.docker.com/reference/cli/docker/container/run/
docker run --name <container_name> <image_name>
常用选项:
--name <container name>为容器命名--restart always|unless-stopped|no重启方式-v Source (Host):Destination (Container)文件(夹)映射-p <host_port>"<container_port>端口映射
停止、删除与查看日志
docker stop <container_name>
docker rm <container_name>
docker logs <container_name>
查看所有运行中的容器
docker ps
在容器内执行命令
docker exec CONTAINER_NAME [command]
保存镜像
https://docs.docker.com/reference/cli/docker/image/save/#description
docker save <image_name> > xxxx.tar
导出容器
https://docs.docker.com/reference/cli/docker/container/export/
docker export <container_name> > xxxx.tar
Docker Volume
docker volume ls
docker volume create <volume_name>
docker volume rm <volume_name>
导出 volume
docker run --rm -v your_volume_name:/data -v $(pwd):/backup alpine \
tar cvf /backup/backup.tar -C /data .
导入 volume
docker run --rm -v your_volume_name:/data -v $(pwd):/backup alpine \
sh -c "rm -rf /data/* && tar xvf /backup/backup.tar -C /data"
Build
鸽了。
Docker Compose
人生苦短,我用 Docker Compose。
你只需要一个 docker-compose.yml,这里有一些不错的示例
启动服务
docker compose up -d
-d表示后台运行(detach)
停止服务
docker compose down
容器
暴论环节:从实用性角度出发,对于大部分个人用户的生活场景而言,NAS 也好,homelab 也罢,都是“伪”需求(以折腾本身为乐趣的除外)。相比自部署的服务,商业公司的产品通常更加便捷、稳定,算上时间成本甚至更便宜。开发和企业级场景另当别论,但那是 devops 干的事了。
以下是我长期使用后最终留下的几个容器。
- 为了迁移方便,建议使用确定的版本 tag 而不是
latest,以免迁移时遇到各种奇妙的兼容性问题。 - 不建议用群晖 NAS 做家用 Docker 服务器,这家公司目前沉迷企业级,家庭用户的优先级比较低。
Caddy
用于替代 Nginx Proxy Manager 进行 https 反向代理,Caddy 使用配置文件进行配置的方式更符合我的喜好。
我的使用场景是在校园网范围内实现通过域名(不用添加端口)以 https 的方式访问本地部署的服务。
在同一文件夹中(比如 caddy-lan)新建三个文件:docker-compose.yml,.env 和 caddy/Caddyfile
# docker-compose.yml
name: caddy-lan
services:
caddy:
image: ghcr.io/caddybuilds/caddy-cloudflare:2.11.7-alpine
restart: unless-stopped
ports:
# 必须是分配给 Docker 宿主机的局域网 IPv4 地址。
- "${LAN_IP:?Set LAN_IP in .env}:80:80/tcp"
- "${LAN_IP:?Set LAN_IP in .env}:443:443/tcp"
- "${LAN_IP:?Set LAN_IP in .env}:443:443/udp"
environment:
CF_API_TOKEN: "${CF_API_TOKEN:?Set CF_API_TOKEN in .env}"
LAN_CIDRS: "${LAN_CIDRS:?Set LAN_CIDRS in .env}"
volumes:
- ./caddy:/etc/caddy:ro
- ./data:/data
- ./config:/config
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
在 .env 中设置 Docker 宿主机 IP,局域网网段以及 Cloudflare API (user) Token。Cloudflare 中域名解析指向:
- 若宿主机直连校园网,则直接指向宿主机在校园网中的 ipv4 地址;
- 若路由器连接校园网,宿主机连接路由器,则域名解析指向路由器在校园网中的 ipv4 地址,然后在路由器设置中将 80 和 443 端口转发给宿主机。
我的网络拓扑是后面这一种情况。
# .env
# 运行 Caddy 的 Docker 宿主机所持有的局域网 IPv4 地址。
LAN_IP=192.168.31.250
# 允许本地局域网以及路由器直连的上行子网访问。
# 如有其他经路由的客户端网段,按需添加。多个 CIDR 之间用空格分隔。
LAN_CIDRS="192.xxx.xxx.xxx/24 10.xxx.xxx.xxx/20"
# Cloudflare API Token:Zone / Zone / Read + Zone / DNS / Edit。
# 将 Zone Resources 限制为自己的域名。不要使用 Global API Key。
CF_API_TOKEN=
最后在 caddy/Caddyfile 中设置需要被反向代理的服务的局域网地址和对应域名(将 server1、server2 等修改为你实际的二级域名)
# caddy/Caddyfile
{
acme_ca https://acme-v02.api.letsencrypt.org/directory
}
*.artinx.tech {
tls {
dns cloudflare {env.CF_API_TOKEN}
}
log
# 不是局域网的访问直接排除
@outside not remote_ip {$LAN_CIDRS} 127.0.0.1/32 ::1/128
@server1 host server1.example.com
@server2 host server2.example.com
route {
respond @outside "LAN access only" 403
reverse_proxy @server1 192.168.xxx.xxx:xxxx
reverse_proxy @server2 192.168.xxx.xxxx:xxxx
respond "Not Found" 404
}
}
VaultWarden
参考 部署 Vaultwarden + Cloudflare Tunnel 实现跨平台密码管理
Qbitorrent
最强大的 BT 下载与管理工具,没有之一。
我所使用的组合:
Qbitorrent WebUI + Client-Blocker
- Qbittorrent WebUI 为本体
- 不使用任何美化前端,我是原教旨主义者
- Client-Blocker 是一个拦截器,可以拦截迅雷等吸血客户端。在 PCDN 遭整治后疯狂恶意下载 BT 种子的今天尤为重要。
services:
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:5.2.4
container_name: qbittorrent_5.2.4
# network_mode: "host"
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- WEBUI_PORT=21088
- TORRENTING_PORT=16881
volumes:
- ./config:/config
# 修改为你实际的下载路径
- /mnt/Videos/Contents:/downloads
ports:
- 21088:21088
- 16881:16881
- 16881:16881/udp
restart: unless-stopped
blocker:
image: simpletracker/qbittorrent-clientblocker:3.7
container_name: qbit-blocker_3.7
restart: unless-stopped
volumes:
- ./blocker/config.json:/app/config.json
Blocker 所用的 config.json 参考 Simple-Tracker/qBittorrent-ClientBlocker-Docker 版本使用
Portainer
Portainer、Grafana 这类工具在我看来是给运维团队准备的,homelab 其实没必要折腾这些。
Agent 安装
services:
portainer:
image: portainer/portainer-ce:2.45.3
container_name: portainer
restart: always
ports:
- "8000:8000"
- "9443:9443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
添加 Docker Standalone 环境
https://docs.portainer.io/admin/environments/add/docker
性能监控方案
Node Exporter + Prometheus + Grafana
Node Exporter + Prometheus
Monitoring a Linux host with Prometheus, Node Exporter, and Docker Compose
Grafana
用 Grafana Cloud 省点事。
面板推荐:1860,8919。