前端必会:Docker容器化部署实战指南
2026/9/19 3:50:49 网站建设 项目流程

1. 先别急着敲命令:前端为什么需要 Docker

作为一个每天都跟浏览器、Node、npm 打交道的前端,我第一次接触 Docker 的真实感受是:这东西好像是后端运维的事,跟我有什么关系?直到后来公司让我负责把前端项目部署到测试服务器,我才发现,如果不搞清楚 Docker,前端上线的路会走得特别憋屈——要么在一台刚装好的服务器上手动装 Nginx、配 Node、传文件、改配置,整套流程重复三五遍,要么就只能在本地跑通,换台机器就各种踩坑。

这篇文章的定位很明确:用前端能理解的思路,把 Docker 从零讲清楚,并且带你完整走一遍“本地容器化构建 → 镜像打包 → 服务器部署 → 线上访问”的闭环。你不需要是运维专家,只要会基本的命令行操作,跟着做就能把项目真正跑在服务器上。

我默认你的项目是前端常见的形态:用 Vite / Webpack 构建的静态站点,或者带 Node 后端接口的全栈应用,再或者搭配 MySQL 这类中间件。我会把这些场景全部串进实操里。读完你会明白,Docker 解决的不是“怎么跑一个命令”,而是“怎么让一个项目在任何机器上都能用一模一样的方式跑起来”这件事。

2. 本地环境搭建:Docker Desktop 安装与高频踩坑

2.1 安装前先确认两件事:虚拟化和 WSL2

前端开发者的主力机大多是 Windows 或 macOS。macOS 装 Docker Desktop 相对省心,Windows 上容易出幺蛾子,很多报错都出在“装之前没检查环境”。

Windows 上安装 Docker Desktop 有两个底层依赖需要提前确认。

第一,CPU 虚拟化必须在 BIOS 里开启。任务管理器 → 性能 → CPU,右下角能看到“虚拟化: 已启用”。如果是“已禁用”,需要重启进 BIOS 找 Intel Virtualization Technology 或 AMD SVM Mode 打开。

第二,Docker Desktop 在 Windows 上需要 WSL2 作为后端支撑。以管理员身份打开 PowerShell,执行:

wsl --status

如果提示没有安装,先执行:

wsl --install

装完后重启。这一步完成了再装 Docker Desktop,启动失败的概率会低很多。顺带说明一个容易被忽略的点:WSL2 和虚拟机平台是两套机制,Docker Desktop 会自己管理底层虚拟机,你不需要手动装 Hyper-V,除非你的机器是 Windows 专业版而且公司强制要求用 Hyper-V 隔离。

macOS 用户相对省事,但如果你用的是 Intel 芯片的老款 Mac,装 Docker Desktop 后发热和内存占用会比较明显,后面我会说怎么限制资源。

2.2 Docker Desktop 安装与启动检查

Docker Desktop 的安装包直接去官网下载就行,Windows 用户下载 exe,macOS 用户下载 dmg。安装过程中保持默认选项即可,但有一个勾选框值得留意:Windows 上会询问是否使用 WSL2 而不是 Hyper-V,建议保持勾选 WSL2,这样和终端环境的集成更自然,性能损耗也更小。

安装完后不用急着打开界面,先确认命令行工具是否可用:

docker version

正常情况会输出 Client 和 Server 两段信息。注意一个关键细节:如果你只看到 Client 段,看不到 Server 段,说明 Docker 引擎没起来。这时候去打开 Docker Desktop 图标,等它状态变成绿色的 Running 再执行一次。

还有一个前端同学经常搞混的概念:docker 命令是客户端,真正干活的是 Docker 引擎,也就是 Docker Desktop 里那个跑在 WSL2 里的虚拟机。你执行 docker ps 时,客户端通过管道和引擎通信。所以遇到“无法连接”类报错,第一反应不是重装命令,而是去检查引擎状态。

2.3 高频启动错误排查:从 virtualization support 到 npipe

我把搜索热度最高的几个报错信息整理出来,每个都是我实际遇到过或者被身边同事问过的:

