记录使用 docker compose 去部署项目时遇到的几个问题

之前没搞过这个,没得经验,全凭感觉搞。设计的部署目录如下:


image.png

在config目录下是服务的配置文件,比如nginx的 nginx.conf,前端html资源等,java-app 里面是构建java镜像的Dockerfile 和jar包。所有的数据,包括日志等都挂载到的data对应的目录下。

我想的是快速部署一个项目,而且方便后续服务器的迁移。比如后续需要更换服务器直接把qt_project这个目录拷贝到其他服务器上即可。

这里直接把 qt_project 这个目录丢到服务器根目录即可,我是在虚拟机里面测试的:


image.png

然后给整个部署项目755权限

sudo chmod -R 755 /qt_project

最后执行脚本即可部署整个项目。

cd /qt_project/publish
./start_project.sh

部分代码如下

docker-compose.yml

# version: '3.8' (已过时)

# 定义网络配置
networks:
  d-net: # 直接定义网络名称,无需嵌套 `name`
    driver: bridge # 显式指定驱动(默认是 bridge)

# 定义所有服务
services:
  # Redis 服务配置
  redis:
    image: redis:alpine
    container_name: redis # 指定容器名称
    restart: always # 容器退出时自动重启
    ports:
      - "6379:6379" # 暴露 Redis 默认端口(主机端口:容器端口)
    volumes:
      - ${DATA_DIR}/redis:/data # 挂载宿主机/data/redis到容器的/data目录(持久化数据)
      - ${CONFIG_DIR}/redis/redis.conf:/usr/local/etc/redis/redis.conf # 挂载自定义配置文件
    environment:
      - TZ=Asia/Shanghai # 设置时区为上海
    command: redis-server --appendonly yes # 启动命令,启用AOF持久化
    networks:
      - d-net # 直接引用网络名称

  # MySQL 5.7 服务配置
  mysql:
    image: mysql:5.7
    container_name: mysql # 指定容器名称
    restart: always # 自动重启
    ports:
      - "3306:3306" # 暴露 MySQL 默认端口
    volumes:
      - ${DATA_DIR}/mysql/data:/var/lib/mysql # 数据文件
      - ${DATA_DIR}/mysql/log:/var/log/mysql # 日志目录(关键挂载)
      - ${CONFIG_DIR}/mysql/conf:/etc/mysql/conf.d # 挂载自定义配置文件目录
    environment:
      - MYSQL_ROOT_PASSWORD=root@123 # 设置root密码(请修改)
      # - MYSQL_DATABASE=your_database           # 初始化时创建的数据库名
      # - MYSQL_USER=your_user                   # 创建普通用户
      # - MYSQL_PASSWORD=your_password           # 普通用户密码
      - TZ=Asia/Shanghai # 时区设置
    networks:
      - d-net

  # Nginx 服务配置
  nginx:
    image: nginx:1.21.6-alpine
    container_name: nginx # 容器名称
    restart: always # 自动重启
    ports:
      - "9999:9999"
      # - "80:80" # HTTP 端口
      # - "443:443" # HTTPS 端口
    volumes:
      - ${DATA_DIR}/nginx/log:/var/log/nginx # 挂载日志目录
      - ${CONFIG_DIR}/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
      - ${CONFIG_DIR}/nginx/html:/usr/share/nginx/html # 挂载网站根目录
    depends_on:
      - java-app # 声明依赖关系(等待java-app启动)
    networks:
      - d-net

  # Java 应用服务配置
  java-app:
    build:
      context: ${CONFIG_DIR}/java-app # 构建上下文的目录
      dockerfile: ./Dockerfile # Dockerfile 路径
    container_name: java-app # 容器名称
    restart: always # 自动重启
    ports:
      - "8002:8002" # 暴露应用端口(假设Spring Boot默认8080)
    depends_on:
      - mysql # 依赖 MySQL 服务
      - redis # 依赖 Redis 服务
    environment:
      - SPRING_PROFILES_ACTIVE=prod # 设置Spring Boot使用生产环境配置
      - TZ=Asia/Shanghai # 时区设置
    networks:
      - d-net

  # # RocketMQ NameServer 配置
  # rocketmq-namesrv:
  #   image: apache/rocketmq:4.9.4
  #   container_name: rocketmq-namesrv
  #   restart: always
  #   ports:
  #     - "9876:9876"
  #   volumes:
  #     - ${DATA_DIR}/rocketmq/namesrv/logs:/home/rocketmq/logs
  #   environment:
  #     - JAVA_OPT_EXT=-server -Xms128m -Xmx128m -Xmn128m
  #     - TZ=Asia/Shanghai
  #   command: sh mqnamesrv
  #   networks:
  #     - d-net

  # # RocketMQ Broker 配置
  # rocketmq-broker:
  #   image: apache/rocketmq:4.9.4
  #   container_name: rocketmq-broker
  #   restart: always
  #   ports:
  #     - "10909:10909"
  #     - "10911:10911"
  #     - "10912:10912"
  #   volumes:
  #     - ${DATA_DIR}/rocketmq/broker/logs:/home/rocketmq/logs
  #     - ${DATA_DIR}/rocketmq/broker/store:/home/rocketmq/store
  #     - ${CONFIG_DIR}/rocketmq/broker.conf:/opt/rocketmq/conf/broker.conf
  #   environment:
  #     - JAVA_OPT_EXT=-server -Xms2g -Xmx2g -Xmn1g # 固定 JVM 内存
  #     - TZ=Asia/Shanghai
  #   command: sh mqbroker -c /opt/rocketmq/conf/broker.conf
  #   depends_on:
  #     - rocketmq-namesrv
  #   networks:
  #     - d-net

