Debian 12 VPS Docker 面板选择与安全部署教程
这篇笔记整理一台 Debian 12 新 VPS 从初始化加固到 Docker 应用管理的完整路线。目标是:先保证 SSH 不被锁死,再完成基础安全配置,然后安装 Docker,最后用 Dockge 管理 Compose 应用,并用 Nginx Proxy Manager 统一处理域名和 HTTPS。
推荐的最终架构是:
公网入口:
80/tcp
443/tcp
SSH:
自定义端口,例如 8622
禁止 root 登录
禁止密码登录
只允许密钥登录
安全组件:
UFW
fail2ban
unattended-upgrades
Docker 管理:
Docker Engine
Docker Compose Plugin
Dockge
反向代理:
Nginx Proxy Manager
公共 Docker 网络 npm_proxy适用场景
这套方案适合以下 VPS 使用场景:
- 准备用 Docker Compose 长期部署多个自建应用。
- 希望有一个轻量 Web 面板管理 Compose 文件和容器日志。
- 想用域名访问应用,而不是记住一堆端口。
- 希望管理面板不直接裸露到公网。
- 想在 Debian 12 上先完成基础安全加固,再部署服务。
如果只是临时测试一两个容器,纯命令行也可以;如果准备长期运行博客、Alist、Uptime Kuma、Vaultwarden、数据库、代理服务等,Dockge + Nginx Proxy Manager 会更好维护。
总体部署顺序
建议按这个顺序执行:
1. 保留当前 SSH 连接,避免配置错误后失联
2. 修复 hostname / sudo warning
3. 更新系统并安装基础工具
4. 配置 UFW 防火墙
5. 修改 SSH 配置
6. 安装 fail2ban
7. 开启自动安全更新
8. 安装 Docker Engine 和 Compose Plugin
9. 安装 Dockge
10. 安装 Nginx Proxy Manager
11. 创建公共 Docker 网络 npm_proxy
12. 后续应用统一接入 npm_proxy,由 NPM 做域名反代1. 保留当前 SSH 安全窗口
开始加固前,不要关闭当前 SSH 窗口。后续每次修改 SSH 或防火墙,都新开一个终端测试登录。
例如计划把 SSH 改到 8622 端口后,本地 PowerShell 测试:
ssh -p 8622 fage@你的服务器IP新窗口确认能登录后,再关闭旧窗口或删除旧端口规则。这样即使某一步配置错误,也还有一个可用会话可以救回服务器。
2. 修复 sudo hostname 警告
如果执行 sudo 时出现类似提示:
sudo: unable to resolve host imztb先检查主机名和 hosts:
hostname
cat /etc/hostname
cat /etc/hosts如果 hostname 是 imztb,编辑 /etc/hosts:
sudo nano /etc/hosts确保至少包含:
127.0.0.1 localhost
127.0.1.1 imztb测试:
sudo whoami如果输出 root 且不再出现 warning,说明修复完成。
3. 更新系统并安装基础工具
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl wget git vim nano ca-certificates gnupg lsb-release unzip htop这些工具会在后续下载 Docker 源、编辑配置、检查资源和排障时用到。
4. 配置 UFW 防火墙
安装 UFW:
sudo apt install -y ufw默认拒绝入站,允许出站:
sudo ufw default deny incoming
sudo ufw default allow outgoing放行新的 SSH 端口:
sudo ufw allow 8622/tcp如果后续要部署网站或反向代理,放行 HTTP 和 HTTPS:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp启用防火墙:
sudo ufw enable查看状态:
sudo ufw status verbose确认至少有:
8622/tcp ALLOW IN
80/tcp ALLOW IN
443/tcp ALLOW IN如果还没有确认新 SSH 端口能正常登录,可以临时保留 22:
sudo ufw allow 22/tcp确认 8622 登录成功后再删除:
sudo ufw delete allow 22/tcp5. 修改 SSH 加固配置
编辑 SSH 服务端配置:
sudo nano /etc/ssh/sshd_config推荐配置:
Port 8622
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3关键参数说明:
Port 8622:修改 SSH 监听端口,减少默认端口扫描噪音。PermitRootLogin no:禁止 root 直接登录。PasswordAuthentication no:禁止密码登录,只使用密钥登录。PubkeyAuthentication yes:启用公钥认证。KbdInteractiveAuthentication no:关闭键盘交互式认证,避免绕过密码登录策略。UsePAM yes:保留 PAM 会话管理能力,Debian 上通常建议保持开启。X11Forwarding no:关闭 X11 转发,服务器场景一般用不到。ClientAliveInterval 300:每 300 秒检查一次客户端连接。ClientAliveCountMax 2:连续 2 次无响应后断开空闲连接。MaxAuthTries 3:限制单次连接认证尝试次数。
检查 SSH 配置语法:
sudo sshd -t无输出表示语法正常。然后重载 SSH:
sudo systemctl reload ssh检查监听端口:
sudo ss -lntp | grep ssh新开本地终端测试:
ssh -p 8622 fage@你的服务器IP确认能登录后,再考虑删除 22 端口的防火墙放行。
6. 安装 fail2ban
fail2ban 可以根据登录失败日志自动封禁恶意 IP。
sudo apt install -y fail2ban创建配置:
sudo nano /etc/fail2ban/jail.local写入:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
[sshd]
enabled = true
port = 8622
filter = sshd
logpath = %(sshd_log)s
maxretry = 5启动并设置开机自启:
sudo systemctl enable --now fail2ban检查状态:
sudo fail2ban-client status
sudo fail2ban-client status sshd7. 开启自动安全更新
安装 unattended-upgrades:
sudo apt install -y unattended-upgrades apt-listchanges
sudo dpkg-reconfigure unattended-upgrades弹窗选择 Yes。然后检查服务:
systemctl status unattended-upgrades这一步可以让系统自动安装安全更新,适合长期运行的 VPS。
8. 安装 Docker Engine 和 Compose Plugin
Dockge 本身也是 Docker 应用,所以使用 Dockge 之前必须先安装 Docker。
创建 keyrings 目录并导入 Docker GPG key:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg添加 Docker 官方源:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null安装 Docker:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin启动并开机自启:
sudo systemctl enable --now docker让普通用户可以执行 Docker 命令:
sudo usermod -aG docker fage执行后退出 SSH 并重新登录,让用户组生效。然后测试:
docker version
docker compose version9. Docker 与 UFW 的安全注意事项
Docker 会直接操作 iptables,有时可能绕过 UFW 的入站规则。因此管理面板不要随便用下面这种方式直接暴露到公网:
ports:
- "5001:5001"更推荐把管理端口只绑定本机:
ports:
- "127.0.0.1:5001:5001"然后从本地电脑通过 SSH 隧道访问:
ssh -p 8622 -L 5001:127.0.0.1:5001 fage@服务器IP浏览器打开:
http://127.0.0.1:5001这样管理面板不会直接暴露公网,安全性更高。
10. Docker 面板选择建议
常见选择大致可以分为三类:
Dockge:
轻量,专注 Docker Compose,适合个人 VPS 管理多个 compose 应用。
Portainer:
功能更全,但更重,适合更复杂的 Docker 管理场景。
纯命令行:
最透明、依赖少,但维护多个应用时不如 Web 面板直观。如果目标是在一台 VPS 上部署多个自建服务,推荐使用 Dockge。它可以集中管理 compose 应用、在线编辑 compose.yaml、启动停止服务、查看日志,比纯命令行更直观,也比 Portainer 更轻。
可以把关系理解为:
Docker Engine = 地基
Docker Compose = 应用编排工具
Dockge = Docker Compose 的网页管理面板Dockge 不能替代 Docker,它只是 Docker 之上的管理工具。
11. 安装 Dockge
创建目录:
sudo mkdir -p /opt/dockge
sudo mkdir -p /opt/stacks
sudo chown -R fage:fage /opt/dockge /opt/stacks
cd /opt/dockge创建 compose.yaml:
nano compose.yaml写入:
services:
dockge:
image: louislam/dockge:1
container_name: dockge
restart: unless-stopped
ports:
- "127.0.0.1:5001:5001"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /opt/stacks:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks启动:
docker compose up -d查看状态:
docker compose ps
docker logs dockge本地 PowerShell 开 SSH 隧道:
ssh -p 8622 -L 5001:127.0.0.1:5001 fage@服务器IP浏览器打开:
http://127.0.0.1:5001首次进入会要求创建管理员账号。密码一定要足够强。
12. FinalShell 粘贴 YAML 的建议
FinalShell 里直接往 nano 粘贴大段 YAML,容易出现缩进、换行、特殊字符错乱。更稳的方式是用 here-document 写文件。
例如重写 Dockge 的 compose:
cat > /opt/dockge/compose.yaml <<'EOF'
services:
dockge:
image: louislam/dockge:1
container_name: dockge
restart: unless-stopped
ports:
- "127.0.0.1:5001:5001"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /opt/stacks:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
EOFcat <<'EOF' 的好处是内容会原样写入文件,不容易被 shell 展开变量,也不依赖 nano 的粘贴行为。
如果仍想用 nano,建议先在本地编辑器里整理好 YAML,再少量分段粘贴,并用下面命令检查最终文件:
sed -n '1,120p' /opt/dockge/compose.yaml13. 规划 Docker 目录
推荐目录:
/opt/dockge
compose.yaml
data/
/opt/stacks
nginx-proxy-manager/
compose.yaml
alist/
compose.yaml
uptime-kuma/
compose.yaml
vaultwarden/
compose.yamlDockge 管理 /opt/stacks 下的各个应用,每个应用一个目录,方便备份和迁移。
14. 部署 Nginx Proxy Manager
Nginx Proxy Manager,简称 NPM,用来把域名转发到 Docker 内部应用。
例如:
https://alist.example.com -> http://alist:5244
https://kuma.example.com -> http://uptime-kuma:3001
https://dockge.example.com -> http://dockge:5001先确认防火墙放行网站端口:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload不要把 NPM 管理端口 81 直接开放到公网。推荐让 80/443 对公网开放,81 只绑定本机。
创建公共 Docker 网络:
docker network create npm_proxy如果提示已经存在,可以忽略。
在 Dockge 里创建应用,名称建议为:
nginx-proxy-managercompose.yaml 示例:
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "127.0.0.1:81:81"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- npm_proxy
networks:
npm_proxy:
external: true这个配置里:
- "80:80"
- "443:443"用于公网访问网站。
- "127.0.0.1:81:81"表示 NPM 后台只允许服务器本机访问。
15. 访问 NPM 后台
因为 81 端口只绑定本机,所以需要 SSH 隧道:
ssh -p 8622 -L 8181:127.0.0.1:81 fage@服务器IP保持这个窗口不要关,浏览器打开:
http://127.0.0.1:8181NPM 默认账号:
Email: [email protected]
Password: changeme首次登录后立即修改邮箱和密码。
16. 配置域名 DNS
假设域名是 example.com,可以添加这些 A 记录:
类型 主机记录 值
A npm 你的服务器IP
A dockge 你的服务器IP
A app 你的服务器IP也可以添加泛解析:
类型 主机记录 值
A * 你的服务器IP这样以后 alist.example.com、kuma.example.com、vault.example.com 都可以在 NPM 里单独配置。
17. 后续应用如何接入 NPM
只要应用需要通过域名访问,就建议加入公共网络:
networks:
- npm_proxy文件底部加:
networks:
npm_proxy:
external: true例如 Alist:
services:
alist:
image: xhofe/alist:latest
container_name: alist
restart: unless-stopped
volumes:
- ./data:/opt/alist/data
networks:
- npm_proxy
networks:
npm_proxy:
external: trueNPM 里配置:
Domain Names: alist.example.com
Scheme: http
Forward Hostname / IP: alist
Forward Port: 5244即使 Compose 没有写 ports,NPM 和应用在同一个 Docker 网络里,也可以通过容器名访问。这是最推荐的方式。
18. ports 要不要绑定 127.0.0.1
按用途判断。
NPM 入口服务
NPM 必须开放公网的 80 和 443:
ports:
- "80:80"
- "443:443"
- "127.0.0.1:81:81"81 是后台管理端口,建议只绑定 127.0.0.1。
管理面板
Dockge、Portainer、NPM 后台、Uptime Kuma 管理页这类服务,如果还想保留 SSH 隧道访问,建议:
ports:
- "127.0.0.1:5001:5001"这样公网不能直接访问端口。
普通 Web 应用
如果应用只通过 NPM 域名访问,通常不需要写 ports,只要加入 npm_proxy 网络即可。
需要公网直连的服务
只有确实需要公网直连时,才开放:
ports:
- "0.0.0.0:端口:容器端口"这类服务要特别确认认证、访问限制和防火墙策略。
记忆规则:
NPM:开放 80、443;81 绑 127.0.0.1
管理面板:端口尽量绑 127.0.0.1
普通应用:不写 ports,只加入 npm_proxy
需要公网直连的服务:才开放 0.0.0.0:端口19. 是否要用域名访问 Dockge
可以用域名访问 Dockge,但要谨慎。
Dockge 挂载了:
/var/run/docker.sock:/var/run/docker.sock这意味着 Dockge 拥有很高的 Docker 控制权限,基本等价于服务器管理能力。
如果要配置:
https://dockge.example.com至少建议:
- Dockge 密码必须强。
- NPM 给
dockge.example.com添加 Access List。 - 最好限制 IP 或增加 Basic Auth。
- 不要把
5001端口公网开放。 - 保留 SSH 隧道作为备用访问方式。
Dockge 的 compose 可以改成:
services:
dockge:
image: louislam/dockge:1
container_name: dockge
restart: unless-stopped
ports:
- "127.0.0.1:5001:5001"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /opt/stacks:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
networks:
- npm_proxy
networks:
npm_proxy:
external: true然后重新应用:
cd /opt/dockge
docker compose up -dNPM 里添加 Proxy Host:
Domain Names: dockge.example.com
Scheme: http
Forward Hostname / IP: dockge
Forward Port: 5001SSL 里勾选:
Request a new SSL Certificate
Force SSL
HTTP/2 Support20. Dockge 域名访问 502 的排查
如果访问 dockge.example.com 出现 502 Bad Gateway,说明浏览器已经访问到 NPM,但 NPM 转发不到 Dockge 容器。
常见原因:
1. Dockge 没有真正加入 npm_proxy 网络
2. NPM 里 Forward Hostname 写错
3. NPM 里 Forward Port 写错
4. Dockge 容器名不是 dockge
5. Dockge 服务本身没正常启动检查 Dockge 容器状态
docker ps应该能看到:
dockge
nginx-proxy-manager如果没有 dockge,查看日志:
docker logs dockge --tail=50检查 Docker 网络
docker inspect dockge --format '{{json .NetworkSettings.Networks}}'正常情况下能看到 npm_proxy。
也可以检查整个网络:
docker network inspect npm_proxy输出里应该同时有:
nginx-proxy-manager
dockge如果只有 NPM 没有 Dockge,就是 Dockge 没接入网络。
检查 Dockge compose
Dockge 的 compose 需要同时包含:
networks:
- npm_proxy以及底部:
networks:
npm_proxy:
external: true修改后要执行:
cd /opt/dockge
docker compose up -d只重启 Docker 服务不一定会重新应用 compose 网络配置。
检查 NPM Proxy Host
NPM 中应填写:
Domain Names: dockge.example.com
Scheme: http
Forward Hostname / IP: dockge
Forward Port: 5001不要填:
127.0.0.1
localhost
服务器IP
https
443对 NPM 容器来说,127.0.0.1 指的是 NPM 容器自己,不是宿主机,也不是 Dockge。
在 NPM 容器中测试
进入 NPM 容器:
docker exec -it nginx-proxy-manager sh测试访问 Dockge:
wget -S -O- http://dockge:5001如果正常,会看到 HTML 内容。
如果提示:
bad address 'dockge'说明 NPM 解析不到 Dockge,通常是 Docker 网络没打通。
如果提示:
connection refused说明找到了 Dockge,但 Dockge 的 5001 没监听或服务异常。
测试完退出:
exit临时快速修复
如果只想先恢复访问,可以在 NPM 里临时填:
Scheme: http
Forward Hostname / IP: 172.17.0.1
Forward Port: 5001前提是 Dockge 仍然有:
ports:
- "127.0.0.1:5001:5001"但这个方式不如 Docker 网络稳定。长期推荐使用:
Forward Hostname / IP: dockge
Forward Port: 500121. 常用检查命令
SSH:
sudo ss -lntp | grep ssh
sudo systemctl status ssh防火墙:
sudo ufw status numberedfail2ban:
sudo fail2ban-client status sshdDocker:
docker ps
docker logs 容器名
docker compose ps端口监听:
sudo ss -lntp系统资源:
htop
df -h
free -h总结
Debian 12 VPS 自建服务的关键不是先装哪个面板,而是先把基础安全做好。推荐先完成 SSH、UFW、fail2ban 和自动安全更新,再安装 Docker。应用管理层可以选择 Dockge,它适合个人 VPS 管理多个 Compose 应用;域名访问层用 Nginx Proxy Manager,后续普通应用统一加入 npm_proxy 网络,由 NPM 通过容器名转发。
管理面板类服务不要直接裸露公网。更稳妥的做法是:端口绑定 127.0.0.1,平时用 SSH 隧道访问;如果要用域名访问,也要加 HTTPS、强密码、Access List 或 IP 限制,并保留隧道作为备用入口。