个人博客上线
从电脑里的代码,到别人能打开的网站:零基础服务器部署实录
本文根据 resin-blog 在 2026 年 9 月的部署与迁移经历整理,代码流程核对于 2026-09-14。适合会在电脑上运行项目,却还不清楚服务器、Docker、域名之间关系的同学。
文中的 IP 和域名示例使用
203.0.113.10、www.example.com等占位值,不能直接访问。服务器路径采用本项目实际结构。文章是流程教程,不是把所有代码块依次粘贴就能完成的通用安装脚本。
我第一次迁移网站时,以为把代码压缩、传到另一台服务器,事情就完成了一半。后来才发现:程序能启动、域名能访问、图片能显示、下一次还能正常发布,是四件需要分别验证的事。
这篇文章把它们串起来。先认识网站由哪些部分组成,再连接服务器,理解容器和发布脚本,最后讲如何验证、备份和迁移。
第一部分:先画一张地图,知道自己在操作什么

图中数据库类型是通用举例;本项目实际使用 PostgreSQL。发布脚本在电脑上打包源码,在服务器上构建应用,具体顺序见第四部分。
1. 服务器也是电脑,只是它一直替你运行程序
在本地运行开发命令后,浏览器可以打开网站。但电脑关机,开发服务也就停止。云服务器提供一台通过网络管理的机器,让网站持续运行。
服务器上同样有操作系统、内存、磁盘和文件夹。这里使用 Alibaba Cloud Linux 3。虽然它和一些 Linux 发行版有相近的操作习惯,但不能把它直接当成 CentOS;安装之前先看系统实际是什么。
2. 一次访问需要哪些角色
| 名称 | 可以怎样理解 | 在本项目里做什么 |
|---|---|---|
| 本地电脑 | 工作台 | 写代码、测试、发起发布 |
| Git | 有编号的代码版本册 | 记录这次发布的代码版本 |
| 云服务器 ECS | 持续工作的电脑 | 运行 Nginx 和网站容器 |
| SSH | 加密的远程终端连接 | 在电脑上操作服务器 |
| Docker 镜像 | 程序和运行依赖的打包结果 | 提供可启动的应用版本 |
| Docker 容器 | 镜像启动后的运行实例 | 真正处理网站请求 |
| Nginx | 网站入口和转发员 | 接收 HTTPS,把请求交给对应应用 |
| DNS | 域名地址簿 | 把域名解析为服务器地址 |
| 数据库 | 内容资料库 | 保存文章、账号和互动数据 |
| OSS | 图片等文件的云端存储 | 保存新上传的博客图片 |
浏览器先通过 DNS 找到地址,然后向该地址发起连接。DNS 并不负责转发每一张网页。
本项目的访问关系可以读成:
浏览器查询 DNS → 得到服务器 IP
浏览器请求 HTTPS → 服务器 Nginx → 博客容器
├→ 云数据库:读取文章
└→ OSS:上传图片
浏览器拿到文章中的图片 URL → 从 OSS 读取图片
代码、数据库和图片不一定在同一台机器上。 本项目数据库在 Neon,新图片在 OSS。这一点直接决定以后如何备份。
3. 三件容易混淆的事
- 部署:让一个应用版本运行起来。
- 发布更新:用新代码构建的新版本替换当前版本。
- 迁移服务器:换一台机器承接现有网站,包括配置、运行环境、文件和访问入口。
迁移时可以先恢复原来正常运行的版本,再验证以后的发布脚本。没有必要把“换机器”和“大改代码”捆在同一次操作里。
第二部分:连接服务器,先分清命令在哪执行

