ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

从Docker部署到线上稳定运行:完整实践与避坑指南

从Docker部署到线上稳定运行:完整实践与避坑指南 又是这个环节——代码写完了本地跑通了测试环境一切正常接下来就是把服务扔到云服务器上让它在公网活起来。这一步听着简单实际做起来坑不少。域名解析、防火墙、环境依赖、数据库迁移、日志保留哪一个环节没理顺半夜就能收到告警电话。我最近一次上线项目也是用 Docker 完成的借着这次实操把整个部署流程和踩过的坑整理出来分享给同样在忙部署的朋友。这篇总结适合正在做中小型项目上线的开发者尤其是从“本地能跑”到“服务器上稳定运行”这个跨越阶段的人内容覆盖镜像构建、编排方案、数据迁移、线上排查等完整链路照着走能少走不少弯路。先说一个很关键的整体判断Docker 部署这事难点从来不是“把容器跑起来”而是“跑起来之后怎么让它稳定、可维护、可回滚”。很多人第一次用 Docker 部署项目时都会有一种错觉——本地 docker-compose up 一切正常服务器上复制一遍应该也行。真到服务器上你会发现镜像构建缓慢、内存不足、数据库数据卷权限、容器日志不持久化、时区不一致、自启动策略失效这些全是隐藏的地雷。这篇文章我想按实际的部署顺序来讲从方案选型开始到镜像构建、Compose 编排、数据持久化、反向代理、线上排查最后分享一些实践教训尽量把每一个关键节点背后的“为什么”说清楚。1. 部署之前先把方案选型想清楚1.1 单容器还是编排先分清项目形态很多新手一开始就容易陷入纠结到底用docker run一条命令跑起来还是老老实实写一套docker-compose.yml我的建议很简单只要项目依赖了两个以上服务比如前端 后端 MySQL就直接上 Compose别犹豫。docker run适合临时验证镜像、单容器调试这种一次性场景它的问题是每次启动都要带上一长串参数端口映射、环境变量、数据卷、网络模式写完自己都不想看第二遍。而且一旦涉及多个容器之间的通信用docker run一个个启动再手动建网络整个操作流程的脆弱性会成倍增加。举一个我实际经历过的例子某次上线模拟项目 X组件包括前端 Nginx 容器、后端 API 容器和一个 MySQL 容器。如果用docker run分别启动得先docker network create创建自定义网络、再依次启动数据库、后端、前端三个容器之间通过容器名互相访问。这一套操作做完没问题但下次重新部署、服务器重启后恢复、换一台机器迁移全得重来。而 Compose 文件把这些全部声明出来docker-compose up -d一条命令完成从网络创建到容器启动的全部过程可复制性、可审查性都强得多。1.2 服务器环境提前确认这四件事方案确定之后还得先检查服务器本身。我见过太多人在服务器上装完 Docker 就开始部署结果后面资料堆积、排错半天最后发现是最基础的环境问题。上服务器之前至少确认四件事系统版本和内核Docker 对内核版本有要求uname -r看一下如果内核过老有些新版镜像可能起不来。Ubuntu 20.04 以上、Debian 11 以上这类版本基本都没问题。磁盘剩余空间镜像加数据很容易把磁盘塞满df -h确认一下建议至少预留 20G 以上否则镜像构建到一半直接报 no space left。内存大小free -h看下实际内存如果只有 1G - 2G构建 Java、前端这类重镜像时很容易触发 OOM。防火墙状态很多云服务商的安全组和系统防火墙是两套体系需要两边都确认放行端口。这里有个很容易踩的坑云服务商的安全组是卡在虚拟机外层的系统自带的ufw或firewalld是虚拟机内部的。你可能把安全组的端口放开了结果忘了系统防火墙没放行服务从外部访问不了排查半天还以为是容器出问题了。遇到“端口明明映射了但访问不通”的情况先按这个顺序排查安全组 → 系统防火墙 → 容器端口映射 → 应用监听地址。1.3 手动部署和 Docker 部署的取舍很多团队已经习惯了手动部署本地打包、scp 上传、连上服务器找进程 kill 掉、替换文件、重启服务。这套流程在项目只有一个节点、更新频率低的时候勉强可用。但一旦服务要扩容、要迁移服务器、要快速回滚版本手动部署的劣势就非常明显服务器上散落着各种半新半旧的依赖、手动改过的配置文件换一台机器根本复现不出来。Docker 把应用和它的运行环境整个打包进镜像依赖项、启动命令、工作目录、端口声明全都固化在镜像和 Compose 文件里只要这两样东西在任何一台装了 Docker 的服务器都能还原出一模一样的运行状态。我在一次迁移经历里体会特别深要把整套服务从旧服务器迁到新服务器用 Docker 的话打包备份数据库数据卷、上传镜像或者直接拉取镜像、复制 Compose 文件和.env半小时内就能完成切换。如果纯手工部署各种软件的安装版本、路径、配置差异足以让人加班到天亮。2. 镜像构建阶段的细节与优化2.1 多阶段构建把镜像体积打下来既然要用 Docker 部署第一关就是写镜像构建文件。如果你的项目是编译型语言Go、Java、前端 Node 构建产物建议直接上多阶段构建multi-stage build。它的核心思想是构建阶段用完整的编译环境比如带 Node 或 JDK 的基础镜像最终运行阶段只拷贝编译好的产物到轻量镜像里这样做出来的镜像体积往往能缩小一半以上而且运行时没有多余工具链也降低了被攻击的风险。以前端项目为例Dockerfile 可以这样写# 阶段一构建 FROM node:18-alpine AS builder WORKDIR /app COPY package.json ./ RUN npm install COPY . . RUN npm run build # 阶段二运行 FROM nginx:1.25-alpine COPY --frombuilder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80这样构建出来的镜像只包含 Nginx 和静态文件体积可能只有几十兆。如果在第一阶段直接用 node 镜像去跑生产光 node_modules 就有几百兆更别提基础镜像本身的体积差距。后端的思路类似以 Spring Boot 项目为例# 阶段一构建 FROM maven:3.8-openjdk-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # 阶段二运行 FROM openjdk:17-jre-slim COPY --frombuilder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app.jar]注意这里我把依赖下载和源码拷贝分成了两步COPY pom.xml . RUN mvn dependency:go-offline是为了充分利用 Docker 构建缓存。如果不分开每次改一行代码都会触发完整的依赖重下载构建速度会慢到一个让人崩溃的程度。这个优化在本地开发时就能明显感觉到差异团队协作时更是巨大提升。2.2 时区问题部署第一天就得处理镜像构建阶段容易被忽略但影响深远的一个点时区。默认情况下很多基础镜像的时区是 UTC而国内业务一般需要 CST北京时间。如果容器里运行的业务需要打印日志、做定时任务时区不一致会导致日志时间和服务器本地时间差 8 小时定时任务定点执行容易直接错位。最简单的处理方式是在 Dockerfile 里直接设置ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ /etc/timezone或者更简洁的方式在 Compose 文件里统一配置environment: - TZAsia/Shanghai需要注意Nginx 镜像基于 Alpine 时可能没有/usr/share/zoneinfo目录这时可以安装tzdata包或者直接用 Compose 的TZ环境变量来达到目的。Java 应用则最好在启动命令中显式指定-Duser.timezoneAsia/Shanghai因为 JVM 默认有时自己从系统读时区有时又会优先读环境变量多设一手最保险。2.3 构建用户权限别让 root 在裸奔另一个细节是容器内用户权限。默认情况下 Docker 容器内以 root 运行构建时 RUN 的指令都以 root 执行生产容器在对外提供服务时保持 root 身份会增大被攻击后的风险面。很多官方镜像也专门提供了更安全的做法。我自己的习惯是Nginx 这种本身设计良好的镜像保持默认即可但对于 Java、Python、Node 这类应用镜像在 Dockerfile 里创建一个非 root 用户来启动应用RUN addgroup -S appgroup adduser -S appuser -G appgroup USER appuser这个 USER 指令放在 ENTRYPOINT 之前之后的所有运行阶段包括 PID 1 进程都会以非 root 身份执行。有一类坑是数据卷挂载目录的权限如果宿主机上的数据目录是 root 所有容器内非 root 用户写入时会提示 permission denied需要在宿主机上先处理目录归属chown或者挂载时使用适当的用户 ID 映射。3. Compose 编排把服务之间的关系一次理清3.1 服务拆分与实际依赖关系有了单个镜像接下来是把多个服务组织起来。docker-compose.yml是部署的核心配置文件它的价值在于把“网络、端口、数据卷、环境变量、启动顺序”这些运维信息全部声明化。部署上线时真正需要维护的不是命令而是这份声明文件。在做 Compose 编排时先梳理清楚项目包含哪些服务服务之间的依赖方向是怎么走的然后才动手写配置。我用一个常见的前后端分离项目来举例服务包括前端静态资源由 Nginx 容器提供服务后端 APIJava 或 Node 容器数据库 MySQL缓存 Redis如果有对应的 Compose 配置大致是这样version: 3.8 services: mysql: image: mysql:8.0 container_name: project-mysql restart: always environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} volumes: - mysql-data:/var/lib/mysql networks: - internal backend: build: ./backend container_name: project-backend restart: always depends_on: - mysql environment: SPRING_PROFILES_ACTIVE: prod DB_HOST: mysql DB_PORT: 3306 DB_NAME: ${MYSQL_DATABASE} DB_USER: root DB_PASSWORD: ${MYSQL_ROOT_PASSWORD} ports: - 8080:8080 networks: - internal frontend: build: ./frontend container_name: project-frontend restart: always depends_on: - backend ports: - 80:80 networks: - internal networks: internal: driver: bridge volumes: mysql-data: driver: local3.2 端口映射与网络模式的关键选择Compose 文件里最容易纠结的是端口映射。这里我想强调一个原则容器与容器之间通过内部网络访问尽量少用端口映射暴露给宿主机。比如后端 8080 端口如果只是前端 Nginx 反向代理需要访问完全可以不映射到宿主机让 Nginx 容器通过http://backend:8080直接访问内部的 8080。只有在需要外部直接访问时才映射到宿主机的某个端口。这样做有几个好处第一减少了宿主机的端口占用和暴露面安全组、防火墙要放行的端口更少第二容器间的访问走 Docker 内部网络不经过宿主机网络栈时延更低且不受宿主机防火墙策略干扰第三未来如果有多台后端实例前端只需要指向同一个服务名改起来也简单。MySQL 这种数据库服务我的习惯是端口不映射到宿主机只有开发调试时临时加一个映射。生产环境数据库暴露在宿主机端口上等于给攻击者多开了一扇门而且对本机的其他服务来说本来就可以通过内部网络访问没必要多此一举。如果非要外部备份工具连数据库可以考虑用 SSH 隧道或者在安全组里限制访问来源 IP。3.3 数据库容器化的数据持久化方案用 Docker 跑 MySQL 这类有状态服务最关心的就是数据会不会丢。容器本身是无状态的重启、升级容器后内部文件系统的数据都可能丢失所以数据卷volume是必须的。Compose 文件里mysql-data:/var/lib/mysql这个声明会让 Docker 把数据存放在它托管的卷目录中容器删除重建后数据依然在。这里我给一个有一定经验的人可能都会推荐的进阶做法不要把数据库和业务应用塞在同一个 Compose 项目里强制绑定反而可以给数据库单独建一个 Compose 文件单独管理它的生命周期。原因是业务应用发布频率高数据库基本不动如果混在一起每次docker-compose up -d都可能因为配置差异导致数据库容器被重建这无疑增大了数据风险。数据卷的使用还有一个注意事项容器内运行的用户对数据卷目录是否可写。MySQL 镜像对此相对友好它会在启动时自动处理数据目录权限但如果你用自定义镜像并把数据目录挂载到宿主机某个目录bind mount权限问题就经常出现。解决方式是在宿主机上提前创建目录并设置正确的属主或者使用:z这类 SELinux 标签特定系统需要。3.4 环境变量管理别把密码硬编码进 Compose 文件Compose 文件里我用了${MYSQL_ROOT_PASSWORD}这种变量引用方式这是强烈建议的实践。docker-compose.yml本身可能被提交到代码仓库里如果里面直接写数据库密码、密钥、第三方 API Token就等于把机密信息暴露给了所有有代码仓库权限的人。正确做法是把这些变量放在.env文件中并且把.env加入.gitignore。Compose 会自动读取同目录下的.env文件填充变量。还有一个常见做法是使用 Docker 的 secrets 机制但在单机 Compose 部署场景下.env文件权限管理比如设置成 600已经能满足大部分需求。后面如果上到 K8s会有更完整的 secrets 方案这里不展开。4. 从镜像到线上一次完整的部署履历记录4.1 准备部署目录与环境变量服务器上建议建立一个清晰的部署目录比方说/opt/project下面放 Compose 文件、.env、备份脚本。千万不要图省事把部署文件直接丢在 root 目录等部署的服务多起来目录结构混乱会让人很痛苦。我的目录习惯是/opt/project/ docker-compose.yml .env backup/ logs/ README.md.env文件里放的是各种环境变量。这里提醒一下.env中的值不要加引号比如MYSQL_PASSWORDStrongPassword123就好Compose 在解析时如果检测到引号会把它当成值的一部分。一个细节是密码中如果包含特殊字符如$、#需要留意转义问题$在 Compose 里有特殊含义可以用$$转义或者避免这类字符。4.2 镜像构建与推送服务器上构建还是本地构建代码准备好、Compose 文件也写完接下来是如何把镜像弄到服务器上。这里有两种路径各有优劣本地或 CI 构建镜像推送到镜像仓库比如 Docker Hub、私有仓库服务器上直接docker pull。服务器上直接执行docker compose build用服务器资源现场构建。第一种方式适合有持续集成流水线、团队协作的场景镜像在受控环境里构建确保可复现性缺点是如果要推公网仓库镜像涉及敏感业务代码时需要谨慎隐私问题可以考虑私有仓库或服务器本地 registry。第二种方式在小项目、个人项目中很常用优点是简单直接代码传到服务器上直接构建缺点也很明显——服务器性能有限构建大型前端项目会产生大量编译临时文件如果磁盘空间和内存没到位很容易构建失败。我用的折中方案是在本地先把镜像构建好打包导出再上传到服务器加载。这个方案适合个人部署和网络带宽够快的场景# 本地构建镜像 docker build -t my-project-backend:1.0 ./backend # 导出镜像 docker save my-project-backend:1.0 | gzip my-project-backend.tar.gz # 上传到服务器后加载 gunzip -c my-project-backend.tar.gz | docker loaddocker save和docker load是镜像迁移中非常趁手的工具比直接 pull 更可控尤其是服务器和本地无法通过镜像仓库互通的时候。当然如果服务器本身带宽好、内存充足直接在服务器上docker compose build也不差毕竟少了几次文件传输。4.3 启动服务与检查运行状态首次上线时我会一步一步来不会直接docker-compose up -d一次性拉起所有服务。建议的顺序是先启动数据库等它初始化完成并且健康检查通过再启动后端最后起前端。这样更容易定位问题是出在哪一层。# 启动并查看日志 docker compose up -d mysql docker compose logs -f mysql # 确认数据库就绪后 docker compose up -d backend docker compose logs -f backend # 最后再启动前端 docker compose up -d frontend首次启动时最好用docker compose logs -f跟着看日志输出。很多人喜欢直接up -d完就不管了结果过了很久发现某个容器启动失败还得从日志里一点点排查。首次部署时多花几分钟跟一下日志能省下后面几十分钟的排查时间。docker compose ps是日常查看运行状态的命令可以看每个容器的状态、端口映射和健康状态。如果 Compose 文件里定义了 healthcheck日志输出和ps状态都会更丰富。我个人强烈建议给依赖类服务都写上 healthcheck比如 MySQLhealthcheck: test: [CMD, mysqladmin, ping, -h, localhost] interval: 10s timeout: 5s retries: 5这样 Compose 的depends_on可以配合condition: service_healthy让后端等服务真正“就绪”后再启动而不是单纯“进程起来了”就启动。这个机制能大幅降低因启动顺序问题导致的连接失败。4.4 反向代理配置与 HTTPS 接入前端容器如果直接用 Nginx 提供服务通常还需要做好两件事把/api这类请求反向代理到后端容器以及配置 HTTPS 证书。拿前端 Nginx 配置举例容器内部监听 80 端口宿主机通过 80 端口对外提供服务。配置反向代理的要点是 upstream 指向后端容器名因为 Compose 网络内可以通过服务名访问server { listen 80; server_name example.com; root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://backend:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }上面的try_files是 SPA单页应用必需的处理逻辑否则刷新页面时 Nginx 会尝试找真实文件找不到就返回 404而不是正确回退到index.html。HTTPS 证书可以用 certbot 在宿主机上申请并自动续期然后把证书目录挂载进 Nginx 容器再在 Nginx 配置里启用 443 端口并跳转 80。挂载证书时要注意容器内 Nginx 用户对证书文件的读取权限有时候证书文件是 root 权限且目录不可读容器内启动 Nginx 会直接报错。4.5 日常发布更新镜像版本管理项目上线之后日常更新的流程应该是高度标准化、可复现的。我的标准发布流程是# 1. 在部署目录中更新代码或切换分支 # 2. 重新构建镜像 docker compose build backend # 3. 滚动重启对应服务 docker compose up -d backend # 4. 检查服务状态 docker compose ps docker compose logs --tail50 backend这里有一个发布版本管理的细节尽量不要使用latest标签。latest带来的问题是无法精确知道线上跑的是哪个版本。我习惯用明确的版本号标签比如my-project-backend:1.2.0Compose 文件里也写死这个具体版本。回滚时就很简单——把 Compose 文件里的版本改回上一个重新up -d即可。如果用latest回滚时根本不知道“上一个”是哪个只能瞎猜这是很可怕的事情。5. 线上排查这几类问题我基本都遇到过5.1 容器一直重启日志倒是一堆线上最容易遇到的一个现象容器启动几秒后退出又被restart: always拉起来反复重启日志刷了一屏又一屏。这时候第一件事是看日志但注意要看的是docker logs的最后几百行不是从头翻到尾。很多启动失败的原因在最后几行就能找到。常见原因分成几类端口冲突宿主机上已经有别的进程占了容器要映射的端口。用ss -lntp看一下端口占用。环境变量缺失代码里读取某个环境变量时找不到值启动时直接抛异常。检查.env里变量名和 Compose 里引用是否一致。数据库连接失败后端在启动阶段就连数据库数据库还没就绪、密码错误、网络不通都会导致后端崩溃。这时候有效的办法是等数据库就绪后再启动后端或者使用前面说的 healthcheck 机制。内存不足如果docker compose ps显示容器状态是OOMKilled大概率就是内存不够。用free -h和dmesg | grep -i oom确认。我的建议是排查问题时按“日志 → 资源 → 配置”三层来。先看日志定位是什么层面的错误再看系统和容器的资源使用情况最后核对配置项和环境变量。直接猜原因往往是在浪费时间。5.2 宿主机能访问公网就是访问不了这类问题的特征很明确在服务器本机 curl 服务的地址能通从外网访问就是超时或者拒绝连接。这时候大概率跟容器没什么关系问题出在网络链路上排查顺序是检查云服务商安全组是否放行了对应端口TCP 80/443/8080 等。检查系统防火墙是否放行比如ufw status。检查容器端口映射是否正确docker ps看PORTS列。检查应用本身是否监听了正确的地址有些框架默认只监听 127.0.0.1容器内或宿主机访问外部 IP 时就会失败。另外要提醒一个容易忽略的场景某些云厂商的安全组规则不是即时生效修改后有一定延迟别着急判断没生效等一两分钟再测试。5.3 数据卷备份与恢复的实操记录线上跑了一段时间数据库里积累了不少数据这时候最怕的就是误操作把数据库容器删了。虽然数据卷还在但如果没有备份习惯碰到磁盘损坏、误删卷或者迁移服务器损失就是不可逆的。我目前使用的备份策略是每天凌晨用 cron 执行数据库逻辑备份备份文件保留 7 天。MySQL 的逻辑备份用容器内自带的命令就能完成docker exec project-mysql mysqldump --single-transaction -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE /opt/project/backup/project_$(date \%Y\%m\%d).sql这个命令里的--single-transaction参数对 InnoDB 表很重要它可以不用锁表就完成一致性备份避免备份过程中业务写入被阻塞。恢复时操作正好反过来docker exec -i project-mysql mysql -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE /opt/project/backup/project_20250601.sql数据卷备份是另一种思路直接把卷目录打包。先查一下卷对应的实际路径docker volume inspect project_mysql-data然后把Mountpoint路径下的整个目录打包。这个方法适合整库全量迁移但恢复时要求目标环境的数据目录结构和权限一致比较繁琐。日常备份我更推荐逻辑备份文件可读性高、体积小、迁移时也灵活。5.4 日志不持久化容器一删全没了容器日志默认写在 Docker 的管理空间里但如果容器被删、或者日志量大到把 Docker 日志文件撑爆日志就会丢失或者影响 Docker 本身运行。这是一个需要在部署之初就解决好的问题。在 Compose 文件里可以对日志做限制和持久化services: backend: logging: driver: json-file options: max-size: 50m max-file: 5如果还想把日志落到宿主机上的固定目录可以对容器内的日志目录做 bind mount比如volumes: - /opt/project/logs/backend:/app/logs线上排查问题时日志就是救命稻草。没有日志持久化的容器一旦重启、重建之前所有的问题线索都会消失这会让排查线上问题变成一场灾难。5.5 权限问题Permission denied 的立体排查权限问题在 Docker 部署中相当常见表现形式五花八门创建文件失败容器内用户不是 root数据卷目录宿主机属主是 root。读取上传文件失败Nginx 用户没有权限读取挂载目录里的文件。执行命令失败宿主机上挂载进来的脚本没有可执行权限。解决思路也简单要么统一容器内用户和宿主机目录属主让 uid 对上要么在容器启动入口处用 root 修改权限后再切换用户。我最常用的方式是先确认容器内运行用户的 uid然后在宿主机上chown -R uid:gid /opt/project/logs直接解决目录写入权限不一致的问题。# 查看容器内当前用户 uid docker exec project-backend id # 输出结果类似 uid1000(appuser) gid1000(appgroup)然后在宿主机上chown -R 1000:1000 /opt/project/logs/backend这样容器内非 root 用户就能正常写宿主机挂载目录了。很多经验不足的同学在遇到权限问题时习惯直接chmod 777这是很危险的做法尤其是数据目录。正确思路是精确匹配 uid/gid。6. 部署完成后我建议你再做这几件事前面的内容讲完了从镜像构建到线上运行的完整流程最后分享几个部署完成后最好立即跟进的小事它们直接影响后续的运维体验。第一把部署文档写下来。哪怕只是几百字的 README记录 Compose 文件的用途、每个服务的端口、.env里有哪些变量、备份命令是什么、回滚流程怎么走。等你过几个月再碰这个项目这些记录能帮你节省的时间远超写它的时间。我自己的习惯是部署完当天就写 README趁所有细节还在脑子里不然后面全靠回忆去猜比重新部署一遍还痛苦。第二设置日志轮转和磁盘告警。docker 默认的日志策略不限制大小一个长期运行的服务日志文件能默默从 GB 涨到 TB。我吃过一次教训某次容器日志文件暴涨直接把磁盘塞满导致数据库容器写入失败、服务异常。从那以后所有 Compose 文件我都强制带日志参数logging: driver: json-file options: max-size: 100m max-file: 3第三定期做恢复演练。备份从来不是为了“有备份”这个心理安慰而是为了恢复的时候真的能用上。我建议每个月在测试环境执行一次从零恢复到完整可访问的演练就是把备份文件、镜像、Compose 文件全部重新拉起一遍确认流程没坏。如果自己都没怎么测过备份恢复真遇到事故时才发现备份文件损坏或者恢复命令不对那就追悔莫及了。第四关注镜像和依赖的安全更新。基础镜像和依赖包的安全漏洞是持续存在的最好养成定期重建镜像的习惯不用等漏洞公告找上门。至少每季度用最新基础镜像构建一次生产镜像同时检查项目依赖是否有已知的高风险漏洞。第五把回滚路径练熟。每发布一个新版本都应该同时明确“如果这个版本出问题我回滚到哪、怎么回滚”。我习惯在每个版本发布前随手写下一条回滚命令。多数时候用不上但碰上更新后服务异常、需要立刻恢复线上手边有现成方案和临时抓瞎是完全两种状态。总体来说Docker 部署是一个典型的“把事情做对”的过程。前期花一点时间把镜像构建、Compose 编排、数据持久化、日志策略这些基础打扎实后续的上线和维护都会顺畅很多。希望这篇总结能给你提供一条清晰的路径参考让你在部署自己的项目时少踩几个我曾经踩过的坑。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表