golang+docker部署

推荐使用第二种方式!!!

推荐使用第二种方式!!!

推荐使用第二种方式!!!

1. 第一种方式本机编译golang可执行文件

1. 本机编译golang可执行文件

2. 构建docker镜像,删除容器,启动最新版本容器

3. sh脚本如下(启动报错可能是数据库、redis等地址用的127.0.0.1,可以配置host

#!/bin/sh
name=$1
version=$2

logs="/apps/$name/logs"
conf="/apps/$name/config"
if [ ! -d $logs  ];then
  mkdir -p $logs
fi
if [ ! -d $conf  ];then
  mkdir -p $conf
fi

go build main.go
docker build -f Dockerfile3 -t $name:$version .
rm -f main
docker rm $name -f
# --add-host=myhost:192.168.1.100
docker run --name $name -p 8080:8080 -v $logs:/apps/logs -v $conf:/apps/config -d $name:$version

config目录下的配置文件记得copy一份到挂载目录

cp ./config/* /apps/xxxx/config

dockerfile如下

# 表示依赖 alpine 最新版
FROM alpine:latest
# 下载Alpine镜像很慢有时候会卡住,因为使用的资源默认是境外服务器,将境外服务器替换为国内服务器即可
RUN set -eux && sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
LABEL MAINTAINER="Joker"
LABEL EMAIL="[email protected]"
ENV VERSION 1.0

# 在容器根目录 创建一个 apps 目录
WORKDIR /apps

# 挂载容器目录
VOLUME ["/apps/config"]
VOLUME ["/apps/logs"]

# 可执行文件拷贝当前目录下
ADD main /apps/main

# 拷贝配置文件到容器中
COPY config /apps/config
# COPY logs /apps/logs

# 设置时区为上海
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

# 设置时区(以 Asia/Shanghai 为例)
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai

# 设置编码
ENV LANG C.UTF-8

# 暴露端口
EXPOSE 8080

# 运行golang程序的命令
CMD ["./main"]

2. 第二种方式,使用容器编译

此方式的好处是本机不需要golang环境,而且打包出来的容器大小和第一种方式一样

sh脚本如下

#!/bin/sh
set -x

name=$1
version=$2
mode=$3
logs="/tmp/apps/$name/logs"
conf="/tmp/apps/$name/config"

if [ ! -d $logs  ];then
  sudo mkdir -p $logs
fi
if [ ! -d $conf  ];then
  sudo mkdir -p $conf
fi

if [ -z "$name" ] || [ -z "$version" ] || [ -z "$mode" ]; then
  echo "请依次输入 项目名称 版本号 部署环境"
  exit 1
fi

# git操作
sudo chmod 777 -R .git/
git pull

# go build main.go
sudo docker build -f Dockerfile3 -t $name:$version .
# 判断是否存在名为 "xxx" 的容器
if sudo docker ps -a --format '{{.Names}}' | grep -q "$name"; then
  # 停止并删除容器
  sudo docker stop "$name"
  sudo docker rm "$name" -f
  echo "${name}容器已停止"
fi
# 获取当前版本镜像的 ID
current_image_id=$(sudo docker images -q $name:$version)
# 之前版本镜像都删掉
sudo docker images | awk -v name="$name" -v version="$version" -v current_image_id="$current_image_id" '$1 == name && $2 != version && $3 != current_image_id { print $3 }' | xargs -I {} sudo docker rmi {}

# # 之前版本镜像也都删掉
# if sudo docker images -q $name; then
#   sudo docker rmi $(docker images -q $name)
#   echo "${name}镜像已删除"
# fi
# conf暂时不挂载
sudo docker run --name $name -p 8080:8080 -v $logs:/apps/logs -e Mode="$mode" -d $name:$version
# docker run --name $name -p 8080:8080 -v $logs:/apps/logs -v $conf:/apps/config -d $name:$version
# docker run --name $name -p 8080:8080 \
# --mount type=bind,source=$logs,target=/apps/logs \
# --mount type=bind,source=$conf,target=/apps/config \
# -d $name:$version

dockerfile如下

FROM golang:1.20.5-alpine as builder
# 这里在docker里也使用go module的代理服务
ENV GOPROXY https://goproxy.cn,direct
ENV GO111MODULE on
# 在容器根目录 创建一个 apps 目录
RUN mkdir -p /apps
# 设置工作目录
WORKDIR /apps
COPY . /apps
## 编译
RUN go build -o /apps/main ./main.go

# ============================================================
# ============================================================
# ======================= 运行应用 ============================
# ============================================================
# ============================================================

# 表示依赖 alpine 最新版
FROM alpine:latest
# 下载Alpine镜像很慢有时候会卡住,因为使用的资源默认是境外服务器,将境外服务器替换为国内服务器即可
RUN set -eux && sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories
LABEL MAINTAINER="Joker"
LABEL EMAIL="[email protected]"
ENV VERSION 1.0
# 在容器根目录 创建一个 apps 目录
RUN mkdir -p /apps
# 设置工作目录
WORKDIR /apps
# 挂载容器目录
VOLUME ["/apps/config"]
VOLUME ["/apps/logs"]

# 可执行文件拷贝当前目录下
COPY --from=builder /apps/main /apps/main

# 拷贝配置文件到容器中
COPY --from=builder /apps/config /apps/config
# COPY --from=builder logs /apps/logs

# 设置时区为上海
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

# 设置时区(以 Asia/Shanghai 为例)
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
# 设置编码
ENV LANG C.UTF-8

# 暴露端口
EXPOSE 8080

# 运行golang程序的命令
CMD ["./main"]

sh脚本太多了怎么办,那就放到一个shell里面

#!/bin/bash

# cd ../entry_manage

function show_help {
  echo "Usage: $0 [OPTIONS]"
  echo "Options:"
  echo "  --mode=   Set the mode (local, dev, test, prod)"
  echo "  --v=   Set the version number"
  echo "  --name=   Set the project name"
  echo "  --help          Show this help message"
}


# 保存输入的参数
args=("$@")
# 使用 shift 命令去除已处理的位置参数
shift
# 处理命令行参数
for ((i = 0; i < "${#args[@]}"; i++)); do
  case "${args[$i]}" in
    --mode=*|-mode=*)
      mode="${args[$i]#*=}"
      ;;
    --mode|-mode)
        mode="${args[$((i+1))]}"
      ;;
    --v=*|-v=*)
      version="${args[$i]#*=}"
      ;;
    --v|-v)
      version="${args[$((i+1))]}"
      ;;
    --name=*|-name=*)
      name="${args[$i]#*=}"
      ;;
    --name|-name)
      name="${args[$((i+1))]}"
      ;;
    --help)
      show_help
      exit 0
      ;;
  esac
done

if [ -z "$name" ]; then
  echo "请输入项目名称"
  exit 1
fi

# 检查 mode 是否合法
valid_modes=("" "local" "dev" "test" "prod")
valid=false
for valid_mode in "${valid_modes[@]}"; do
  if [ "$mode" = "$valid_mode" ]; then
    valid=true
    break
  fi
done

# 如果 mode 不在合法的模式值中,则输出错误信息
if ! $valid; then
  echo "mode值只能是:空值 local, dev, test, prod."
  exit 1
fi

logs="/apps/$name/log"
conf="/apps/$name/config"
if [ ! -d $logs ]; then
  sudo mkdir -p $logs
fi
if [ ! -d $conf ]; then
  sudo mkdir -p $conf
fi

# git操作
echo "更新代码..."
# sudo chmod 777 -R .git/
# git pull

function setVersoin {
  # 获取上一个镜像版本
  previous_version=$(sudo docker images | awk '$1 == "'${name}'" && $2 != "latest" {print $2}' | sort -rV | head -n 1)

  if [ -z "$previous_version" ]; then
    # 如果没有上一个版本,则默认设置为 1.0.0
    version="1.0.0"
  else
    # 去除可能存在的 "v" 字符串
    version_without_v=$(echo "$previous_version" | sed 's/^v//')

    # 将上一个版本的主版本号、次版本号和修订号分离出来
    major=$(echo "$version_without_v" | awk -F'.' '{print $1}')
    minor=$(echo "$version_without_v" | awk -F'.' '{print $2}')
    patch=$(echo "$version_without_v" | awk -F'.' '{print $3}')

    # 递增修订号,如果修订号超过 10,则递增次版本号
    patch=$((patch + 1))
    if [ "$patch" -ge 10 ]; then
      patch=0
      minor=$((minor + 1))
    fi

    # 如果次版本号超过 10,则递增主版本号
    if [ "$minor" -ge 10 ]; then
      minor=0
      major=$((major + 1))
    fi

    # 更新新版本号
    version="$major.$minor.$patch"
  fi
}

if [ -z "$version" ]; then
  setVersoin
fi

echo "项目:${name} 版本:${version}   环境:${mode}"

function deploy1 {
  sudo docker build -f Dockerfile -t $name:$version .
  sudo docker rm $name -f
  sudo docker run --restart=always --name $name -p 8087:8080 -v $logs:/apps/log -e Mode="$mode" -d $name:$version
}

function deploy2 {
  sudo rm -f main
  go build -o main main.go
  CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main main.go
  sudo chown root:root main
  sudo chmod +x main
  sudo docker build -f Dockerfile2 -t $name:$version .
  sudo rm -f main
  sudo docker rm $name -f
  sudo docker run --restart=always --name $name -p 8087:8080 -v $logs:/apps/log -e Mode="$mode" -d $name:$version
}

function deploy3 {
  sudo docker build -f Dockerfile3 -t $name:$version .
  # 判断是否存在名为 "xxx" 的容器
  if sudo docker ps -a --format '{{.Names}}' | grep -q "$name"; then
    # 停止并删除容器
    sudo docker stop "$name"
    sudo docker rm "$name" -f
    echo "${name}容器已停止"
  fi
  # 获取当前版本镜像的 ID
  current_image_id=$(sudo docker images -q $name:$version)
  # 之前版本镜像都删掉
  # sudo docker images | awk -v name="$name" -v version="$version" -v current_image_id="$current_image_id" '$1 == name && $2 != version && $3 != current_image_id { print $3 }' | xargs -I {} sudo docker rmi {}
  # conf暂时不挂载
  sudo docker run --restart=always --name $name -p 8087:8080 -v $logs:/apps/log -e Mode="$mode" -d $name:$version
}

echo "请选择dockerfile:"
echo "1. Dockerfile"
echo "2. Dockerfile2"
echo "3. Dockerfile3"

# 使用 read 命令读取用户输入,并将输入的值赋给变量 choice
read -p "请输入选项的序号: " choice

# 根据用户输入的值进行不同的处理
case $choice in
1) deploy1 ;;
2) deploy2 ;;
3) deploy3 ;;
*) echo "无效的选项。" ;;
esac

使用sh脚本

# 自动递增版本
./deploy.sh --name xxx -mode=local

# 指定镜像版本打包
./deploy.sh --name xxx -v=1.0

# 自动递增版本、不指定环境变量
./deploy.sh --name xxx

# 指定版本、指定环境
./deploy.sh --name xxx -v=1.0 -mode=local

你可能感兴趣的:(docker,golang,容器,ssh)