4. 连接前准备什么
在云控制台确认服务器正在运行,记下公网 IP、登录用户和登录方式。本文沿用当时的 root 密码登录;这是管理员账户,操作权限很大。
还需要允许 SSH 连接。安全组可以理解为云平台上的网络入口规则:SSH 通常使用 TCP 22,网站使用 TCP 80 和 443。SSH 的来源范围尽量限定为自己的网络;网站端口需要供访客访问。服务器内部防火墙也可能有另一层规则。
这与“应用跑在哪个端口”不同。博客的 3000 端口绑定到服务器本机,外部访客通过 Nginx 访问,不需要直接开放它。
5. 先认识服务器,再输入密码
SSH 主机指纹是服务器公钥的摘要,用来核对你是否连接到了预期机器。
操作位置:云控制台提供的可信服务器终端。 输入:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256
记下其中的 SHA256:...。随后从电脑连接时,核对提示的指纹与这份可信记录一致。ssh-keyscan 只能采集网络对面给出的公钥,本身不能证明对面就是你的服务器。
操作位置:自己电脑的 PowerShell。 下面是连接示例,IP 必须替换:
ssh [email protected]
首次连接核对身份后按提示确认,再输入密码。输入密码时通常不显示字符,也不显示星号,这是正常现象。
成功连接后,提示符会从电脑上的 PS C:\...> 变成类似 [root@server ~]#。此时输入普通 Linux 命令,操作的是服务器。
6. 第一次登录,只做只读检查
操作位置:服务器终端。目的:确认机器身份、系统和资源。
hostname
cat /etc/os-release
uname -m
df -hT /
free -h
| 命令 | 看什么 | 怎样理解结果 |
|---|---|---|
hostname |
机器名称 | 迁移时防止把旧机、新机弄反 |
cat /etc/os-release |
Linux 发行版 | 决定安装说明是否适用 |
uname -m |
CPU 架构 | 例如 x86_64,影响镜像兼容性 |
df -hT / |
根文件系统容量和类型 | 判断可用磁盘空间 |
free -h |
内存和 Swap | 判断运行、构建是否有资源余量 |
Swap 是用磁盘提供的交换空间,可以缓解内存紧张,但速度和真实内存不同,不能把 2 GiB 内存加 4 GiB Swap 当成 6 GiB 内存。
输入 exit 会退出这次远程连接,回到电脑终端。
7. 连接和传文件是两回事
ssh 让你执行命令;scp 可以复制文件。
例如先在服务器上创建练习目录:
mkdir -p /root/upload-demo
然后回到 Windows PowerShell,把自己准备好的 D:\demo\hello.txt 上传:
scp "D:\demo\hello.txt" [email protected]:/root/upload-demo/hello.txt
来源是电脑文件,落点是服务器文件。回到服务器执行 ls -lh /root/upload-demo/hello.txt,能看到文件才算上传完成。
上传代码包也是同一道理。但文件到了服务器,并不表示网站已经启动。
第三部分:代码、镜像、容器和数据,分别放在哪里

图中的 Python 文件只是源码的举例,本项目使用 TypeScript。数据卷独立保存的前提是没有执行删除该卷的操作,它也需要备份。
8. 从源文件到运行实例
源码是开发时编辑的文件。Dockerfile 描述怎样安装依赖、编译源码,并把运行所需内容装进镜像。Docker 根据镜像创建容器后,程序才开始运行。
容器不是一台完整的独立虚拟机;它是带有隔离环境的进程。一个镜像可以启动多个容器,镜像名和容器名也不是同一个概念。Docker:什么是容器
源码 + Dockerfile → 构建 → 应用镜像 → 创建并启动 → 应用容器
在本项目中,博客容器名是 resin-blog,应用镜像则带着一个版本标签。以后换版本,可以核对到底运行的是哪一个镜像。
9. 数据不能只靠容器保存
容器中的可写文件会随着容器删除而丢失。需要持续保存的内容,应放在数据卷、明确的宿主机挂载目录或外部存储中。Docker 数据卷有独立于容器的生命周期,但也可能被明确的删除操作移除,不能因此省略备份。Docker:数据卷
本项目采用:
| 内容 | 实际位置 |
|---|---|
| 开发源码 | 本地 D:\resin-blog |
| 服务器项目与发布状态 | /www/wwwroot/resin-blog |
| 生产配置 | /www/wwwroot/resin-blog/.env |
| 旧版上传图片 | Docker 命名卷,挂到 /app/public/uploads |
| 新上传图片 | 阿里云 OSS |
| 正式文章等业务数据 | Neon 云数据库 |
| Nginx 配置 | /etc/nginx |
| 迁移归档和操作日志 | /root/migration-backup |
/www 并不是 Linux 强制要求的网站目录。放在 /home 或 /opt 也可以,但部署脚本、挂载路径、权限都要一致。本次沿用 /www/wwwroot/resin-blog,减少迁移时需要同时改变的东西。
10. 为什么作品集没有一份明显的源码文件夹
当时检查作品集发现,它直接从镜像启动,没有网站目录挂载。容器里的静态文件位于 /usr/share/nginx/html。
这些是构建后的 HTML、JS、CSS 等产物,不一定包含开发时的原始组件、注释和工程配置。迁移镜像可以恢复网站运行;继续开发仍要保留源码仓库。
11. Compose 是一份启动说明书
手动启动容器时,需要指定镜像、环境变量、端口和数据卷。Docker Compose 把这些参数写进一个 YAML 文件,避免每次重新输入。
下面摘自本项目发布配置的关键部分,用于阅读,不是完整的可独立运行配置:
services:
web:
image: resin-blog:${IMAGE_TAG:?IMAGE_TAG is required}
container_name: resin-blog
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
env_file:
- .env
volumes:
- blog_images:/app/public/uploads
端口这一行读作:服务器本机地址 127.0.0.1 上的 3000,转给容器里的 3000。Nginx 在服务器上,因此能访问这个入口。
.env 是运行配置,不是源码的一部分。修改宿主机文件后,已运行容器的环境变量不会自动刷新;应通过正确的部署流程重新创建容器。也不要把它的内容贴到公开教程里。
12. 看状态时,人应该输入什么
操作位置:已经安装 Docker 的服务器。以下都是检查命令。
docker --version
docker compose version
systemctl is-active docker
docker ps -a
docker image ls
docker logs --tail 50 resin-blog
docker ps -a 看容器,docker image ls 看镜像,docker logs 看程序输出。日志可能包含业务信息,分享前检查是否有密钥或用户数据。
Up 表示容器运行中;有健康检查的容器出现 healthy,表示该检查通过。它仍然不能替代登录、上传和数据库等业务验收。
第四部分:自动化部署,不过是把人工步骤写进脚本

