Docker Compose 前后端部署流程

本地构建镜像、导出 tar、上传服务器、load 后 compose 启动

Docker Compose 前后端部署流程

这套流程不走镜像仓库,而是:本地用 docker compose 构建 → 把镜像打成 tar → scp 到服务器 → docker load → 再 compose up。适合内网或临时环境,不想搭 Registry 的时候用。

整体顺序:

  1. 本地构建 frontend / backend 镜像
  2. docker save 导出 tar
  3. scp 传到服务器 /tmp
  4. 服务器 docker load 还原镜像
  5. 读入环境变量
  6. docker compose up 只重建对应服务
  7. curl 验证端口

本地构建

先进入项目的 deploy 目录,这里有 docker-compose.yml。

1
cd <项目路径>\deploy

构建用的就是这份 compose 文件,-p deploy 指定项目名,后面所有容器、网络都会挂在这个名字下面。

1
2
docker compose -p deploy build frontend
docker compose -p deploy build backend
参数 作用
-p deploy compose 项目名,镜像/容器名前缀都跟它走
build frontend 只构建 frontend 这个 service
build backend 只构建 backend 这个 service

构建完成后看一眼镜像:

1
docker images

一般会看到两个:

  • finhire-backend:latest:后端镜像(compose 里写死了 image 名)
  • deploy-frontend:latest:前端镜像(没写死 image 时,默认是 项目名-服务名,所以是 deploy-frontend)

导出成 tar

服务器上没有你本地的构建缓存,直接把镜像打包带走。

1
2
docker save finhire-backend:latest -o .\artifacts\finhire-backend.tar
docker save deploy-frontend:latest -o .\artifacts\finhire-frontend.tar
参数 作用
docker save 把镜像打成 tar,包含所有层
-o 输出文件路径
.\artifacts\ 本地产物目录,上传前确认目录存在

save 和 export 不一样:save 存的是镜像,load 回来还能再 run / compose up;export 存的是容器文件系统快照,不要用错。


上传到服务器

Windows PowerShell 里反引号 ` 是换行。密钥和服务器地址按自己的环境改,不要把私钥和公网 IP 写进仓库。

1
2
3
scp -i <密钥路径>.pem `
    "<本地路径>\deploy\artifacts\finhire-frontend.tar" `
    <用户>@<服务器IP>:/tmp/
1
2
3
scp -i <密钥路径>.pem `
    "<本地路径>\deploy\artifacts\finhire-backend.tar" `
    <用户>@<服务器IP>:/tmp/
参数 作用
-i 指定 SSH 私钥
最后一个参数 用户@主机:目标目录,这里丢到 /tmp/

传完后 ssh 上去,确认文件在:

1
ls -lh /tmp/finhire-frontend.tar /tmp/finhire-backend.tar

服务器上还原镜像

1
2
sudo docker load -i /tmp/finhire-frontend.tar
sudo docker load -i /tmp/finhire-backend.tar

load 之后再用 sudo docker images,应该能看到刚才那两个 tag。名字必须和 compose 里要用的一致,否则 up 的时候会重新 pull / build。


指定配置文件

服务器上的 compose 目录和环境文件是分开的:代码在 app 目录,密钥和端口在 config 目录。

1
2
3
cd /opt/finhire/app/deploy
export ENV_FILE_PATH=/opt/finhire/config/.env.staging
set -a && source "$ENV_FILE_PATH" && set +a

这几句在干什么:

  • ENV_FILE_PATH:告诉后面的脚本 env 文件在哪。FINHIRE_ENV_PROD 之类是给其它部署脚本起的别名,这次手动 compose up 用不到。
  • set -a:接下来 source 进来的变量自动 export,子进程(也就是 docker compose)才能读到。
  • source "$ENV_FILE_PATH":把 MYSQL_*、FRONTEND_PORT 等读进当前 shell。
  • set +a:关掉自动 export,避免后面随便定义的变量也被导出。

sudo -E 的 -E 很关键:sudo 默认会丢掉环境变量,不加 -E,刚才 source 进去的东西 compose 看不到。


启动容器

只重建某一个服务,不要把无关容器一起掀了。

1
sudo -E docker compose -p deploy up -d --force-recreate --no-deps frontend

后端有改动再跑:

1
sudo -E docker compose -p deploy up -d --force-recreate --no-deps backend
参数 作用
sudo -E 提权,同时保留当前环境变量
-p deploy 必须和构建时同一个项目名,否则会当成另一套栈
-d 后台跑
--force-recreate 即使配置没变也重建容器,保证用上刚 load 的镜像
--no-deps 不连带重启依赖服务(比如 mysql、redis)
frontend / backend 只操作这一个 service

-p deploy 一定要对上。本地 build 用的是 deploy,服务器 up 也必须是 deploy,镜像名 deploy-frontend 才对得上。


验证

1
sudo docker ps

看 frontend、backend 是不是 Up,端口映射对不对。

1
2
curl -sS http://127.0.0.1:5150/health          # 动过后端才需要
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3100/
命令 期望
后端 /health 返回健康检查内容
前端 3100/ HTTP 状态码 200

前端 200 只说明 nginx/静态资源起来了。如果页面能开但接口全挂,再去看 backend 日志:

1
2
sudo docker logs --tail 100 deploy-backend-1
sudo docker logs --tail 100 deploy-frontend-1

容器名以 docker ps 里实际名字为准。


小结

这套办法的核心就三步:本地 build 出带 tag 的镜像 → tar 搬到服务器 → load 完用同一份 compose 和同一份 env 拉起来。

容易踩的点:

  • 镜像 tag 对不上(前端经常是 deploy-frontend,不是 finhire-frontend)
  • 服务器 compose up 忘了 -p deploy
  • sudo 没加 -E,env 全丢
  • 用了 --no-deps 是故意的,mysql 没起来时不要指望 backend 自己把数据库拉起来
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 Stack 由 Jimmy 设计