2025-11-28 15:44:02 +08:00
2025-11-28 15:39:54 +08:00
2025-11-28 15:43:53 +08:00

Docker 镜像一键构建 & 远程部署脚本说明

脚本文件:docker_deplay.sh 作用:在本地构建 Docker 镜像 → 打包为 tar → 上传到远程服务器 → 在服务器上停止旧容器并启动新容器支持多架构AMD64 / ARM64与“仅上传”模式。


1. 功能概述

这个脚本主要解决的一件事:

一条命令完成从本地构建到服务器部署的全流程。

包含步骤:

  1. 检查本地依赖(dockersshpass

  2. 按指定架构构建 Docker 镜像(amd64arm64

  3. 导出为 xxx.tar 文件

  4. 使用 scp 上传 tar 到服务器 /tmp/

  5. 在服务器上:

    • 停止并删除旧容器
    • 删除旧镜像
    • docker load 导入新的 tar 镜像
    • 通过 docker run 启动新容器
    • 清理 /tmp 中的临时 tar
  6. 输出访问地址和部署信息


2. 运行环境要求

本地机器(执行脚本的地方)

  • 操作系统Linux / macOS支持 Bash

  • 已安装:

    • docker(且已启动)

    • docker buildxDocker 19.03+ 一般自带)

    • sshpass

      • macOS: brew install sshpass
      • Ubuntu: sudo apt-get install sshpass

远程服务器

  • 已安装:

    • docker
  • 当前用户具备 sudo 权限(脚本中使用了 sudo docker ...


3. 快速开始(最简用法)

  1. 把脚本放到项目根目录(有 Dockerfile 的目录)

  2. 修改脚本顶部“配置变量”部分为你自己的服务器信息

  3. 给脚本执行权限:

    chmod +x docker_deplay.sh
    
  4. 直接执行(默认 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.4your.domain.com
SERVER_USER SSH 登录用户名,例如 rootubuntu
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例如 latestv1.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

  1. 如果已有同名 tar 文件,先删除

  2. 使用 docker buildx build 构建并导出镜像:

    docker buildx build \
      --platform $PLATFORM \
      -t "${IMAGE_NAME}:${IMAGE_TAG}" \
      --output type=docker,dest="./${TAR_FILE}" .
    
  3. 构建成功会提示 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

在服务器上执行一段远程脚本:

  1. 若存在同名容器:

    • docker stop CONTAINER_NAME
    • docker rm CONTAINER_NAME
  2. 若存在同名镜像:

    • docker rmi IMAGE_NAME:IMAGE_TAG
  3. docker load -i /tmp/TAR_FILE 导入新镜像

  4. docker run -d -p LOCAL_PORT:CONTAINER_PORT --name CONTAINER_NAME IMAGE_NAME:IMAGE_TAG

  5. 判断容器是否启动成功(通过 docker ps | grep

  6. 清理 /tmp/TAR_FILE

  7. 打印访问地址

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 中先构建,再单独在本地只“上传 + 部署”

  1. 第一步(在 CI 或其他机器完成构建):

    ./docker_deplay.sh -amd
    # 或手动构建得到 epage_server-latest-amd64.tar
    
  2. 以后在你本地,只要本地有这个 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 refusedNo route to host

    • 检查 SERVER_HOSTSERVER_PORT 是否正确
    • 检查服务器安全组 / 防火墙设置
  • 如果报 Permission denied

    • 检查 SERVER_USERSERVER_PASSWORD 是否正确
    • 或考虑改为 SSH 密钥认证

9. 安全建议(可选优化)

目前脚本直接在代码里写了密码并通过 sshpass 使用,适合开发、内网或快速测试环境。更安全的做法:

  • 禁用密码登录,只保留 SSH Key
  • 修改脚本,将 sshpass 部分改为纯 ssh / scp,让系统自动使用私钥
  • 或从环境变量中读取密码,而不是写死在脚本里

如果你愿意,我也可以帮你基于这个脚本再拆分一版 “生产安全版”(用 SSH Key、不明文写密码或者帮你写一版 英文 README 方便放到 GitHub。

Description
docker部署脚本
Readme 33 KiB
Languages
Shell 100%