Skip to the content.

返回

分离式部署

针对单体应用的分离式打包+Docker部署。

各类脚本

有公网情况快速安装基础环境

# 安装Docker
mkdir -p /home/package /home/docker && cd /home/package && \
wget https://download.docker.com/linux/static/stable/x86_64/docker-25.0.4.tgz && \
wget https://raw.githubusercontent.com/yoko-murasame/jeecg-boot/yoko-3.4.3last/docs/DevOps/shell/docker-install.sh && \
chmod +x docker-install.sh && sh -x docker-install.sh

# 安装基础环境
wget https://raw.githubusercontent.com/yoko-murasame/jeecg-boot/yoko-3.4.3last/docs/DevOps/shell/docker-start-multi-container.sh && \
chmod +x docker-start-multi-container.sh && \
vim docker-start-multi-container.sh
# 各种参数目录需要自行修改,pg镜像也需要自己准备

直接部署方式

Jar包运行脚本: start.sh

# 先修改脚本配置, 详情见脚本内容
#启动
sh start.sh start
#停止
sh start.sh stop
#重启
sh start.sh restart
#查看状态
sh start.sh status

Docker部署方式

Dockerfile:

Docker方式部署:

# 防火墙
firewall-cmd --zone=public --add-port=8888/tcp --permanent && firewall-cmd --reload

## 单体应用分离式打包
# 构建容器
docker build -t app-image -f Dockerfile_Separate .
docker save -o ./app-image app-image
# 第一次载入镜像
docker load -i app-image
# 启动
docker run -di --name app-container --restart=unless-stopped -p 9999:8888 -v /application/app:/app -v /application/upFiles:/opt/upFiles app-image

## 超图依赖的应用打包
https://blog.csdn.net/SerikaOnoe/article/details/130337989

如何打包动态链接库?

有时候,项目有Java调用native方法的需求,这时需要依赖.so文件,参考Dockerfile配置:

FROM anapsix/alpine-java:8_server-jre_unlimited

MAINTAINER yoko

# root用户权限
USER root

