一、服务器安装docker

Docker 安装命令

# 1. 安装必要的软件包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

# 1.1 这一步如果执行失败,可以尝试替换centos 仓库地址
##### 备份
sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
##### 编辑配置文件
sudo vi /etc/yum.repos.d/CentOS-Base.repo
##### 修改仓库地址为阿里云镜像源
将mirrorlist字段注释掉(如果存在),并添加或修改baseurl字段,指向国内镜像站点的地址。
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra  
baseurl=https://mirrors.aliyun.com/centos/$releasever/os/$basearch/
##### 清理缓存并测试地址
sudo yum clean all  
sudo yum makecache


# 2. 设置镜像源
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 3. 更新 yum 软件包索引
sudo yum makecache fast

# 4. 安装docker CE
## 4.1 目前国内镜像源被封,在安装时会无法下载,需要修改配置文件,执行下面的命令
 vi /etc/docker/daemon.json
## 4.2 插入下面的代码
{ 
"registry-mirrors" : 
[ 
"https://docker.m.daocloud.io", 
"https://docker.jianmuhub.com",
"https://huecker.io",
"https://dockerhub.timeweb.cloud",
"https://dockerhub1.beget.com",
"https://noohub.ru"
] 
}
## 4.3 清理yum 
sudo yum clean all
## 4.4 更新yum 缓存
sudo yum makecache
## 4.5 安装docker CE
sudo yum install -y docker-ce docker-ce-cli

# 5. 启动docker 服务
sudo systemctl start docker

# 6. 设置docker 开机自启动
sudo systemctl enable docker

二、中间件安装

包含Nginx、RabbitMQ、XXL-Job

Nginx 安装

#1 rpm包的获取
wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.20.1-1.el7.ngx.x86_64.rpm

#2 安装
rpm -ivh nginx-1.20.1-1.el7.ngx.x86_64.rpm

#3 查看安装版本
[root@nginx-test app]# nginx -v
nginx version: nginx/1.20.1

#4 查看都指定了哪些参数
[root@nginx-test app]# nginx -V

#5 查看默认安装路径
[root@nginx-test app]# find / -name nginx

#8 设置开机自启
sudo systemctl enable nginx

要使用自定义配置文件启动Nginx,只需完成以下两个步骤:

  1. 创建nginx.conf文件并保存至目标目录
  2. 执行以下启动命令(请将路径替换为实际配置文件位置):
nginx -c /usr/local/nginx/conf/nginx.conf

RabbitMq 安装

# 拉取镜像
docker pull rabbitmq:management

# 创建容器
docker volume create rabbitmq-home
    ## 这个容器的物理位置可以使用 docker volume inspect rabbitmq-home 命令来查看
    ## 一般来说在:/var/lib/docker/volumes/rabbitmq-home/_data

# 使用docker 安装
docker run -id --name=rabbitmq --restart always -v rabbitmq-home:/var/lib/rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=rmq -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq:management    ## 这里将刚才上一步创建的volume容器挂载到docker里,并且使用-p暴露了两个端口,及设定了两个环境变量:
    ## 15672端口:RabbitMQ的管理页面端口
    ## 5672端口:RabbitMQ的消息接收端口
    ## RABBITMQ_DEFAULT_USER环境变量:指定RabbitMQ的用户名,这里我指定为rmq
    ## RABBITMQ_DEFAULT_PASS环境变量:指定RabbitMQ的密码,这里我指定为123456

我的项目中rabbitMQ还需要安装一个插件,才能保证正常运行。

rabbitmq_delayed_message_exchange 插件安装

插件下载地址:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases

# 查看docker中安装的rabbitMq 版本
docker exec -it rabbitMQ容器ID bash
# 查看版本
rabbitmqctl version

# 将刚刚上传的插件拷贝到容器内plugins目录下,rabbit是容器的name,也可以使用容器id
docker cp /root/rabbitmq_delayed_message_exchange-3.13.0.ez rabbitmq:/plugins

# 进入到RabbitMQ容器内部
docker exec -it rabbitmq /bin/bash

# 查看插件是否存在
root@my-rabbit:/# cd plugins
root@my-rabbit:/plugins# ls | grep delay

# 启用插件(注意是在plugins内)
root@my-rabbit:/plugins# rabbitmq-plugins enable rabbitmq_delayed_message_exchange

# 从容器中退出
root@my-rabbit:/plugins# exit

# 重启RabbitMQ容器
docker restart rabbit

Xxl-job 安装命令

# 拉取镜像
docker pull xuxueli/xxl-job-admin:2.4.1

# 查看镜像
docker images

# 创建容器外置宿主机文件目录
mkdir -p /data/xxl-job-admin/data/applogs/xxl-job
mkdir -p /data/xxl-job-admin/tmp

# 创建容器并启动
docker run --name xxl-job-admin --restart=always -e PARAMS="--spring.datasource.url=jdbc:mysql://k8s-bj-test-nodeports.ruijie.com.cn:31585/middleware_data?Unicode=true&characterEncoding=UTF-8 --spring.datasource.username=system --spring.datasource.password=b904d8c987dd49bc9926906eed3323a1 --server.port=8080 --server.servlet.context-path=/xxl-job-admin" -p 8080:8080 -v /tmp:/data/xxl-job-admin/tmp -v /data/xxl-job-admin/data/applogs/xxl-job:/data/applogs/xxl-job -v /data/xxl-job-admin/tmp:/tmp -d xuxueli/xxl-job-admin:2.4.1

上述命令最后创建容器并启动时,将数据库链接地址和账号密码替换为你自己的。

三、应用服务部署

  • 创建DockerFile 文件

FROM openjdk:8-jdk

LABEL maintainer="111(111@ruijie.com.cn)"

