Docker 部署从 Windows 到 Linux 的完整配置流程与常见坑
第一次在 Windows 上装 Docker 的人,十有八九会卡在 WSL2 那一步——装完 Docker Desktop 重启,打开终端敲 docker ps,报错说找不到 daemon。这不是 Docker 本身的问题,而是 Windows 上跑容器本质上得先有一层 Linux 内核。另一批人则相反,本地开发一切正常,把镜像推到服务器上跑不起来,多半是 Linux 那边的用户组权限或者镜像加速没配。这两种情况我都遇到过很多次,问题都不大,但顺序错了就要来回折腾。下面把 Windows 和 Linux 两条线的安装、配置、验证串起来讲,重点放在容易忽略的几处配置上,而不是照抄官方文档的安装命令。
Windows 端:先确认 WSL2 和虚拟化,再谈装 Docker
Windows 上装 Docker 的前提条件比 Linux 多一层。BIOS 里的虚拟化(VT-x 或 AMD-V)没开,Docker Desktop 装完也起不来,这个错误提示往往很含糊。装之前先在任务管理器看 CPU 那一栏有没有「虚拟化:已启用」。
WSL2 是必须的。PowerShell 里执行 wsl --install,装完重启,再用 wsl --set-default-version 2 把默认版本设成 2。WSL1 和 WSL2 的差别在文件系统调用上,Docker 依赖的 cgroup 和 namespace 只有 WSL2 才完整支持。
内存分配是 Windows 端最容易踩的坑。默认情况下 WSL2 最多吃掉主机一半的内存,如果你机器是 16GB,跑两三个 Node 容器再加上 IDE,很快就卡了。我一般会在用户目录下建一个 .wslconfig,把内存上限压到 8GB,留出余量给 Windows 本身。
- Docker Desktop 安装包约 500MB 左右,装完第一次启动会自动拉取 WSL2 内核更新
- 如果公司网络走代理,要在 Docker Desktop 的 Settings → Resources → Proxies 里单独填,系统代理它读不到
- 镜像加速地址填在 Settings → Docker Engine 的 JSON 里,改完点 Apply & Restart 才生效
Windows 这套方案适合本地开发调试,不适合当生产环境。Docker Desktop 本身带商业授权限制,公司规模超过一定人数就要付费。真要跑长期服务,还是得挪到 Linux 服务器上。
Linux 端:内核版本、用户组和镜像加速三件事
Linux 这边反而简单。内核 3.10 以上就能跑 Docker,CentOS 7 和 Ubuntu 18.04 之后的版本基本都满足。用官方脚本 curl -fsSL https://get.docker.com | sh 装完,先别急着 pull 镜像。
第一件事是把当前用户加进 docker 组,否则每条命令都得加 sudo。执行 sudo usermod -aG docker $USER 之后要重新登录才生效,很多人忘了这步,以为装失败了。
第二件事是配镜像加速。国内直接拉 Docker Hub 的镜像经常超时,编辑 /etc/docker/daemon.json,加上 registry-mirrors 字段,然后 sudo systemctl restart docker。这个文件如果写错一个逗号,Docker 服务直接起不来,报错信息还不明显,所以改完先用 docker info 验证一下。
第三件事是数据目录。默认所有镜像和容器都堆在 /var/lib/docker,系统盘小的话很快就满。生产环境我一般会在挂载数据盘后,把 data-root 指过去,避免哪天磁盘写满导致容器全挂。
如果你打算长期跑容器,机器选型上别太省。一台 8 核 10G 内存的香港 VPS,比如香港VPS独享30M国际线路,月付 $15.13,跑十个以内的轻量容器(Nginx、Redis、几个后端服务)完全够用,30M 带宽对内网调用和外部访问都还凑合。再往上堆服务,就得考虑物理服务器了。
容器网络和端口映射:为什么本地能通、外面访问不到
这一节是最容易出问题的地方,也是我觉得最值得花时间搞明白的一步。
Docker 默认创建 bridge 网络,容器之间通过内部 IP 互通,但外部访问必须靠 -p 做端口映射。常见错误是写了 -p 8080:80 却访问不了,原因通常是防火墙没放行 8080,而不是 Docker 的问题。Linux 上先用 firewall-cmd --list-ports 或 ufw status 确认。
另一个高频坑是容器里服务监听的地址。如果程序绑的是 127.0.0.1,那么即使端口映射对了,从宿主机外面也进不来,必须让它监听 0.0.0.0。这个问题在 Node 和 Python 应用里特别常见,本地开发时不会暴露,一上服务器就现形。
如果你用的是云服务器,还要注意安全组。宿主机防火墙开了,安全组没开,一样访问不了。我一般排查顺序是:容器内 curl localhost:端口 → 宿主机 curl 127.0.0.1:映射端口 → 外部访问。哪一步断了,问题就在哪一层。
需要多个容器互相通信又不想暴露端口时,用自定义 bridge 网络比默认的方便,容器名直接当主机名用。命令是 docker network create mynet,启动时加 --network mynet。
如果服务需要对外提供稳定带宽,尤其是做站群或者需要抗攻击的场景,容器本身帮不上忙,得从机器层面解决。像香港大带宽服务器 XXVII这种 Platinum-8168*2 / 64G / 100M 的配置,月付 $913.50,适合把多个容器化服务集中到一台机器上,省去跨机调用的延迟。
数据持久化和权限:容器删了数据不能丢
容器本身是无状态的,写进容器里的数据随着 docker rm 一起消失。数据库、上传文件、日志这三类必须挂出来。
Volume 和 bind mount 的区别值得说清楚。Volume 由 Docker 管理,存在 /var/lib/docker/volumes 下,适合数据库;bind mount 直接映射宿主机目录,适合配置文件和代码,改完不用重建镜像。
权限问题在 Linux 上最常见。容器里默认以 root 跑,挂载出来的文件属主变成 root,宿主机上的普通用户改不了。解决办法是在 docker run 时加 --user $(id -u):$(id -g),或者提前把目录权限设好。这个坑我踩过不止一次,尤其是跑 Jenkins 这类需要写文件的容器。
备份方面,数据库容器别只依赖 volume,定期 docker exec 进去导出一份 SQL 到宿主机才是稳妥做法。Volume 本身不是备份方案,磁盘坏了照样丢。
最后给一个可以直接执行的结论:本地开发用 Windows + Docker Desktop,内存上限压到 8GB,镜像加速配好;生产环境一律上 Linux,装完先加 docker 组、再配 daemon.json、然后把 data-root 挪到数据盘。轻量服务用 8H10G 的香港 VPS 月付 $15 起步就够,服务数量和带宽需求上来了再换物理服务器,别在 VPS 上硬扛高并发。