图中第 6 步的“本地”指服务器本地镜像库;重建发生在服务器。第 7 步包含脚本检查及发布后的人工作业验收。
13. 先讲清楚:这份脚本不是空服务器安装器
本项目日常发布前,服务器已经有 Docker、Compose、生产配置和可用的网站环境。首次部署还需要准备域名、证书、数据库、OSS 和 Nginx。
不要在一台完全空白的机器上双击脚本,就期待它替你创建所有云资源。新机器可以先通过已有备份恢复环境,也可以根据所选系统的官方安装说明逐项初始化,再接入发布流程。
14. 如果全部由人手动做,会发生什么
假设我们修改了博客的一处页面:
- 在电脑上检查改动、运行测试,提交成一个 Git 版本。
- 把这个版本打成压缩包。
- 连接正确的服务器,把压缩包传过去。
- 在服务器核对压缩包,解压到新的版本目录。
- 用 Dockerfile 构建应用镜像。
- 检查新版本需要的配置,执行必要的数据库结构迁移。
- 用新镜像重新创建博客容器。
- 等待健康检查,再实际访问网站。
- 成功就记住这个版本;失败则尝试恢复上一个应用版本。
脚本自动化的是这些重复动作。它仍然需要正确的服务器地址、配置和凭据,也仍然可能因为网络、空间、代码问题而停止。
15. 三个入口,各自负责一段
自己电脑:deploy.cmd
↓ 启动
自己电脑:scripts/deploy.ps1
↓ 测试、打包、核对身份、通过 SSH 上传
服务器:scripts/deploy-remote.sh
↓ 构建、配置预检、数据库迁移、容器切换、健康检查
服务器:运行新的 resin-blog 容器
| 文件 | 主要职责 |
|---|---|
deploy.cmd |
Windows 双击入口 |
scripts/deploy.ps1 |
检查分支和工作区、测试、打包、核验主机指纹、上传并执行远程脚本 |
scripts/deploy-remote.sh |
控制服务器上的完整发布过程和失败处理 |
Dockerfile |
描述如何得到应用镜像与一次性迁移镜像 |
docker-compose.deploy.yml |
描述容器启动参数 |
docker/runtime-healthcheck.mjs |
检查运行配置和应用响应 |
博客使用“上传源码,在服务器构建”。作品集使用的镜像仓库发布方式是另一条路线,不能把两者混用。
16. 第一次配置发布目标
操作位置:Windows 的项目目录。 只有在 deploy.config.json 不存在时才复制示例文件;已有配置就编辑,避免覆盖:
Set-Location D:\resin-blog
Copy-Item deploy.config.example.json deploy.config.json
配置里最重要的是:
| 字段 | 应填写什么 |
|---|---|
remoteAddress |
目标服务器公网 IP |
remoteUser |
登录用户,本次使用 root |
remotePort |
SSH 端口,本次为 22 |
hostKeyFingerprint |
从可信控制台取得的主机指纹 |
deployRoot |
/www/wwwroot/resin-blog |
branch |
允许发布的 Git 分支,本项目为 main |
retainReleases |
成功版本保留数量,本项目默认 3 |
密码由终端提示时输入,不写进这个文件。换服务器以后,IP 和可信指纹需要一起更新。
17. 日常发布,真正需要人为做的步骤
先在 电脑项目目录 看改动:
git status --short
git diff
检查并提交准备发布的文件,工作区保持干净。然后运行:
.\deploy.cmd
当前默认流程会运行完整测试。看到目标机器、版本和目录后,核对无误,输入 DEPLOY。随后按提示输入服务器密码,通常上传一次、执行远程发布一次;失败清理还可能再次询问。
本项目使用 git archive HEAD 打包,意味着发布的是已经提交的版本。编辑器里改了但没提交的内容,不会因为双击发布就自动成为正式版本。被忽略的本地配置也不会随正常的 Git 归档进入发布包。
18. 文件从哪里到哪里
电脑 Git HEAD
→ 电脑临时目录中的源码压缩包
→ 服务器登录用户主目录中的临时上传包
→ /www/wwwroot/resin-blog/.deploy/incoming/
→ /www/wwwroot/resin-blog/.deploy/releases/本次版本号/
→ 构建进 Docker 应用镜像
成功后,.deploy/current 指向本次版本目录。它是一个“指向哪里”的符号链接,不能把改这个链接误当作已完成容器切换。
不同文件各有用途:压缩包负责运输,版本目录负责构建和保留版本,镜像负责启动应用,容器负责处理请求。
19. 为什么脚本里有这么多检查
- 主机指纹核对:防止上传到错误的服务器。
- SHA-256 校验:比较上传前后的包是否一致,不代表代码逻辑必然正确。
- 发布锁:同一时刻只允许一个发布流程修改这个站点。
- 资源检查:磁盘或内存明显不足时,提前停止。
- 配置预检:发现缺失变量,先报告名称,而不是启动后再等待报错。
- 健康检查和回退:发现新应用无法正常运行时,尝试恢复旧应用。
本项目先构建,再检查新镜像的运行配置,再执行 Prisma 迁移,最后切换容器。数据库迁移会修改表结构,因此应用回退不等于数据库回退。有破坏性的表结构变更,必须单独设计兼容方案和数据恢复办法。
当前是替换单个博客容器,切换期间可能有短暂中断,不是完整的零停机发布系统。
20. 日志出现 DONE,为什么还不能关窗口
一次发布有很多步骤。Prisma Client generated 只说明客户端生成成功;exporting layers done 只说明某个镜像构建完成。
真正需要继续等到容器切换和健康检查通过,再验证外部访问。配置检查过了也不代表 OSS 权限正确,它只能检查规定的变量是否存在、格式是否基本合理。
看到 CACHED 通常表示复用了构建结果。不要看到安装步骤名称就以为每次都重新下载,也不要为了“保险”每次清空构建缓存。
第五部分:让浏览器通过域名找到网站
21. 端口就像不同的服务窗口
本次服务器上的职责是:
公网 443 → Nginx
├→ www 域名 → 127.0.0.1:3000 → 博客
└→ portfolio 域名 → 127.0.0.1:8080 → 作品集
Nginx 根据域名选择站点,把请求交给相应的应用。这就是反向代理。HTTPS 证书在这个入口使用,所以应用容器自己监听 HTTP 也能对外提供 HTTPS 网站。
22. Nginx 的配置要找实际安装位置
原来通过面板安装的 Nginx 在 /www/server/nginx,后来系统软件包安装的版本在 /etc/nginx。同一个软件,安装方式不同,路径可能不同。
操作位置:服务器。目的:先确认配置入口。
nginx -v
nginx -t
本项目主配置是 /etc/nginx/nginx.conf,博客站点配置是 /etc/nginx/conf.d/coderesin.xyz.conf。
修改前备份原文件;修改后先 nginx -t。只有配置检查通过,再执行 systemctl reload nginx 重载。重载配置不需要重新构建博客镜像。
迁移中遇到过 unknown directive "http2":旧配置的写法与新机 Nginx 1.24 不兼容。我们根据实际版本适配后再测试,没有因为“都是 Nginx”就直接覆盖启用。
23. 三层验证,逐层缩小问题范围
第一层:服务器内部,应用是否响应。
curl -sS -o /dev/null -w 'HTTP=%{http_code}\n' http://127.0.0.1:3000/
200 表示这个页面请求成功。它没有测试 Nginx、公网入口和 DNS。
第二层:电脑直接访问新机,但保留正确域名和证书验证。 替换示例域名和 IP:
curl.exe --ipv4 --noproxy "*" --resolve "www.example.com:443:203.0.113.10" -sS --max-time 20 -o NUL -w "HTTP=%{http_code} IP=%{remote_ip}\n" "https://www.example.com/"
--resolve 为这次请求指定地址,不会修改公共 DNS。这样可以先验证新服务器,再让所有访客切换过去。
第三层:切换 DNS 后,按正常方式访问。
Resolve-DnsName www.example.com -Type A
curl.exe --ipv4 --noproxy "*" -sS --max-time 20 -o NUL -w "HTTP=%{http_code} IP=%{remote_ip}\n" "https://www.example.com/"
结果中的 IP 应是新机地址。最后再打开浏览器,测试文章、登录、评论和图片。301 如果是设计好的跳转,例如裸域跳到 www,并不是故障。
第六部分:从实际踩坑理解排查顺序
24. 能连接服务器,为什么 Docker 下载失败
SSH 通和镜像仓库通,是不同的网络路径。
这次服务器能登录,但 Docker Hub 请求超时。本项目后来改用 Docker 官方镜像的 ECR Public 分发地址,并固定了基础镜像摘要。它改变的是基础镜像下载来源,博客依然在服务器构建,没有改成把博客上传到 ACR。
排查时先看失败的是下载基础镜像、安装依赖、编译代码,还是启动容器。不要看到“部署失败”就重复调整密码。
25. 图片上传成功,为什么文章里看不到
上传权限和公开读取权限不同。后台有凭据写入 OSS,不代表匿名读者可以读取图片 URL。
当时直接访问图片返回了 403,原因是读取权限。处理方向是只给博客图片目录配置需要的读取权限,而不是把整个 Bucket 设置成公共读写。
判断成功也要拆两步:上传接口成功;在无登录状态打开返回的图片 URL 也成功。
26. 图片要传 OSS,为什么 Nginx 会说请求太大
本项目的上传路径是:
浏览器 → Nginx → /api/upload → OSS
图片先经过 Nginx,才到后端。因此前面的限制也生效。Nginx 的 client_max_body_size 默认是 1m,超过限制会返回 413。Nginx 官方说明
本项目单张图片最多 8 MiB,整个请求还包含表单信息,所以对应的 www 站点配置增加了:
client_max_body_size 9m;
这行放在处理博客请求的 server 块内,不是单独粘贴到终端。2026-09-11 的实际输出确认语法检查与重载成功;文章依据的记录尚未包含修改后图片上传的完整验收结果,因此不把它写成“所有图片问题都解决了”。
27. 还有几条经常被误解的报错
| 现象 | 先看哪里 |
|---|---|
| SSH Permission denied | 用户、登录方式、交互输入的密码 |
| HTTP 000 或超时 | TCP 连接、安全组、防火墙、目标地址和服务监听 |
| Nginx 502 | 容器是否运行、后端端口是否正确 |
| Missing environment variable | 新版本要求哪些变量,容器是否读到配置 |
| 磁盘买了 50G,系统仍显示 40G | 云盘、分区、文件系统是否都已扩容 |
| 容器 healthy,登录仍失败 | OAuth 回调、真实会话、数据库等业务链路 |
遇到 TLS 证书校验失败,应排查信任链和连接配置,不要长期通过关闭证书验证来绕过。我们曾做过移除禁用变量后的临时只读查询,查询成功不代表已经永久修正运行容器的配置。
第七部分:迁移是搬家,备份要覆盖每一种东西