报错信息原因解决办法
virtualisation support wasn't detectedBIOS 虚拟化未开启或未生效进 BIOS 开启 VT-x/AMD-V,重启后确认任务管理器中“虚拟化”为已启用
failed to connect to the docker api at npipe:////./pipe/dockerDesktopLinuxEngineDocker 引擎没启动或处于启动中状态打开 Docker Desktop 等待引擎 Running;如果一直失败,退出重开,或检查 WSL2 状态
docker: permission denied while trying to connect当前用户不在 docker 用户组执行 sudo usermod -aG docker $USER,然后重新登录终端
Docker Desktop failed to start because virtualisation support...同上虚拟化问题,也可能是旧版 Docker 残留配置冲突先开虚拟化,再卸载重装 Docker Desktop,删除 %AppData%\Docker 配置目录

第二种情况在 Windows 上出现频率最高。我自己排查过一台电脑,WSL 版本是 1,docker 一直连不上,把 WSL 升级到 2 之后问题直接消失。升级命令:

wsl --set-version Ubuntu-22.04 2

如果提示没有安装发行版,默认的 docker-desktop 发行版会自动创建,不用手动管。

2.4 配置镜像加速与资源限制

Docker Desktop 装好后,有两处配置建议前端同学提前设置。

镜像加速。国内网络环境下,直接拉取 Docker Hub 镜像经常卡到怀疑人生。打开 Docker Desktop → Settings → Docker Engine,在 JSON 配置里加上 registry-mirrors:

