docker不停机部署

背景

最近做大疆项目时,后台更新部署时,机场和无人机就会掉线。设备自动重连注册时间比较长,应用长时间不可用。所以需要灰色发布服务。docker-compose的swarm模式可解决此问题。

服务构建脚本Dockerfile

bash 复制代码
# 使用官方Java基础镜像(推荐选择Alpine轻量版)
FROM openjdk:17-jdk-alpine
# 更新时区
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone \
# 设置工作目录
WORKDIR /app

# 将JAR文件复制到容器中(注意替换为你的JAR文件名)
COPY ./*.jar /app/
COPY ./lib/*.jar /app/lib/

ARG JAVA_OPTS="-server -Xmx512m -Xms512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256M -Xss256k -XX:+DisableExplicitGC -XX:+UseG1GC -XX:LargePageSizeInBytes=128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps/oom_dump.hprof -Djava.security.egd=file:/dev/./urandom"

RUN mkdir -p /app/dumps
RUN mkdir -p /app/logs
# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/${project.build.finalName}.jar > /app/logs/${project.build.finalName}.log 2>&1"]

容器编排配置docker-compose.yml

下面的内容没有一行是多余的,修改时要慎重考虑

bash 复制代码
version: '3.8'
networks:
  ${project.artifactId}-stack-proxy-tier: # 自定义的网络名称(可任意定义,但是需要提前创建)
    external: true

services:
  ${project.artifactId}: #docker应用服务名称,不能包含非法字符比如点
    image: ${project.build.finalName}:${project.version}
    deploy:
      replicas: 2  # 至少保持2个副本
      update_config:
        parallelism: 1    # 每次更新1个实例
        delay: 10s        # 新实例启动间隔
        order: start-first # 先启动新实例,再停止旧实例
      restart_policy:
        condition: any
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://localhost:23111/actuator/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 20s
    volumes:
        - ./${project.build.finalName}.jar:/app/${project.build.finalName}.jar
        - ./lib:/app/lib
    environment:
      - VIRTUAL_HOST=192.168.1.4 # ip或者域名
      - VIRTUAL_PORT=23111 # 应用启动的端口
    networks:
      - ${project.artifactId}-stack-proxy-tier

  # 配置Nginx反向代理
  nginx:
    image: jwilder/nginx-proxy #专应用docker负载均衡、服务发现额镜像,功能非常强大
    environment:
      - TZ=Asia/Shanghai
      - HTTP_CHECK=/"actuator/health"
    ports:
      - "22011:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - ${project.artifactId}-stack-proxy-tier
    depends_on:
      - ${project.artifactId}

启动脚本restart

linux

bash 复制代码
#!/bin/bash

# 设置脚本在遇到错误时立即退出
set -e

init(){
    docker swarm init
    # 检查Overlay网络是否存在‌:ml-citation{ref="3,4" data="citationList"}
    if [[ -z $(docker network ls --filter name=^${project.artifactId}-stack-proxy-tier$ --format '{{.Name}}') ]]; then
        echo "Creating overlay network..."
        docker network create --driver overlay --attachable ${project.artifactId}-stack-proxy-tier
    else
        echo "Network ${project.artifactId}-stack-proxy-tier already exists, skipping creation."
    fi
  deploy
}

restart(){
  deploy
}

deploy() {
  # 构建Docker镜像
  docker build -t ${project.build.finalName}:${project.version} .
  # 部署Docker堆栈
  docker stack deploy --detach=false -c docker-compose.yml ${project.artifactId}-stack
}

remove() {
  #删除堆栈
  docker stack rm ${project.artifactId}-stack
  #删除网络
  docker network rm ${project.artifactId}-stack-proxy-tier
}

case $1 in
          init) init;;
          restart)  restart;;
          remove)  status;;
              *)  echo "require init|restart|remove";;
esac

windows

bash 复制代码
@echo off
setlocal enabledelayedexpansion

if "%1"=="init" goto init
if "%1"=="restart" goto restart
if "%1"=="remove" goto remove
echo require init^|restart^|remove
exit /b 1

:init
docker swarm init
for /f "tokens=*" %%i in ('docker network ls --filter name^^=^${project.artifactId}-stack-proxy-tier$ --format "{{.Name}}"') do set network=%%i
if "!network!"=="" (
    echo Creating overlay network...
    docker network create --driver overlay --attachable ${project.artifactId}-stack-proxy-tier
) else (
    echo Network ${project.artifactId}-stack-proxy-tier already exists, skipping creation.
)
goto deploy

:restart
goto deploy

:deploy
docker build -t ${project.build.finalName}:${project.version} .
docker stack deploy --detach=false -c docker-compose.yml ${project.artifactId}-stack
exit /b 0

:remove
docker stack rm ${project.artifactId}-stack
docker network rm ${project.artifactId}-stack-proxy-tier
exit /b 0

整合maven

上面脚本配置中的类似${project.build.finalName}变量是需要maven在构建时替换的。

resources进行替换,打包工具我用的maven-assembly-plugin,根据项目自行替换

bash 复制代码
<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/assembly/docker</directory>
                <includes>
                    <include>docker-compose.yml</include>
                    <include>Dockerfile</include>
                    <include>restart.sh</include>
                    <include>restart.bat</include>
                    <include>nginx.conf</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugin>
                <!-- 配置打包文件 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <descriptors>
                        <descriptor>src/assembly/distribution.xml</descriptor>
                    </descriptors>
                    <finalName>${project.artifactId}-${project.version}</finalName>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <!-- 配置启动入口 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.dji.sample.CloudApiSampleApplication</mainClass>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib</classpathPrefix>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            </plugins>
    </build>

我所有的脚本以及配置文件是放在src/assembly/docker下的

maven构建配置distribution.xml

bash 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<assembly
	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
	<id>package</id>
	<formats>
		<format>zip</format>
	</formats>
	<includeBaseDirectory>false</includeBaseDirectory>
	<fileSets>
		<fileSet>
			<directory>target</directory>
			<outputDirectory>./</outputDirectory>
			<includes>
				<include>*.jar</include>
			</includes>
		</fileSet>
		<fileSet>
			<directory>target/classes</directory>
			<outputDirectory>./</outputDirectory>
			<includes>
				<include>docker-compose.yml</include>
				<include>Dockerfile</include>
				<include>restart.sh</include>
				<include>restart.bat</include>
				<include>nginx.conf</include>
			</includes>
		</fileSet>
	</fileSets>

	<dependencySets>
		<dependencySet>
			<outputDirectory>lib</outputDirectory>
		</dependencySet>
	</dependencySets>
</assembly>

docker容器启动

首次部署命令

bash 复制代码
restart.bat init

重启命令

bash 复制代码
restart.bat restart

删除命令(仅限调试)

bash 复制代码
restart.bat remove

修改镜像版本

每次更新时需要修改项目的版本号${revision}

相关推荐
Ronin-Lotus1 小时前
上位机知识篇---Linux特殊功能文件
linux·运维·服务器·特殊功能寄存器
热心市民运维小孙2 小时前
基于HAproxy搭建负载均衡
运维·junit·负载均衡
Zucker n3 小时前
Ubuntu本地部署Open manus(完全免费可用)
linux·运维·ubuntu
zym大哥大4 小时前
Linux进程信号二
linux·运维·服务器
全是操作5 小时前
k8s scheduler源码阅读
云原生·容器·kubernetes
call_me_wangcheng6 小时前
Ubuntu用户安装cpolar内网穿透
linux·运维·ubuntu
小杨4046 小时前
springboot框架项目应用实践四(日志)
运维·spring boot·后端
人间打气筒(Ada)6 小时前
负载均衡集群和高可用集群
运维·负载均衡
obboda6 小时前
Docker基础入门
运维·docker·云原生·容器·eureka
me8326 小时前
【Linux docker】关于docker启动出错的解决方法。
java·linux·docker