# 设置时区(需同时配置系统时区和JVM时区)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone && \
    mkdir -p /opt/projects/ictcloud

WORKDIR /opt/projects/ictcloud

COPY ict-cloud-cms-api.jar cms-api.jar

# 添加JVM时区参数
CMD java -jar -Duser.timezone=Asia/Shanghai \
    -Xms2048m -Xmx2048m -Xss512k \
    -XX:SurvivorRatio=8 -XX:+UseG1GC \
    cms-api.jar

在 Docker 镜像构建过程中设置时区时,如果仅使用 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 命令,可能会出现时间不准确的问题,主要原因和解决方案如下:

  1. 缺少时区配置文件

    • 需要同时配置 /etc/timezone 文件
    • 完整命令示例:
      RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
          && echo "Asia/Shanghai" > /etc/timezone
      

  2. 基础镜像差异

    • 不同 Linux 发行版对时区的处理方式不同
    • 对于 Alpine 镜像需要额外安装 tzdata 包:
      RUN apk add --no-cache tzdata \
          && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
          && echo "Asia/Shanghai" > /etc/timezone
      

  3. 容器与宿主机时间同步

    • 建议在运行容器时挂载宿主机的 /etc/localtime
      docker run -v /etc/localtime:/etc/localtime:ro ...
      

  4. 多阶段构建注意事项

    • 如果在多阶段构建中设置时区,需确保最终阶段也包含时区配置
  5. 应用层时间处理

  • 某些应用(如 Java 应用)可能需要额外配置:
ENV TZ=Asia/Shanghai

最佳实践是在 Dockerfile 中同时设置符号链接和 timezone 文件,并根据实际运行环境考虑是否需要挂载宿主机的时区文件。对于关键业务系统,建议在容器启动时验证系统时间是否正确。

  • 服务打包,将jar包和DockerFile上传到指定的目录下

要将JAR包与Dockerfile分离存放,可通过调整Dockerfile中的COPY指令路径实现。以下是具体实现方式:

示例目录结构:

project/
├── docker/
│   └── Dockerfile
└── target/
    └── app.jar

Dockerfile修改方案:

# 相对路径方案(推荐)
COPY ../target/app.jar /app/app.jar

# 绝对路径方案
COPY /home/user/project/target/app.jar /app/app.jar

构建镜像注意事项:

  • 使用相对路径时,需在项目根目录执行构建命令:
    docker build -f docker/Dockerfile -t myapp .
    

关键说明:

  1. 相对路径中".."表示上级目录
  2. Linux系统使用正斜杠(/)作为路径分隔符
  3. 构建时的工作目录会影响路径解析
  4. 生产环境建议采用明确的路径指定方式

可选替代方案:

  • 通过--build-arg参数动态传递JAR路径
  • 采用多阶段构建,在构建阶段生成JAR包
  • 在CI/CD流程中预先部署JAR文件
  • 构建服务镜像,注意需要切换到DockerFile文件所在的目录下

docker build -t ict-cloud-cms-api::latest
  • 运行容器

docker run -d -p 9000:9000 \
           -e SPRING_CLOUD_NACOS_DISCOVERY_IP=172.16.3.208 \
           -e SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR=172.16.3.208:8848 \
           --name cms-api --restart always ict-cloud-cms-api::latest
  • 检查是否启动,执行命令 docker ps -a

如果觉得每次更新服务都要重新创建镜像,停止服务,启动服务太繁琐。也可以创建一个可执行文件,文件放在与dockerfile 统一目录下。

#!/bin/bash
# 定义服务参数
IMAGE_NAME="ict-cloud-cms-api"
CONTAINER_NAMES=("ict-cloud-cms-api1" "ict-cloud-cms-api2" "ict-cloud-cms-api3" "ict-cloud-cms-api4")
LOG_PATHS=("/home/logs/ict-cloud-cms-api1/logs/" "/home/logs/ict-cloud-cms-api2/logs/" 
           "/home/logs/ict-cloud-cms-api3/logs/" "/home/logs/ict-cloud-cms-api4/logs/")
NACOS_PORTS=("9200" "9201" "9202" "9208")
SERVER_IP="10.44.32.86"
DOCKERFILE_PATH="./Dockerfile"  # 假设Dockerfile在当前目录

# 1. 停止并删除旧容器
echo "正在停止并移除旧容器..."
for name in "${CONTAINER_NAMES[@]}"; do
    docker stop $name 2>/dev/null && docker rm $name 2>/dev/null
done

# 2. 删除旧镜像
echo "正在删除旧镜像..."
docker rmi ${IMAGE_NAME}:latest 2>/dev/null

# 3. 重新构建镜像
echo "正在构建新镜像..."
docker build -t ${IMAGE_NAME}:latest -f ${DOCKERFILE_PATH} .

# 4. 启动新容器
echo "正在启动新容器..."
for i in "${!CONTAINER_NAMES[@]}"; do
    docker run -d --restart always \
        --network host \
        --name ${CONTAINER_NAMES[$i]} \
        -v ${LOG_PATHS[$i]}:/opt/projects/ictcloud/logs/ \
        -e SERVER_PORT=${NACOS_PORTS[$i]} \
        -e spring.cloud.nacos.discovery.port=${NACOS_PORTS[$i]} \
        -e spring.cloud.nacos.discovery.ip=${SERVER_IP} \
        ${IMAGE_NAME}:latest
done

# 5. 验证部署结果
echo -e "\n部署结果验证:"
docker images | grep ${IMAGE_NAME}
docker ps --filter "name=ict-cloud-cms-api" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

在上面的可执行命令中,我是一次性启动了四个服务,并分别指定了对应的端口,你可以根据自己的真实需求进行修改。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