11 KiB
Docker 镜像一键构建 & 远程部署脚本说明
脚本文件:docker_deplay.sh
作用:在本地构建 Docker 镜像 → 打包为 tar → 上传到远程服务器 → 在服务器上停止旧容器并启动新容器,支持多架构(AMD64 / ARM64)与“仅上传”模式。
1. 功能概述
这个脚本主要解决的一件事:
一条命令完成从本地构建到服务器部署的全流程。
包含步骤:
-
检查本地依赖(
docker、sshpass) -
按指定架构构建 Docker 镜像(
amd64或arm64) -
导出为
xxx.tar文件 -
使用
scp上传 tar 到服务器/tmp/ -
在服务器上:
- 停止并删除旧容器
- 删除旧镜像
docker load导入新的 tar 镜像- 通过
docker run启动新容器 - 清理
/tmp中的临时 tar
-
输出访问地址和部署信息
2. 运行环境要求
本地机器(执行脚本的地方)
-
操作系统:Linux / macOS(支持 Bash)
-
已安装:
-
docker(且已启动) -
docker buildx(Docker 19.03+ 一般自带) -
sshpass- macOS:
brew install sshpass - Ubuntu:
sudo apt-get install sshpass
- macOS:
-
远程服务器
-
已安装:
docker
-
当前用户具备
sudo权限(脚本中使用了sudo docker ...)
3. 快速开始(最简用法)
-
把脚本放到项目根目录(有 Dockerfile 的目录)
-
修改脚本顶部“配置变量”部分为你自己的服务器信息
-
给脚本执行权限:
chmod +x docker_deplay.sh -
直接执行(默认 AMD64 架构):
./docker_deplay.sh
执行成功后,脚本会告诉你类似:
- 服务器地址
- 访问端口
- 容器名、镜像名
- 访问 URL,例如:
http://服务器IP:8199
4. 配置变量说明(一定要先改这里)
脚本顶部这块是你需要根据实际情况修改的:
SERVER_HOST="6.6.6.86" # 服务器IP地址
SERVER_USER="ubuntu" # 服务器用户名
SERVER_PASSWORD="qweasdzxc1"# 服务器密码
SERVER_PORT="22" # SSH端口
IMAGE_NAME="epage_server" # Docker镜像名称
IMAGE_TAG="latest" # Docker镜像标签
CONTAINER_NAME="epage_server-container" # 容器名称
LOCAL_PORT="8199" # 服务器对外暴露端口
CONTAINER_PORT="8199" # 容器内部服务端口
TAR_FILE="${IMAGE_NAME}-${IMAGE_TAG}.tar" # 压缩包文件名(后面会根据架构改名)
4.1 服务器相关变量
| 变量名 | 说明 |
|---|---|
SERVER_HOST |
你的服务器 IP 或域名,例如 1.2.3.4、your.domain.com |
SERVER_USER |
SSH 登录用户名,例如 root、ubuntu |
SERVER_PASSWORD |
SSH 登录密码(脚本用 sshpass 免交互登录)不建议在生产环境明文写密码,推荐改为 SSH Key 方式 |
SERVER_PORT |
SSH 端口,默认 22,一般不用改,除非你自己改过 |
⚠️ 脚本中有一段安全检查:
if [ "$SERVER_HOST" = "your-server-ip" ] || [ "$SERVER_PASSWORD" = "your-password" ]; then ... fi如果你保留了默认占位字符串会直接退出,记得改成你自己的真实信息。
4.2 镜像 & 容器相关变量
| 变量名 | 说明 |
|---|---|
IMAGE_NAME |
构建的镜像名字,例如 epage_server |
IMAGE_TAG |
镜像 tag,例如 latest、v1.0.0 |
CONTAINER_NAME |
服务器上运行的容器名称,方便后续 docker logs/stop 等操作 |
LOCAL_PORT |
服务器对外暴露端口,比如用户访问 http://SERVER_HOST:LOCAL_PORT |
CONTAINER_PORT |
容器内部应用监听的端口,比如你的服务在容器内跑在 8199 |
TAR_FILE |
导出的镜像文件名,如 epage_server-latest-amd64.tar(脚本会自动加上架构后缀) |
在服务器上运行容器时实际使用的是:
sudo docker run -d -p ${LOCAL_PORT}:${CONTAINER_PORT} --name ${CONTAINER_NAME} ${IMAGE_NAME}:${IMAGE_TAG}
即:外部访问 LOCAL_PORT → 映射到容器内部的 CONTAINER_PORT。
4.3 架构相关变量
PLATFORM="linux/amd64" # 默认架构
ARCH_SUFFIX="" # 架构后缀,用于区分不同架构tar文件
-
当你执行
-amd时:PLATFORM="linux/amd64"ARCH_SUFFIX="-amd64"TAR_FILE="epage_server-latest-amd64.tar"
-
当你执行
-arm时:PLATFORM="linux/arm64"ARCH_SUFFIX="-arm64"TAR_FILE="epage_server-latest-arm64.tar"
这样可以在同一个目录下区分不同架构导出的镜像包。
5. 命令用法 & 参数说明
5.1 基本用法(不带参数)
./docker_deplay.sh
等价于:
- 目标架构:
linux/amd64 - 先构建镜像 → 打包 tar → 上传 → 部署 → 清理临时文件 适用于:大多数 x86_64 服务器(普通云服务器、PC 服务器)
5.2 指定架构构建 & 部署
构建并部署 AMD64
./docker_deplay.sh -amd
- 使用
linux/amd64平台构建 - 导出为
epage_server-latest-amd64.tar - 上传 & 部署完成后删除本地 tar
构建并部署 ARM64
./docker_deplay.sh -arm
- 使用
linux/arm64平台构建 - 适用于:树莓派 4、部分 ARM 服务器 等
- 导出为
epage_server-latest-arm64.tar
✅ 如果你不确定服务器架构,一般云服务器都是
amd64,树莓派/部分国产 ARM 机器则是arm64。
5.3 仅上传 & 部署已存在的 tar(不重新构建)
有时你已经在 CI 或别的机器上打好了 tar,只想复用这个 tar 文件部署到服务器,可以使用 -upload 模式。
默认 AMD64 架构,只上传 & 部署
./docker_deplay.sh -upload
-
不执行构建步骤
-
只会检查当前目录是否存在:
epage_server-latest.tar(默认)- 或根据你之前指定的架构自动命名的 tar 文件
如果你之前是用 -amd 构建过,会生成:
epage_server-latest-amd64.tar
那么你需要这样配合使用:
仅上传之前构建好的 AMD64 包
./docker_deplay.sh -upload -amd
- 跳过构建
- 查找
epage_server-latest-amd64.tar - 如果存在 → 上传 & 部署
- 部署成功后删除本地 tar
仅上传之前构建好的 ARM64 包
./docker_deplay.sh -upload -arm
- 跳过构建
- 查找
epage_server-latest-arm64.tar - 上传 & 部署
⚠️ 如果指定了
-upload,但当前目录没有对应 tar 文件,脚本会直接报错退出:未找到tar文件: xxx.tar
6. 脚本内部流程(帮你快速理解在干什么)
6.1 check_dependencies
- 检查
docker是否存在 - 检查
sshpass是否存在 如果缺少,直接提示如何安装并退出。
6.2 parse_arguments "$@"
解析命令行参数:
-amd:设置PLATFORM="linux/amd64",ARCH_SUFFIX="-amd64"-arm:设置PLATFORM="linux/arm64",ARCH_SUFFIX="-arm64"-upload:设置UPLOAD_ONLY=true- 未知参数:直接报错并退出
然后根据架构拼好最终的 TAR_FILE 名字,并打印出来。
6.3 build_image
-
如果已有同名 tar 文件,先删除
-
使用
docker buildx build构建并导出镜像:docker buildx build \ --platform $PLATFORM \ -t "${IMAGE_NAME}:${IMAGE_TAG}" \ --output type=docker,dest="./${TAR_FILE}" . -
构建成功会提示
Docker 镜像构建完成: xxx.tar
6.4 upload_to_server
通过 sshpass + scp 上传:
sshpass -p "$SERVER_PASSWORD" scp -P "$SERVER_PORT" -o StrictHostKeyChecking=no "$TAR_FILE" "${SERVER_USER}@${SERVER_HOST}:/tmp/"
目标目录为服务器的 /tmp/。
6.5 deploy_on_server
在服务器上执行一段远程脚本:
-
若存在同名容器:
docker stop CONTAINER_NAMEdocker rm CONTAINER_NAME
-
若存在同名镜像:
docker rmi IMAGE_NAME:IMAGE_TAG
-
docker load -i /tmp/TAR_FILE导入新镜像 -
docker run -d -p LOCAL_PORT:CONTAINER_PORT --name CONTAINER_NAME IMAGE_NAME:IMAGE_TAG -
判断容器是否启动成功(通过
docker ps | grep) -
清理
/tmp/TAR_FILE -
打印访问地址
6.6 cleanup_local
- 本地删除临时 tar 文件,防止堆积。
6.7 show_deployment_info
最后在本地打印一份部署摘要信息,包括:
- 服务器地址
- 应用端口
- 访问 URL
- 容器名称
- 镜像名称
- 目标架构
- 镜像文件名
7. 常见操作示例
7.1 我就一台普通云服务器(x86),一键部署
./docker_deplay.sh
或更明确一点:
./docker_deplay.sh -amd
7.2 我的服务要部署到树莓派(ARM)
在你的开发机上:
./docker_deplay.sh -arm
7.3 CI 中先构建,再单独在本地只“上传 + 部署”
-
第一步(在 CI 或其他机器完成构建):
./docker_deplay.sh -amd # 或手动构建得到 epage_server-latest-amd64.tar -
以后在你本地,只要本地有这个 tar,就可以重复部署:
./docker_deplay.sh -upload -amd
8. 日志 & 排错
脚本使用彩色日志:
[INFO]:普通流程提示[SUCCESS]:成功信息[WARNING]:警告信息[ERROR]:错误信息(一般会退出)
8.1 查看容器日志
脚本最后会提示:
如需查看容器日志,请在服务器上运行: sudo docker logs epage_server-container
你只需 SSH 到服务器上执行:
sudo docker logs -f epage_server-container
8.2 手动停止容器
sudo docker stop epage_server-container
8.3 连接类问题
-
如果报
Connection refused、No route to host:- 检查
SERVER_HOST、SERVER_PORT是否正确 - 检查服务器安全组 / 防火墙设置
- 检查
-
如果报
Permission denied:- 检查
SERVER_USER和SERVER_PASSWORD是否正确 - 或考虑改为 SSH 密钥认证
- 检查
9. 安全建议(可选优化)
目前脚本直接在代码里写了密码并通过 sshpass 使用,适合开发、内网或快速测试环境。更安全的做法:
- 禁用密码登录,只保留 SSH Key
- 修改脚本,将
sshpass部分改为纯ssh/scp,让系统自动使用私钥 - 或从环境变量中读取密码,而不是写死在脚本里
如果你愿意,我也可以帮你基于这个脚本再拆分一版 “生产安全版”(用 SSH Key、不明文写密码),或者帮你写一版 英文 README 方便放到 GitHub。