图中云服务的恢复、迁移按需要执行。如果继续使用原来的 Neon 和 OSS,只需核对新机连接、权限与独立备份,不必为换 ECS 再搬一次外部数据。
28. 先列清单,不要把整个 Docker 都打包
同一台服务器可能有多个项目。迁移前明确本次范围,检查运行镜像、挂载和端口。像本次,只迁移博客和作品集,不能顺手清理其他数据库或匿名卷。
| 要保留的东西 | 为什么不能省略 |
|---|---|
| 源码仓库 | 以后继续开发与发布 |
| 当前运行镜像 | 需要原样恢复应用时使用 |
.env、Compose、发布状态 |
决定应用怎样启动、连到哪里 |
| Nginx 和证书 | 决定域名、HTTPS 和转发 |
| 数据卷 | 可能包含镜像之外的历史文件 |
| 外部数据库 | 不在 ECS 系统盘里 |
| OSS 对象 | 不会自动进入服务器快照 |
29. 文件迁移,一步一步拆开
人工操作可以理解为:
- 旧机:确认要迁移的文件和数据,选择一致的备份时间;对持续写入的数据,使用对应的备份方法或暂停有关写入。
- 旧机:生成选定文件的归档,记录校验值。
- 电脑或新机:通过 SSH/SCP 复制归档。
- 新机:核对归档校验值,先解压到暂存目录检查。
- 新机:把配置和文件放到预定位置,恢复所需卷和权限。
- 新机:加载需要的 Docker 镜像,根据启动配置创建容器。
- 新机与电脑:完成前面三层访问验证,再处理 DNS。
本次也用过流式传输:旧机边打包,新机边接收,避免旧机磁盘额外存放大归档。下面只是结构示意,不是完整可执行命令:
新机执行:ssh [核验过的旧机连接] 'tar [选定文件并输出到连接]' > 新机备份文件
引号里面的打包发生在旧机;引号外面的 > 把收到的内容写在新机。理解执行位置,比记住一长串命令更重要。
Docker 镜像归档需要通过 docker image load 导入,再按配置启动容器。把压缩包放进 /www 不会自动创建网站,镜像归档也不包含挂载卷的内容。
30. 另一种方法:快照加自定义系统镜像
这次第二次换机采用了:系统盘快照 → 自定义系统镜像 → 新 ECS 更换系统盘 → 启动验证。
这里的“系统镜像”包含磁盘上的操作系统和文件,和 Docker“应用镜像”不是同一种东西。
当时源系统盘为 50 GiB,新机最初为 40 GiB,最终换成 50 GiB 系统盘承接恢复。具体容量、地域和更换条件,以操作时控制台的校验为准。更换系统盘会替换目标机的系统盘内容,应明确目标是准备恢复的新机,而不是仍在服务的旧机。
快照只是那个时间点的磁盘状态。外部数据库、OSS 需要分别备份;有运行中的数据库时,还要考虑应用一致性,不能认为“快照可用”就等于所有业务数据都能完整恢复。
31. 什么时候才能退订旧服务器
我们曾误退订过仍需要使用的 ECS,因此后来把退役放在最后:
备份完成 → 新机恢复 → 本地与公网验证 → 同步最终变化
→ 切换 DNS → 更新发布目标 → 验证登录和图片等功能
→ 暂停旧机并观察 → 确认恢复材料可用 → 旧机退役
还应核对定时任务、证书续期、脚本里的旧 IP、外部服务白名单等依赖。网站首页能打开,只是其中一项。
备份如果只放在准备退订的服务器里,服务器删除后仍可能一起失去。至少保留独立于被释放机器的恢复材料,并确认它确实可读取、可恢复。
第八部分:给第一次操作的同学一张复习表
| 我想做什么 | 应先想到什么 |
|---|---|
| 看服务器文件 | 先 SSH 登录,再确认 hostname 和目录 |
| 把文件传过去 | SCP 负责复制,复制不等于启动 |
| 看应用有没有运行 | Docker 容器状态、日志和实际响应 |
| 发布新代码 | 本地提交版本,通过现有发布脚本完成整条流程 |
| 改 Nginx | 备份 → 编辑正确配置 → 语法检查 → 重载 |
| 改生产环境变量 | 保留机密,按启动配置重新创建应用容器 |
| 排查图片问题 | 区分请求大小、上传权限、公开读取权限 |
| 换服务器 | 文件、镜像、配置、卷、外部数据分别考虑 |
| 退订旧机器 | 新机验收、最终同步、备份和依赖检查后再做 |
第一次学习时,可以先完成一个小闭环:连接服务器,确认机器身份,上传一个练习文件,再找到它。理解这个闭环之后,再看源码包怎样被脚本上传、构建成镜像、启动为容器,就不再是几个陌生名词堆在一起。
真正值得记住的是每个动作的结果:文件到了哪里,哪个程序在运行,数据由谁保存,用户最终连到了哪台机器。