站长必看:Docker 部署网站前,这些安全坑一定要堵上
Docker 安全加固方案|适合站长
对于站长来说,Docker 是一个非常实用的工具:它可以快速部署网站、数据库、缓存、反向代理、监控系统等服务,也方便迁移和备份。但与此同时,Docker 并不是“天然安全”的。很多站长在使用 Docker 时,只关注容器能不能跑起来,却忽略了镜像来源、权限控制、端口暴露、数据挂载、网络隔离、日志审计等问题。一旦配置不当,轻则网站被入侵、数据泄露,重则宿主机被拿下,影响整台服务器甚至更多业务。
本文面向站长群体,重点讲解一套实用、可落地的 Docker 安全加固方案。目标不是追求复杂的企业级安全体系,而是在不明显增加维护成本的前提下,尽可能降低常见风险。
一、站长使用 Docker 的主要安全风险
在开始加固之前,先明确 Docker 常见风险来源。
1. 使用不可信镜像
很多站长部署服务时,会直接从网上复制一条命令:
docker run xxx/yyy
如果镜像来源不明,里面可能包含后门、挖矿程序、恶意脚本,或者使用了存在漏洞的旧版本组件。容器一旦启动,就可能主动连接外部服务器、扫描内网、读取敏感文件。
2. 容器权限过高
部分教程为了“省事”,会建议使用:
--privileged
或者挂载宿主机关键目录:
-v /:/host
-v /var/run/docker.sock:/var/run/docker.sock
这些操作非常危险。拥有过高权限的容器,可能直接控制宿主机,甚至进一步控制其他容器。
3. 端口随意暴露
不少站长会把 MySQL、Redis、PostgreSQL、Elasticsearch、Docker 面板等服务直接暴露到公网。只要密码较弱、存在未授权访问或服务版本有漏洞,就可能被攻击者扫描并入侵。
4. 数据卷权限混乱
Docker 容器常常需要挂载网站目录、数据库目录、配置文件目录。如果权限设置不当,攻击者通过网站漏洞写入 WebShell 后,可能进一步修改配置、读取数据库备份、窃取密钥。
5. 缺少更新和审计
容器运行起来之后,很多站长就不再维护。镜像长期不更新,漏洞越积越多;日志没有查看,异常访问无法发现;资源没有限制,容器被攻击后可能拖垮整台服务器。
二、基础原则:最小权限、最少暴露、可追踪
Docker 安全加固可以归纳为三个核心原则。
1. 最小权限
容器只应该拥有完成任务所需的最低权限。能不用 root 就不用 root,能不用特权模式就不用特权模式,能只读挂载就不要读写挂载。
2. 最少暴露
不是所有服务都需要暴露到公网。数据库、缓存、管理后台、内部 API 应尽量只在内网或 Docker 网络内部访问。
3. 可追踪
服务运行状态、访问日志、容器日志、登录记录都应该能追踪。安全不是只靠“防”,还要能及时发现异常。
三、镜像安全:从源头降低风险
1. 优先使用官方镜像或可信镜像
部署常见服务时,优先选择 Docker Hub 官方镜像或项目官方提供的镜像。例如:
nginxmysqlpostgresrediswordpresstraefikcaddy
如果使用第三方镜像,应检查以下内容:
- 镜像维护者是否可信;
- 镜像是否长期更新;
- Star、下载量、Issue 反馈是否正常;
- 是否提供 Dockerfile;
- 是否包含不必要的软件和脚本。
2. 不要盲目使用 latest
很多教程喜欢写:
image: nginx:latest
这看似方便,但不适合生产环境。latest 可能在某次重启或更新后拉取到新版本,导致配置不兼容或引入未知问题。
建议固定版本:
image: nginx:1.26-alpine
这样便于回滚和排查问题。
3. 定期更新镜像
固定版本不等于永远不更新。站长应定期关注基础镜像和应用镜像的安全更新。建议每月检查一次核心服务,例如:
- Nginx / Caddy / Apache;
- PHP / Node.js / Java / Python;
- MySQL / PostgreSQL / Redis;
- WordPress、Typecho、Halo、各类面板。
更新前应先备份数据,最好在测试环境验证后再上线。
4. 使用轻量镜像
在满足需求的前提下,优先选择 alpine、slim 等轻量镜像。镜像越小,包含的工具越少,潜在攻击面通常也越小。例如:
image: node:20-alpine
不过需要注意,alpine 使用 musl libc,某些程序可能存在兼容问题。安全和稳定要结合实际情况选择。
四、容器运行权限加固
1. 避免使用 --privileged
--privileged 会给容器极高权限,除非你非常清楚自己在做什么,否则不要使用。普通网站、数据库、缓存、反向代理基本不需要特权模式。
错误示例:
docker run --privileged nginx
建议做法:不加 --privileged,并根据需要精确授权。
2. 避免挂载 Docker Socket
以下挂载非常危险:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
拥有 Docker Socket 访问权限的容器,几乎等同于拥有宿主机 root 权限。很多 Docker 管理面板、自动化工具会要求挂载它,站长必须谨慎使用。
如果确实需要使用,例如部署 Portainer、Watchtower 等工具,建议:
- 只在可信环境中使用;
- 面板设置强密码和二次验证;
- 不暴露到公网;
- 使用防火墙限制访问来源;
- 定期升级面板版本。
3. 指定非 root 用户运行
如果镜像支持,尽量使用非 root 用户运行容器。例如:
services:
app:
image: your-app:1.0
user: "1000:1000"
这样即使应用被攻破,攻击者在容器内获得的权限也会受到限制。
对于自建镜像,可以在 Dockerfile 中添加:
RUN adduser -D appuser
USER appuser
4. 设置只读文件系统
对于不需要写入系统目录的容器,可以启用只读文件系统:
read_only: true
如果应用需要写临时文件,可以单独挂载临时目录:
tmpfs:
- /tmp
这可以降低攻击者写入恶意文件、篡改系统文件的风险。
5. 限制 Linux capabilities
Docker 默认给容器保留了一些 Linux capabilities。可以先全部删除,再按需添加:
cap_drop:
- ALL
如果应用确实需要特定能力,再单独添加。对于多数 Web 应用来说,不需要额外 capability。
6. 禁止权限提升
建议添加:
security_opt:
- no-new-privileges:true
该选项可以防止容器内进程通过 setuid 等方式获得更高权限。
五、网络安全:不要把内部服务暴露到公网
1. 区分 ports 和 expose
在 Docker Compose 中,ports 会把端口映射到宿主机,可能暴露到公网:
ports:
- "3306:3306"
而 expose 只是在 Docker 内部网络中暴露端口,不会直接对公网开放:
expose:
- "3306"
对于数据库、Redis、内部 API,优先使用 expose 或不写端口映射,只允许同一 Docker 网络中的服务访问。
2. 数据库不要直接暴露公网
错误示例:
ports:
- "3306:3306"
如果 MySQL 暴露到公网,攻击者会持续爆破密码,甚至利用漏洞入侵。更安全的方式是让网站容器通过内部网络访问数据库:
services:
web:
networks:
- internal
db:
image: mysql:8.0
networks:
- internal
expose:
- "3306"
networks:
internal:
driver: bridge
3. 管理后台使用反向代理和访问限制
如果需要访问管理面板,例如 Portainer、phpMyAdmin、数据库管理工具等,建议:
- 不直接映射公网端口;
- 通过 Nginx、Caddy、Traefik 反向代理;
- 开启 HTTPS;
- 设置强密码;
- 限制 IP 白名单;
- 尽量增加二次认证。
Nginx 示例:
allow 你的固定IP;
deny all;
如果没有固定 IP,可以考虑使用 VPN、Tailscale、ZeroTier 等方式访问管理服务。
4. 使用独立 Docker 网络隔离服务
不要把所有容器都放在默认网络中。可以按业务创建不同网络:
networks:
frontend:
backend:
internal: true
示例:
services:
nginx:
networks:
- frontend
- backend
app:
networks:
- backend
db:
networks:
- backend
networks:
frontend:
backend:
internal: true
这样数据库只在后端网络中可见,外部无法直接访问。
六、数据卷和文件权限加固
1. 谨慎挂载宿主机目录
挂载目录时要遵循最小范围原则。不要为了方便直接挂载整个系统目录。
危险示例:
volumes:
- /:/host
正确做法是只挂载应用需要的目录:
volumes:
- ./data/mysql:/var/lib/mysql
- ./config/nginx:/etc/nginx/conf.d:ro
2. 配置文件尽量只读挂载
Nginx 配置、应用配置、证书目录等,如果容器不需要修改,应使用只读挂载:
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
这样即使容器被入侵,攻击者也不能轻易修改配置文件。
3. 控制网站目录权限
对于 PHP、WordPress 等站点,目录权限尤其重要。建议:
- 程序文件尽量不允许 Web 用户写入;
- 上传目录允许写入,但禁止执行脚本;
- 配置文件权限尽量收紧;
- 数据库备份不要放在 Web 可访问目录下。
例如 WordPress 站点可以将 wp-config.php 设置为更严格权限,并禁止上传目录执行 PHP。
Nginx 示例:
location ~* /uploads/.*\.php$ {
deny all;
}
4. 密钥和密码不要写死在镜像里
不要把数据库密码、API Key、私钥写入 Dockerfile 或提交到 Git 仓库。可以使用 .env 文件或 Docker secrets。
.env 文件也要注意权限:
chmod 600 .env
并确保不要上传到公开仓库。
七、资源限制:防止容器拖垮服务器
如果容器没有资源限制,被攻击或程序异常时可能占满 CPU、内存、磁盘 IO,导致整台服务器不可用。
1. 限制内存和 CPU
Docker Compose 示例:
services:
app:
mem_limit: 512m
cpus: "1.0"
不同版本 Compose 对资源限制支持略有差异,实际使用时要结合 Docker 版本测试。
2. 限制日志大小
容器日志如果不限制,可能不断增长,最终占满磁盘。建议配置日志轮转:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
这对于访问量较大的网站尤其重要。
3. 监控磁盘空间
站长至少应定期检查:
df -h
docker system df
清理无用镜像、容器、构建缓存时,可以使用:
docker system prune
但生产环境执行前要确认不会误删仍需保留的资源。
八、宿主机安全同样重要
Docker 安全不是只配置容器,宿主机本身也必须加固。
1. 保持系统更新
定期更新系统安全补丁:
apt update && apt upgrade
或在 CentOS、Rocky Linux、AlmaLinux 中使用:
dnf update
内核、OpenSSL、SSH、Docker Engine 等组件都应关注安全更新。
2. SSH 安全加固
建议:
- 禁止 root 密码登录;
- 使用 SSH 密钥登录;
- 修改默认端口不是必须,但可以降低扫描噪音;
- 安装 Fail2ban 防爆破;
- 限制允许登录的用户。
示例配置:
PermitRootLogin no
PasswordAuthentication no
修改 SSH 配置后,务必先保持当前会话不关闭,再新开窗口测试登录,避免把自己锁在服务器外。
3. 开启防火墙
使用 ufw 的示例:
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
只开放必要端口。数据库、Redis、管理面板端口原则上不要对公网开放。
4. 限制 Docker API
默认情况下,不要开启 Docker TCP API。如果必须远程管理 Docker,应使用 TLS 认证,并限制访问来源。暴露未认证 Docker API 是极高危行为,攻击者可以直接创建特权容器接管宿主机。
九、Web 服务部署安全建议
站长最常见的 Docker 场景是部署网站。以下建议非常实用。
1. 所有网站启用 HTTPS
可以使用 Caddy、Traefik 或 Nginx + Certbot 自动申请证书。HTTPS 不仅保护登录密码和 Cookie,也有利于搜索引擎和浏览器信任。
2. 设置安全响应头
常见安全头包括:
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
add_header X-XSS-Protection "1; mode=block";
如果网站结构允许,还可以配置更严格的 CSP,但 CSP 容易影响前端资源加载,需要测试后再启用。
3. 后台路径不要裸奔
WordPress、Typecho、宝塔面板、各类 CMS 后台都是扫描重点。建议:
- 使用强密码;
- 开启二次验证;
- 限制后台访问 IP;
- 避免使用默认管理员用户名;
- 定期删除不用的插件和主题;
- 插件、主题、CMS 主程序及时更新。
4. 上传目录禁止执行
大量网站入侵都和上传漏洞有关。即使应用层做了文件类型校验,也应在 Web 服务器层面禁止上传目录执行脚本。
十、备份与恢复:安全的最后防线
没有备份的安全方案是不完整的。因为即使防护再好,也可能遇到误操作、硬盘故障、勒索软件、供应链漏洞等问题。
1. 备份内容
至少备份以下内容:
- 网站源码;
- 数据库数据;
- Docker Compose 文件;
.env配置文件;- Nginx / Caddy / Traefik 配置;
- SSL 证书;
- 上传文件;
- 重要日志。
2. 备份策略
建议采用“本机 + 异地”的组合:
- 本机备份方便快速恢复;
- 异地备份防止服务器彻底损坏或被入侵后备份一起被删。
可以使用对象存储、另一台 VPS、NAS、云盘等方式保存备份。
3. 定期测试恢复
很多站长以为自己有备份,但真正出问题时才发现备份不可用。建议至少每季度测试一次恢复流程,确认数据库能导入、文件完整、配置可用。
十一、推荐的 Docker Compose 安全模板
下面是一个更安全的 Web 应用部署思路,仅供参考:
services:
nginx:
image: nginx:1.26-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf:/etc/nginx/conf.d:ro
- ./nginx/certs:/etc/nginx/certs:ro
- ./app/public:/var/www/html:ro
networks:
- frontend
- backend
read_only: true
tmpfs:
- /var/cache/nginx
- /var/run
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
app:
image: your-app:1.0.0
env_file:
- .env
volumes:
- ./app/uploads:/app/uploads
networks:
- backend
expose:
- "9000"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
db:
image: mysql:8.0
env_file:
- .env
volumes:
- ./mysql/data:/var/lib/mysql
networks:
- backend
expose:
- "3306"
security_opt:
- no-new-privileges:true
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
frontend:
backend:
internal: true
这个模板体现了几个关键思路:
- 只有 Nginx 暴露公网端口;
- 应用和数据库在内部网络通信;
- 配置文件尽量只读挂载;
- 数据库不暴露公网;
- 日志大小有限制;
- 使用
no-new-privileges降低提权风险; - 按服务拆分网络,减少横向移动风险。
实际使用时需要根据应用特性调整,不建议直接复制到生产环境。
十二、站长 Docker 安全检查清单
最后给出一份实用检查清单,适合上线前或定期巡检使用。
镜像与版本
- 是否使用官方或可信镜像;
- 是否避免使用
latest; - 是否定期更新镜像;
- 是否删除不用的旧镜像。
权限控制
- 是否避免使用
--privileged; - 是否避免挂载
/var/run/docker.sock; - 是否尽量使用非 root 用户;
- 是否配置
no-new-privileges; - 是否减少不必要的 capabilities。
网络暴露
- 数据库是否未暴露公网;
- Redis 是否未暴露公网;
- 管理面板是否限制访问;
- 是否只开放
80、443、必要 SSH 端口; - 是否使用内部 Docker 网络隔离服务。
数据与配置
- 配置文件是否只读挂载;
.env文件权限是否足够严格;- 密码是否足够复杂;
- 备份是否加密或妥善保存;
- 上传目录是否禁止执行脚本。
日志与监控
- 是否限制容器日志大小;
- 是否定期查看异常日志;
- 是否监控磁盘空间;
- 是否有 CPU、内存异常告警;
- 是否能快速定位异常容器。
备份与恢复
- 是否定期备份数据库;
- 是否备份 Docker Compose 文件;
- 是否有异地备份;
- 是否测试过恢复流程;
- 是否保留多个历史版本。
结语
Docker 能显著提升站长部署和维护网站的效率,但效率不能以安全为代价。很多 Docker 安全问题并不是因为技术复杂,而是因为配置过于随意:镜像随便用、端口随便开、权限随便给、日志不限制、备份不验证。攻击者最喜欢的正是这些“图省事”的配置。
对于个人站长和中小网站来说,最值得优先落实的措施是:使用可信镜像、固定版本、不要暴露数据库、关闭不必要端口、避免特权容器、限制日志大小、做好备份恢复。这些措施成本不高,却能显著降低被扫描、爆破、入侵和勒索的风险。
安全不是一次性工作,而是一套持续维护习惯。只要坚持最小权限、最少暴露、定期更新、定期备份,Docker 就可以成为站长稳定运营网站的可靠工具,而不是潜在的安全隐患。