# 通过镜像源安装tzdata修正容器时区问题
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && apk add --no-cache tzdata
# 时区(无论是否安装tzdata,JDK时区设置下面软链接后,都会更正,但是tzdata不安装会让容器时区不生效)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 字体(解决流程图部署乱码,请设置好字体目录位置)
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && apk update && apk --no-cache --purge -U upgrade
RUN apk add --no-cache --purge -uU ttf-dejavu fontconfig && rm -rf /var/cache/apk/* && mkdir -p /usr/share/fonts/new/
# 字体直接打入包中
COPY fonts/*.ttf /usr/share/fonts/new/
RUN fc-cache
# 或者字体挂载出来
# VOLUME /usr/share/fonts/new/

# 文件目录
RUN mkdir -p /opt/upFiles && mkdir -p /opt/webapp

# 工作目录
RUN mkdir -p /so-demo
WORKDIR /so-demo

# 动态链接库.so文件目录
RUN mkdir -p /LD_LIBRARY
# 挂载动态链接库(可选)
VOLUME /LD_LIBRARY
# 或者直接加入容器
# ADD ./lib/path/to/so/* /LD_LIBRARY/
# 动态链接库环境变量,会自动拼接到系统上下文
ENV LD_LIBRARY_PATH /LD_LIBRARY:/opt/jdk1.8.0_202/jre/lib/amd64:/opt/jdk1.8.0_202/jre/lib/amd64/server

EXPOSE 7777

ADD ./target/so-demo.jar ./

CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar so-demo.jar

参考启动命令:

docker build -t so-demo .
# --privileged高特权、--user=root以root用户启动
docker run -di --name so-demo --privileged --user=root --restart=unless-stopped -p 7788:7777 -v /path/to/so:/LD_LIBRARY so-demo

修改历史

归档

修改Docker数据默认存储路径

在Linux中,Docker的数据默认存储在/var/lib/docker目录下,包括镜像、容器、卷和网络等数据。如果想将Docker的数据存储在其他磁盘上,可以通过修改Docker的配置文件来实现。

输入 docker info 查看配置 Docker Root Dir,可以看到Docker的数据存储在/var/lib/docker目录下:

首先停止Docker服务:

sudo systemctl stop docker

然后,将/var/lib/docker目录下的数据移动到新的磁盘位置,例如/new_disk/docker

sudo mv /var/lib/docker /new_disk/docker

接下来,你需要修改Docker的配置文件。在/etc/docker/daemon.json文件中添加data-root配置项,指向新的磁盘位置:

{
  "registry-mirrors": ["http://hub-mirror.c.163.com"],
  "data-root": "/new_disk/docker"
}

如果/etc/docker/daemon.json文件不存在,你需要创建它。

最后,重新启动Docker服务:

sudo systemctl start docker

现在,Docker的数据应该存储在新的磁盘位置上了。

Redis部署

# 拉取
docker pull redis
# 下载镜像
docker save -o /mnt/d/redis-image redis:latest
# 推送镜像到服务器
# 加载镜像
docker load -i redis-image
# 查看已有镜像
docker images
# 启动,端口63791,密码123456 配置映射 -v /home/redis/redis.conf:/etc/redis/redis.conf
docker run -di --restart=unless-stopped --name=redis \
-p 63791:63791 \
-v /home/redis/data:/data \
redis:latest --requirepass "123456" --port "63791" --appendonly "yes";
# 进入容器
docker exec -it redis /bin/bash
# 测试启动
redis-cli -h 127.0.0.1 -p 63791
auth 123456
set name test
get name
# 通过别的服务器连接测试
curl 127.0.0.1:63791
# curl: (52) Empty reply from server 即连接是通的

基础容器整合脚本

启动:redis、postgre-14、nginx

#!/bin/bash

# 配置容器和镜像名称
container_names=("redis" "postgre-14" "nginx")
image_names=("redis:latest" "postgres-14-zhparser-postgis:1.0" "nginx:latest")

# 创建容器命令数组
create_container_cmds=(
  "docker run -di --restart=unless-stopped -p 63791:63791 -v /home/redis/data:/data --name ${container_names[0]} ${image_names[0]} --requirepass "yoko@123" --port "63791" --appendonly "yes""
  "docker run -di -e POSTGRES_PASSWORD=yoko@123 -e PGDATA=/var/lib/postgresql/data/pgdata -p 54321:5432 -v /home/postgres/data1:/var/lib/postgresql/data/pgdata --name ${container_names[1]} ${image_names[1]}"
  "docker run -di --network=host -v /home/nginx/nginx.conf:/etc/nginx/nginx.conf -v /home/nginx/log:/var/log/nginx -v /home/nginx/conf.d:/etc/nginx/conf.d -v /home/nginx/html:/etc/nginx/html --name ${container_names[2]} ${image_names[2]}"
)

# 启动容器函数
start_container() {
    local container_name="$1"
    echo "启动 $container_name 容器..."
    docker start "$container_name"
    echo "$container_name 容器已启动。"
}

# 停止容器函数
stop_container() {
    local container_name="$1"
    echo "停止 $container_name 容器..."
    docker stop "$container_name"
    echo "$container_name 容器已停止。"
}

# 重启容器函数
restart_container() {
    local container_name="$1"
    echo "重启 $container_name 容器..."
    docker restart "$container_name"
    echo "$container_name 容器已重启。"
}

# 检查容器状态 -f '\{\{.State.Status\}\}'
container_status() {
    local container_name="$1"
    # docker container inspect --format='' $container_name
    docker inspect -f '' "$container_name" 2>/dev/null
}

# 根据用户输入的参数调用相应的功能
if [ "$1" == "start" ]; then
    # 启动容器
    for ((i=0; i<${#container_names[@]}; i++)); do
        container_name="${container_names[i]}"
        image_name="${image_names[i]}"
        create_container_cmd="${create_container_cmds[i]}"
        
        if [ -z "$(container_status "$container_name")" ]; then
            echo "创建 $container_name 容器..."
            eval "$create_container_cmd"
            echo "$container_name 容器已创建并启动。"
        elif [ "$(container_status "$container_name")" == "exited" ]; then
            start_container "$container_name"
        elif [ "$(container_status "$container_name")" == "running" ]; then
            echo "$container_name 容器已经在运行中。"
        fi
    done
elif [ "$1" == "stop" ]; then
    # 停止容器
    for container_name in "${container_names[@]}"; do
        if [ -n "$(container_status "$container_name")" ] && [ "$(container_status "$container_name")" == "running" ]; then
            stop_container "$container_name"
        else
            echo "$container_name 容器未运行。"
        fi
    done
elif [ "$1" == "restart" ]; then
    # 重启容器
    for container_name in "${container_names[@]}"; do
        if [ -n "$(container_status "$container_name")" ] && [ "$(container_status "$container_name")" == "running" ]; then
            restart_container "$container_name"
        else
            echo "$container_name 容器未运行,无法重启。"
        fi
    done
else
    echo "无效的参数。请使用 'start'、'stop' 或 'restart'。"
fi

Linux Docker离线安装脚本

一键脚本

目录结构:

/
├─home
│  ├─package 安装包路径
│  │  ├─docker-20.tgz 安装包
│  │  ├─docker-install.sh 安装脚本
│  ├─docker 应用安装路径(存储各种镜像、容器等数据)

脚本:

#!/bin/bash

#安装包路径 https://download.docker.com/linux/static/stable/x86_64/
package_path="/home/package"
#应用安装路径(存储各种镜像、容器等数据,默认docker的存储路径为/data/docker0)
install_path="/home/docker"
#docker安装包名
docker_inatall_name=$(find . -name "*docker*.tgz" | grep -oE '[^/]+\.tgz$')
 
# 检查是否有root权限
if [ "$EUID" -ne 0 ]
  then echo "请使用root权限运行此脚本"
  exit
fi
 
cd $package_path
 
# 安装docker
if command -v docker &> /dev/null; then
    echo "----------Docker 已经安装----------"
else
	DOCKER_FILE_PATH="$install_path/docker"
	echo "----------开始安装docker----------"
	cd $package_path
	tar -xvf $docker_inatall_name -C $package_path
	cp docker/* /usr/bin/
	rm -rf $package_path/docker
	echo "[Unit]" >> /etc/systemd/system/docker.service
	echo "Description=Docker Application Container Engine" >> /etc/systemd/system/docker.service
	echo "Documentation=https://docs.docker.com" >> /etc/systemd/system/docker.service
	echo "After=network-online.target firewalld.service" >> /etc/systemd/system/docker.service
	echo "Wants=network-online.target" >> /etc/systemd/system/docker.service
	echo "" >> /etc/systemd/system/docker.service
	echo "[Service]" >> /etc/systemd/system/docker.service
	echo "Type=notify" >> /etc/systemd/system/docker.service
	echo "ExecStart=/usr/bin/dockerd --graph $DOCKER_FILE_PATH" >> /etc/systemd/system/docker.service
	echo "ExecReload=/bin/kill -s HUP \$MAINPID" >> /etc/systemd/system/docker.service
	echo "LimitNOFILE=infinity" >> /etc/systemd/system/docker.service
	echo "LimitNPROC=infinity" >> /etc/systemd/system/docker.service
	echo "LimitCORE=infinity" >> /etc/systemd/system/docker.service
	echo "TimeoutStartSec=0" >> /etc/systemd/system/docker.service
	echo "Delegate=yes" >> /etc/systemd/system/docker.service
	echo "KillMode=process" >> /etc/systemd/system/docker.service
	echo "Restart=on-failure" >> /etc/systemd/system/docker.service
	echo "StartLimitBurst=3" >> /etc/systemd/system/docker.service
	echo "StartLimitInterval=60s" >> /etc/systemd/system/docker.service
	# Reload systemd daemon and restart Docker
	echo "----------注册docker服务----------"
	chmod +x /etc/systemd/system/docker.service
	systemctl daemon-reload
	echo "----------启动docker服务----------"
	systemctl start docker.service
	echo "----------设置服务开机自启----------"
	systemctl enable docker.service
	echo "----------docker安装完毕----------"
fi

执行脚本:

cd /home
sh -x docker-install.sh

其他配置:

# 以下配置会增加一段自定义内网 IPv6 地址,开启容器的 IPv6 功能,以及限制日志文件大小,防止 Docker 日志塞满硬盘
sudo cat > /etc/docker/daemon.json <<EOF
{
    "log-driver": "json-file",
    "log-opts": {
        "max-size": "20m",
        "max-file": "3"
    },
    "ipv6": true,
    "fixed-cidr-v6": "fd00:dead:beef:c0::/80",
    "experimental":true,
    "ip6tables":true
}
EOF

Linux Docker离线安装步骤

参考:这里

1)下载docker官方离线包

安装包官方地址:https://download.docker.com/linux/static/stable/x86_64/

2)解压安装包

tar -zxvf docker-20.10.8.tgz
sudo cp docker/* /usr/bin/

3)注册docker为service服务

默认docker的存储路径为/data/docker0
如需修改请修改docker.service
ExecStart=/usr/bin/dockerd --graph=/data/docker0

在/etc/systemd/system/目录下新增docker.service文件

# sudo vi /etc/systemd/system/docker.service

输入内容
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
  
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
# 如果有搭建私有镜像仓库,--insecure-registry设置为私有镜像仓库地址。
ExecStart=/usr/bin/dockerd --graph /home/docker0
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
  
[Install]
WantedBy=multi-user.target

4)启动docker

# 赋予docker.service 执行权限
chmod +x /etc/systemd/system/docker.service
# 重载配置文件以生效
systemctl daemon-reload
# 启动docker
sudo systemctl start docker
# 设置服务开机自启
sudo systemctl enable docker.service
# 查看服务状态
systemctl status docker

5)普通用户执行dockers命令

用户组配置文件:/ect/group 即用户组的所有信息都存放在此文件中。

# 新建用户组 docker,如果用户组已经存在则跳过
sudo groupadd docker
# 将 appuser用户添加到 docker 组
gpasswd -a appuser docker
# 更新用户组
newgrp docker
# 修改docker.sock用户组权限
chown root:docker /var/run/docker.sock
# 切换普通用户,验证docker命令是否能执行
su - admin
docker version

Docker多容器启动脚本

#!/bin/bash

# 配置容器和镜像名称
container_names=("redis-test" "mysql-test")
image_names=("redis" "mysql")

# 创建容器命令数组
create_container_cmds=("docker run -d --name ${container_names[0]} ${image_names[0]}"
                      "docker run -d --name ${container_names[1]} ${image_names[1]}")

# 启动容器函数
start_container() {
    local container_name="$1"
    echo "启动 $container_name 容器..."
    docker start "$container_name"
    echo "$container_name 容器已启动。"
}

# 停止容器函数
stop_container() {
    local container_name="$1"
    echo "停止 $container_name 容器..."
    docker stop "$container_name"
    echo "$container_name 容器已停止。"
}

# 重启容器函数
restart_container() {
    local container_name="$1"
    echo "重启 $container_name 容器..."
    docker restart "$container_name"
    echo "$container_name 容器已重启。"
}

# 检查容器状态
container_status() {
    local container_name="$1"
    docker inspect -f '' "$container_name" 2>/dev/null
}

# 根据用户输入的参数调用相应的功能
if [ "$1" == "start" ]; then
    # 启动容器
    for ((i=0; i<${#container_names[@]}; i++)); do
        container_name="${container_names[i]}"
        image_name="${image_names[i]}"
        create_container_cmd="${create_container_cmds[i]}"
        
        if [ -z "$(container_status "$container_name")" ]; then
            echo "创建 $container_name 容器..."
            eval "$create_container_cmd"
            echo "$container_name 容器已创建并启动。"
        elif [ "$(container_status "$container_name")" == "exited" ]; then
            start_container "$container_name"
        elif [ "$(container_status "$container_name")" == "running" ]; then
            echo "$container_name 容器已经在运行中。"
        fi
    done
elif [ "$1" == "stop" ]; then
    # 停止容器
    for container_name in "${container_names[@]}"; do
        if [ -n "$(container_status "$container_name")" ] && [ "$(container_status "$container_name")" == "running" ]; then
            stop_container "$container_name"
        else
            echo "$container_name 容器未运行。"
        fi
    done
elif [ "$1" == "restart" ]; then
    # 重启容器
    for container_name in "${container_names[@]}"; do
        if [ -n "$(container_status "$container_name")" ] && [ "$(container_status "$container_name")" == "running" ]; then
            restart_container "$container_name"
        else
            echo "$container_name 容器未运行,无法重启。"
        fi
    done
else
    echo "无效的参数。请使用 'start'、'stop' 或 'restart'。"
fi

Docker单容器启动脚本

#!/bin/bash

# 配置容器和镜像名称
container_name="redis-test"
image_name="redis"

# 创建容器命令
create_container_cmd="docker run -d --name $container_name $image_name"

# 启动容器函数
start_container() {
    echo "启动 $container_name 容器..."
    docker start "$container_name"
    echo "$container_name 容器已启动。"
}

# 停止容器函数
stop_container() {
    echo "停止 $container_name 容器..."
    docker stop "$container_name"
    echo "$container_name 容器已停止。"
}

# 重启容器函数
restart_container() {
    echo "重启 $container_name 容器..."
    docker restart "$container_name"
    echo "$container_name 容器已重启。"
}

# 检查容器状态
container_status=$(docker inspect -f '' "$container_name" 2>/dev/null)

# 根据用户输入的参数调用相应的功能
if [ "$1" == "start" ]; then
    # 启动容器
    if [ -z "$container_status" ]; then
        echo "创建 $container_name 容器..."
        eval "$create_container_cmd"
        echo "$container_name 容器已创建并启动。"
    elif [ "$container_status" == "exited" ]; then
        start_container
    elif [ "$container_status" == "running" ]; then
        echo "$container_name 容器已经在运行中。"
    fi
elif [ "$1" == "stop" ]; then
    # 停止容器
    if [ -n "$container_status" ] && [ "$container_status" == "running" ]; then
        stop_container
    else
        echo "$container_name 容器未运行。"
    fi
elif [ "$1" == "restart" ]; then
    # 重启容器
    if [ -n "$container_status" ] && [ "$container_status" == "running" ]; then
        restart_container
    else
        echo "$container_name 容器未运行,无法重启。"
    fi
else
    echo "无效的参数。请使用 'start'、'stop' 或 'restart'。"
fi

Linux分配磁盘空间

当我们有多块磁盘时,可能需要将不同的目录挂载到不同磁盘上,这时需要通过重新分配目录挂载实现,这里以 /root 目录为例:

首先查看 /root 目录的挂载情况:

# 查看目录占用情况
du -sh /root
------------
5.0G    /root

# 查看/root挂载情况
df -Th /root
------------
/dev/vda1      xfs   25G  5.0G  20G  20% /root

# 查看所有磁盘空间
df -Th
------------
/dev/vda1               xfs       25G   5.0G  20G   20% /boot
/dev/vdb1               xfs       200G  0.0G  200G   0% /root

可以看到磁盘 /dev/vdb1 是空闲的,而当前 /root 目录挂载到了 /dev/vda1 磁盘,因此我们需要进行修改。

要将空闲空间分配给 /root 目录,按照以下步骤进行操作:

1)首先备份重要的数据。在进行分区和文件系统操作之前,备份是非常重要的,以防止数据丢失。

2)将空闲空间挂载到一个临时目录:创建一个临时目录,例如 /mnt/temp,并将空闲空间 /dev/vdb1 挂载到该目录:

mkdir /mnt/temp
mount /dev/vdb1 /mnt/temp

3)复制 /root 目录的内容:使用 rsync 命令将 /root 目录的内容复制到临时目录:

rsync -avxHAX /root/ /mnt/temp/

这将确保所有文件和权限都被正确复制到临时目录。

4)卸载原来的 /root 目录:卸载原来的 /root 目录,确保没有其他进程或服务正在使用该目录:

umount /root

5)挂载空闲空间到 /root 目录:将空闲空间重新挂载到 /root 目录:

mount /dev/vdb1 /root

6)更新 /etc/fstab 文件:打开 /etc/fstab 文件,并将原来指向 /root 的行修改为:

# ext4是文件系统类型,需要根据实际修改
/dev/vdb1  /root  ext4  defaults  0  0
# 实际可能长这样:/data目录是这个磁盘原先挂载的目录,对应的文件系统类型为xfs
/dev/vdb1 /data xfs defaults 0 0

保存文件并关闭。

7)重新启动系统:为了确保所有更改生效,重新启动系统:

reboot

系统重启后,会看到 /root 目录现在位于空闲空间 /dev/vdb1 上。