# 定义命名卷(虽然主要使用主机目录挂载,但保留命名卷作为备用)
# volumes:
#   mysql-data:
#     driver: local              # 本地驱动
#   redis-data:
#     driver: local
#   nginx-data:
#     driver: local
#   java-app-data:
#     driver: local

.env

# 项目名称
PROJECT_NAME=qt
# 项目的数据挂载目录
DATA_DIR=../data
# 项目的配置文件目录
CONFIG_DIR=../config

start_project.sh

#!/bin/bash
# 启动项目脚本,会启动该项目所有docker服务

# 检查.env文件是否存在
if [ ! -f ".env" ]; then
    echo "错误:.env文件不存在,无法读取配置。"
    exit 1
fi


# 加载 .env 并删除所有 \r
source <(tr -d '\r' < .env)

# 定义变量
COMPOSE_FILE="docker-compose.yml"
SUB_DIRS=(
    "redis"
    "mysql/data"
    "mysql/log"
    "nginx/log"
    "java-app"
    "rocketmq/namesrv/logs"
    "rocketmq/namesrv/store"
    "rocketmq/broker/logs"
    "rocketmq/broker/store"
)
# 检查docker-compose文件是否存在
if [ ! -f "$COMPOSE_FILE" ]; then
    echo "错误:docker-compose文件 $COMPOSE_FILE 不存在,无法启动项目。"
    exit 1
fi

# 创建数据目录及其子目录
create_directory() {
    local dir="$1"
    if [ ! -d "$dir" ]; then
        echo "创建目录: $dir"
        mkdir -p "$dir"
        if [ $? -ne 0 ]; then
            echo "错误:无法创建 $dir 目录,请检查权限。"
            exit 1
        fi
    else
        echo "目录已存在,跳过创建: $dir"
    fi
}

echo "检查数据目录结构..."
create_directory "$DATA_DIR"
for sub_dir in "${SUB_DIRS[@]}"; do
    full_sub_dir="$DATA_DIR/$sub_dir"
    create_directory "$full_sub_dir"
done
echo "数据目录结构检查完成。"

# 停止并移除旧的容器、网络等
DOWN_OUTPUT=$(docker compose -f $COMPOSE_FILE -p $PROJECT_NAME down 2>&1)
DOWN_STATUS=$?
if [ $DOWN_STATUS -ne 0 ]; then
    echo "错误:停止并移除旧服务失败。详细信息如下:"
    echo "$DOWN_OUTPUT"
    exit 1
fi

# 1. 先构建服务(前台显示构建日志)
echo "正在构建服务..."
docker compose -f $COMPOSE_FILE -p $PROJECT_NAME build
BUILD_STATUS=$?
if [ $BUILD_STATUS -ne 0 ]; then
    echo "错误:构建失败!"
    exit 1
fi

# 2. 后台启动服务(不显示持续日志)
echo "启动服务到后台..."
docker compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d

echo "启动成功!"

遇到的几个错误和解决办法

问题1:当执行 start_project.sh 脚本的时候发现在shell脚本里面老是报目录找不到

目录是配置在 .env 文件里面的,这样 docker-compose.yml 可以直接读取。这让我很抓狂,目录其实就在旁边,就是报目录找不到。。。。.env 里面配置的也是shell脚本的开始执行的路径,不存在什么相对路径错误的问题。
然后我发现当我重新在服务器上修改了.env文件后可以运行了,但是给我创建了两个data目录。

最后定位到问题原因:shell脚本读取的时候把换行符也读了,后面带上了 \r所以导致找不到目录。比如本来是/data 目录读出来就变成了/data\r。

问题2:当执行 start_project.sh 脚本的时候控制台报version警告
WARN[0000] /project/projectConfig/publish/docker-compose.yml: `version` is obsolete

解决办法:version 是旧版 docker compose 需要的声明,现在不需要了,去掉 docker-compose.yml 顶部的 version 字段即可。

问题3:docker-compose 没有显示里面每个服务的构建过程

表现为卡了半天,我都以为哪里没弄好报错了,结果只是没有显示日志。
最后发现因为我在shell脚本里面把构建命令拿来做了判断,最后去掉这个判断直接用原始的这个命令执行就行了,这个错误完全是自找的。。。

直接用下面这个就行了,不要做多余的操作。

# 1. 先构建服务(前台显示构建日志)
echo "正在构建服务..."
docker compose -f $COMPOSE_FILE -p $PROJECT_NAME build
BUILD_STATUS=$?
if [ $BUILD_STATUS -ne 0 ]; then
    echo "错误:构建失败!"
    exit 1
fi

# 2. 后台启动服务(不显示持续日志)
echo "启动服务到后台..."
docker compose -f $COMPOSE_FILE -p $PROJECT_NAME up -d

echo "启动成功!"
问题4:nginx 页面地址未访问成功

这个就是单纯的配置出问题了,参考我之前的docker 同时部署两个前端项目就行了,我用的这个镜像:nginx:1.21.6-alpine。
我是直接拿的之前的配置,但是之前的里面是同时部署的两个前端服务,然后我这边的目录 qt_project/config/nginx/html 里面是直接放的前端dist资源,这个改下nginx.conf 配置就好了

        # 指定前端项目所在位置
        location / {
            root  /usr/share/nginx/html/lzkj/;
            index  index.html index.htm;
        }
改为

        # 指定前端项目所在位置
        location / {
            root  /usr/share/nginx/html/;
            index  index.html index.htm;
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容