{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerproxy.com" ] }

写完点击 Apply & Restart。注意镜像加速只影响 docker pull 的速度,不影响容器内部网络,这个后面部署时还会再提。

资源限制。Settings → Resources 里可以设置 CPU、内存和 Swap。前端项目构建时 Node 比较吃内存,建议至少给 Docker 分配 4GB 内存,否则构建大项目时可能直接 OOM。如果你用的是 16GB 内存的 Mac,给 6GB 是合理值,留够宿主机的余量。

3. 前端第一课:用 Docker 跑起来一个 Nginx 静态站点

3.1 镜像、容器、仓库:三个最容易混淆的概念

很多教程上来就列命令,但前端同学最容易卡在概念上。我用一个类比帮助理解。

镜像(Image)就像一个安装包,它包含了运行某个应用需要的所有东西:操作系统基础层、软件、配置、环境变量。容器(Container)是镜像运行起来后的实例,你可以同时用同一个镜像启动多个容器,就像用同一个安装包装了多台机器一样。

仓库(Registry)是存放镜像的地方,最知名的是 Docker Hub。docker pull 就是从仓库下载镜像到本地,docker push 就是把本地镜像上传到仓库。

这三个概念对应到前端的工作流里:镜像就是你的"构建产物"加运行环境的封装,容器就是这个产物在某个端口上的实际运行实例,仓库就是你的"版本发布平台"。

3.2 最简命令:让 Nginx 容器转起来

我们在本地先跑一个最简 Nginx,用这个例子理解容器命令。

docker run -d --name my-nginx -p 8080:80 nginx:latest

拆解一下这条命令:

  • docker run:创建并启动容器。
  • -d:后台运行,不占用当前终端。
  • --name my-nginx:给容器起名字,方便后续管理。
  • -p 8080:80:把宿主机的 8080 端口映射到容器内的 80 端口。
  • nginx:latest:镜像名和标签。

执行完浏览器访问 http://localhost:8080,能看到 Nginx 默认欢迎页。

这时候你要理解端口映射的意义。容器内部是一个独立的网络空间,Nginx 监听的是容器里的 80 端口,宿主机访问不到。必须通过 -p 把宿主机的端口映射进去,才能真正访问到服务。8080 是宿主机的入口,80 是容器内部的端口,这个映射关系在部署到服务器时同样关键。

再看几个最常用的容器管理命令:

docker ps # 列出运行中的容器 docker ps -a # 列出所有容器,包括已停止的 docker stop my-nginx # 停止容器 docker start my-nginx # 启动已停止的容器 docker rm my-nginx # 删除容器 docker logs my-nginx # 查看容器日志

注意 docker rm 删除的是容器,不是镜像。想删除镜像要 docker rmi。如果你停止容器后重新 docker start,之前的端口映射和配置都还在,但如果你 docker rm 后再 docker run,就得重新带全所有参数。这个细节在写自动化部署脚本时容易踩坑。

3.3 把前端项目放进去:数据卷与文件复制

跑起来默认页不算本事,把我们的前端构建产物放进去才算事。做法有两种。

第一种,直接用 docker cp 把本地的 dist 目录复制进容器:

docker cp ./dist my-nginx:/usr/share/nginx/html

这个命令适合临时验证,但不推荐作为正式方案,因为容器一旦被删除,里面的文件就没了。容器是临时性的,任何在容器内部产生的修改都不应该被视为持久数据。

第二种是数据卷(Volume)挂载,用 -v 参数把宿主机目录映射进容器:

docker run -d --name my-nginx -p 8080:80 -v /path/to/dist:/usr/share/nginx/html:ro nginx:latest

这样宿主机的 dist 目录直接出现在容器的 nginx html 目录下,本地构建完刷新就能看到效果,开发调试非常方便。我只在本地调试时用这种方式,正式部署我不用它,原因后面部署篇会详细说。

3.4 进入容器内部排查问题

前端调试时最常用到的两个命令是 docker logs 和 docker exec。

docker logs 查看的是容器内进程的输出。Nginx 的访问日志和错误日志都会输出到终端上,如果页面 502、504,多半能从日志里发现端倪。

docker exec 用于进入运行中的容器执行命令:

docker exec -it my-nginx bash

进去之后你可以看文件、改配置、测试网络,相当于远程登录到这台"微型服务器"里。用 Ctrl+D 退出。

这里补充一个我自己常用的排查套路:页面访问异常时,先 docker logs 看 Nginx 日志,再 docker exec 进容器看 /etc/nginx/conf.d 下的配置,最后用 curl 测试容器内部能否访问后端服务。一层层排查,比在宿主机上瞎猜高效得多。

4. 前端项目容器化:Dockerfile 多阶段构建实战

4.1 多阶段构建:一个 Dockerfile 里装下构建与运行

前端项目容器化的核心不是把 Node 装进容器然后跑 npm run dev,而是用多阶段构建把"编译"和"运行"拆开,最终镜像只保留 Nginx 和静态文件,不含 Node 和源码。

一个标准 Vue/React 项目的 Dockerfile 长这样:

# 第一阶段:构建 FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # 第二阶段:运行 FROM nginx:stable-alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]

这个写法最大的好处是镜像体积小。第一阶段用的 node:20-alpine 可能有两三百兆,但第二阶段只拷贝了编译产物进去,最终镜像可能只有几十兆。部署时拉取更快,服务器磁盘占用也更少。

npm ci 和 npm install 的区别补充一句:npm ci 严格按照 package-lock.json 安装,速度更快,也不会因为版本漂移产生和本地不一致的问题。CI 环境里必须用它。

4.2 .dockerignore:别把 node_modules 一起烤进去

前端项目里最容易犯的错误是忘了写 .dockerignore。如果你没写,那么执行 docker build 时,会把当前目录所有文件都发送给 Docker 构建上下文,包括 node_modules、dist、.git。这不仅会导致构建极慢,还可能因为把本地的二进制依赖带进去而构建失败。

一个精简的 .dockerignore 长这样:

node_modules dist .git *.log .DS_Store .vscode .idea

记住一个原则:构建阶段需要什么就 COPY 什么,不需要的必须挡在上下文外。node_modules 尤其重要,因为整个构建的核心目的就是在容器内重新安装依赖,而不是复用本地的。

4.3 前端路由刷新 404:Nginx 配置必须在镜像里

前端项目用 history 路由模式时,比如 Vue Router 的 createWebHistory 或 React Router 的 BrowserRouter,直接部署 Nginx 会出现一个经典问题:首页能打开,但刷新 /about 页面时 404。

原因很简单:Nginx 接收到 /about 请求后,去 html 目录下找 about 文件,找不到,就返回了 404。而前端路由实际是通过 JS 控制的,所有路径都应该回到 index.html,由前端路由自己判断。

所以 nginx.conf 需要配置 try_files:

server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://backend:3000; } }

location /api/ 里的 proxy_pass 解决了前后端联调的问题:前端请求 /api 开头的接口时,Nginx 把请求转发给容器里运行的后端服务。这个配置在本地开发时用不到,但上服务器跑全栈项目时几乎必用。

4.4 构建镜像与 Compose 编排:把前端后端数据库串起来

写好了 Dockerfile,执行构建:

docker build -t my-app:latest .

-t 指定镜像名和标签。构建过程会分步执行 Dockerfile 里的指令,每一步都会生成一个缓存层。改一次代码后重新构建,只有变化的部分会重新执行,所以构建速度会很快。

如果项目依赖的前端构建耗时较长,比如几十秒甚至几分钟,构建镜像时会感觉卡在那。这属于正常现象,不用慌。

实际线上项目通常不止前端一个服务。假设还有一个 Node 后端服务和 MySQL 数据库,手动用 docker run 逐个启动再配网络会非常痛苦。此时用 Docker Compose。

在项目根目录创建 docker-compose.yml:

version: "3.8" services: frontend: build: ./frontend ports: - "80:80" depends_on: - backend backend: build: ./backend environment: - DB_HOST=mysql - DB_PORT=3306 - DB_NAME=my_app - DB_USER=root - DB_PASSWORD=change_me ports: - "3000:3000" depends_on: mysql: condition: service_healthy mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=change_me - MYSQL_DATABASE=my_app volumes: - mysql-data:/var/lib/mysql ports: - "3306:3306" healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s timeout: 3s retries: 10 volumes: mysql-data:

一个关键知识点:Compose 里的服务名(frontend、backend、mysql)就是容器之间互访的域名。后端连接数据库时,host 填 mysql,而不是 localhost,因为数据库跑在另一个容器里。同理,Nginx 配置里 proxy_pass http://backend:3000,也是走 Compose 服务名。

MySQL 数据持久化通过 volume 实现。没有这一行,容器删除后数据库数据就没了。有这一行,数据会保存在 Docker 管理的卷里,哪怕容器重建,数据还在。

启动命令:

docker compose up -d --build

第一次执行会拉取基础镜像并构建所有服务,之后再次执行,如果镜像没变化,直接就启动容器,秒级完成。

5. 从本地到服务器:部署闭环实战

5.1 部署方案选型:宝塔还是纯命令行

本地搞定的下一步是上服务器。前端同学第一次部署时最容易纠结的是:到底用宝塔面板还是手动敲命令?我的看法是,如果目的是搞懂 Docker 本身,必须走一遍纯命令行的流程。宝塔是一个优秀的图形化管理工具,但它的便捷性会掩盖 Docker 的工作原理。

我推荐的最小部署路径是:

  1. 买一台 Linux 服务器,系统选 Ubuntu Server 22.04 LTS,内存 2GB 起步。
  2. 用 SSH 登录服务器。
  3. 安装 Docker Engine。
  4. 把本地构建好的镜像传到服务器。
  5. 用 docker compose 启动正式服务。

这条路径跑通后,你以后再接触任何自称"一键部署"的工具,都能立刻判断它背地里干了什么。

5.2 服务器安装 Docker Engine

Ubuntu 服务器上安装 Docker Engine 的标准流程:

sudo apt update sudo apt install -y apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

装完后验证:

sudo docker run hello-world

这条命令会拉取一个测试镜像并在容器里输出一段欢迎信息,说明引擎工作正常。

有个细节说一下:默认情况下,docker 命令需要 root 权限,每次敲 docker 都要加 sudo。为了方便,可以把自己加入 docker 用户组:

sudo usermod -aG docker $USER

执行完退出 SSH 重新登录生效。这个操作等同于给当前用户开放了管理 Docker 的权限,有安全风险,但在个人服务器和团队内网环境里足够常见,前提是你清楚后果。

5.3 镜像传输:本地构建好还是服务器构建?

把镜像弄到服务器上有几种方案,我按推荐程度排序:

方案一,本地构建镜像,导出 tar 包,上传服务器再导入。

# 本地 docker save my-app:latest | gzip > my-app.tar.gz scp my-app.tar.gz user@服务器IP:/opt/my-app/ # 服务器 cd /opt/my-app docker load < my-app.tar.gz

这个方案的好处是服务器上不需要 Node 环境,也不用拉 npm 依赖,拉到的镜像体积小,传输快。坏处是要是服务器是 ARM 架构的,比如某些云服务器是 ARM 芯片,本地构建的 x86 镜像就跑不了。所以构建前先确认服务器架构,用 uname -m 查看。

方案二,把源码 git clone 到服务器,在服务器上 docker compose build。这个适合服务器性能不错,而且你希望整个构建流程在服务器端闭环的场景。缺点是要在服务器上装 Dockerfile 里用到的基础镜像和依赖,第一次构建会比较慢。

方案三,推送到镜像仓库,服务器从仓库拉取。如果是个人项目或者公司有私有仓库,这是最正规的姿势。公共 Docker Hub 上可以建免费私有仓库,但因为网络原因,在国内服务器上拉取 Docker Hub 镜像速度不稳定,建议配置镜像加速。

综合来看,前端个人项目最省心的还是方案一。我实际部署时经常是把镜像导出后 scp 上传,简单直接,不受服务器网络影响。

5.4 服务器上的 docker-compose.yml 与生产配置

在服务器上创建部署目录,比如 /opt/my-app,把 docker-compose.yml 传上去。生产环境下的 Compose 文件和本地调试版有几点不同:

  • 镜像直接指定已导入的镜像名,而不是用 build:设置。
  • 环境变量、数据库密码等敏感信息,用 .env 文件管理,不要把密码硬编码在 compose 文件里。
  • 前端 Nginx 容器映射 80 端口,对外直接提供服务。
  • 后端服务可以不映射到宿主机端口,只让 Nginx 内部访问,减少暴露面。

一个生产环境的 compose 示例:

version: "3.8" services: frontend: image: my-app-frontend:latest ports: - "80:80" restart: always depends_on: - backend backend: image: my-app-backend:latest restart: always environment: - DB_HOST=mysql - DB_PASSWORD=${DB_PASSWORD} volumes: - uploads:/app/uploads mysql: image: mysql:8.0 restart: always environment: - MYSQL_ROOT_PASSWORD=${DB_PASSWORD} - MYSQL_DATABASE=my_app volumes: - mysql-data:/var/lib/mysql volumes: mysql-data: uploads:

.env 文件:

DB_PASSWORD=your_strong_password

启动:

docker compose up -d

-restart: always 的作用是:服务器重启或容器异常退出时,Docker 会自动拉起容器。这个参数在本地开发时不重要,但线上必须加,否则服务器一重启服务就全挂了。

5.5 上线后的日常管理:更新、日志与备份

部署完只是开始。前端项目迭代快,改一次代码就得更新一次发布。

更新流程我总结成固定套路:

# 1. 本地构建新镜像并导出 docker build -t my-app-frontend:latest . docker save my-app-frontend:latest | gzip > my-app-frontend.tar.gz # 2. 上传服务器 scp my-app-frontend.tar.gz user@服务器IP:/opt/my-app/ # 3. 服务器上加载新镜像并重启容器 cd /opt/my-app docker load < my-app-frontend.tar.gz docker compose up -d

docker compose up -d 检测到镜像发生了变化,会用新镜像重建容器,期间服务会有短暂中断。对于个人项目和多数企业内部系统,这个中断时间完全可接受。如果追求零停机,需要引入负载均衡和多实例滚动更新,那是另一个话题。

日志管理用 Docker 自带的 json-file 日志驱动就够了。默认情况下,容器日志会一直累加,时间长了占满磁盘。稳妥做法是在 compose 文件里限制日志大小:

services: frontend: image: my-app-frontend:latest ports: - "80:80" logging: driver: json-file options: max-size: "10m" max-file: "3"

数据库备份最实用的方式是定时用 mysqldump 导出 SQL 文件,再定期把备份文件下载到本地。容器里执行:

docker exec mysql mysqldump -u root -p"$DB_PASSWORD" my_app > backup_$(date +%F).sql

配合 crontab 定时执行,能做到每天自动备份。个人服务器环境里把这个跑通了,数据安全性就有基本保障。

6. 前端部署高频问题与排查技巧实录

6.1 端口被占用导致容器启动失败

启动 Nginx 容器时报错 "port is already allocated",说明宿主机上已经有进程占用了 80 或 8080 端口。排查命令:

sudo lsof -i :80 sudo netstat -tulpn | grep :80

找出占用进程后,要么停掉它,要么把 Docker 端口映射改成其他端口。在云服务器上还有一个容易忽略的点:云平台的安全组规则必须放行对应端口,否则即使容器启动正常、端口映射正确,外部依然无法访问。前端同学第一次部署最容易卡在这一步,先在服务器本地 curl localhost:80 测试,能通说明服务正常,再检查安全组。

6.2 容器能启动但页面 502 Bad Gateway

出现 502,说明 Nginx 已经成功接收请求,但转发给后端时失败了。按顺序排查:

  1. 后端容器是否正常运行:docker ps 看状态。
  2. 后端服务端口是否正确:docker logs backend 看启动日志。
  3. Nginx 配置里的 proxy_pass 地址是否正确:Compose 环境里服务名是否拼对,宿主机部署则要用宿主机 IP。
  4. 前后端容器是否在同一个 Docker 网络里:不在同一个网络时,服务名解析不了,就访问不到。

解决这个问题时,我习惯先在 Compose 网络里测试服务互通。进入前端容器执行:

docker exec -it frontend bash curl http://backend:3000/health

能返回数据,说明容器间网络没问题,继续排查 Nginx 配置和路径。

6.3 前端刷新 404,部署后只能在根路径访问

前面提过,history 路由必须配合 try_files。这里补充一个更隐蔽的情况:Nginx 生效的是 /etc/nginx/conf.d/ 下的配置文件,而你用 docker cp 或卷挂载替换了它,但没有重启容器或重新加载配置。

修改 Nginx 配置后执行:

docker exec frontend nginx -s reload

让 Nginx 重新加载配置,不用重启整个容器。如果修改是通过重新构建镜像完成的,那 docker compose up -d 会重建容器,不需要额外操作。

6.4 MySQL 容器数据丢失或时区不对

MySQL 容器重建后数据没了,先看 docker-compose.yml 里有没有挂载 volume。没挂载的话,数据都在容器可写层,容器删除就清零。这是用容器跑数据库最容易踩的坑,没有之一。

时区不对是另一个高频问题。MySQL 8.0 默认使用 UTC 时间,而前端展示通常需要北京时间。启动容器时加参数:

environment: - TZ=Asia/Shanghai command: --default-time-zone=+08:00

前端代码里对时间字段的处理也要统一,建议后端所有时间存 UTC 时间戳,前端展示时用 dayjs 或 date-fns 转本地时区,彻底避开时区混乱。

6.5 构建镜像时 npm install 特别慢

构建阶段执行 npm install 时,如果长时间卡住,大概率是 npm 镜像源的问题。在 Dockerfile 里切换源:

RUN npm config set registry https://registry.npmmirror.com && npm ci

如果你用 pnpm,对应设置 registry 的方式也类似。另一个办法是把 npm install 放在单独的一层,利用 Docker 层缓存。只要 package.json 和 lock 文件不变,这层缓存就不会失效,后面迭代构建时会快很多。

6.6 容器时间与宿主机不一致

容器默认使用 UTC 时区,日志时间比北京时间晚 8 小时。排查问题时经常对不上。解决方案是在 Compose 环境变量里统一设置 TZ=Asia/Shanghai,并让容器共享宿主机的时区文件。如果你已经写了定时任务,比如数据库备份,时间错乱会导致备份时间不符合预期。这个问题不算严重,但遇到了很恶心,提前配好能省很多事。

写在最后的一些体会

踩过这么多坑之后,我的体会是:Docker 对于前端的价值,不在于让你成为运维专家,而在于把"部署"从一门玄学变成一种可复制的工程能力。以前你交付项目是扔一个压缩包加一篇部署文档,现在你交付的是一个镜像加一条 docker compose up,跑在哪台机器上行为都一样。

最后分享两个我自己使用中沉淀下来的小习惯。

第一,本地开发时尽量用 docker compose 把整套环境拉起来,不要只容器化前端,而让后端和数据库裸跑在宿主机上。前后端容器在同一个网络里通信,才最能模拟生产环境。

第二,给镜像打标签时养成带版本号的习惯,比如 my-app:20250615,不要总是覆盖 latest。这样线上出了问题,可以快速回滚到上一个版本。我有一次就是升级前没保留旧版本镜像,结果新版本有问题,只能重新构建旧代码,白白多花了一个小时。版本号这个习惯,关键时候能救命。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询