【Docker 与 Docker-Compose 实战:从零开始容器化部署若依项目,从单容器分步运行到 Compose 一键编排】

提示:本文原创作品,良心制作,干货为主,简洁清晰,一看就会

文章目录


前言

Docker-Compose 是容器化部署的高效工具,能轻松编排多服务应用。本文以若依项目为实战案例,先演示单 Docker 容器分步部署,再重点讲解通过 Docker-Compose 一键编排 MySQL、Redis、前后端服务,让部署更简洁高效

一、docker容器运行若依项目

1.1 若依项目准备

bash 复制代码
# 拉取若依项目
root@ruoyi:~# git clone https://gitee.com/luqing000000/ruoyi-vue.git
root@ruoyi:~# ls ruoyi-vue/
bin  LICENSE  README.md    ruoyi-common     ruoyi-generator  ruoyi-system  ry.bat  sql
doc  pom.xml  ruoyi-admin  ruoyi-framework  ruoyi-quartz     ruoyi-ui      ry.sh

安装jdk、maven、node.js

JDK官网:https://www.oracle.com/java/technologies/downloads/
Maven官网:https://maven.apache.org/
Node.js官网:https://nodejs.org/zh-cn/download

bash 复制代码
#  1. 下载maven,node.js我是直接下载到了电脑上,上传到本机的
root@ruoyi:~#  wget https://dlcdn.apache.org/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.tar.gz  
root@ruoyi:~#  ls
apache-maven-3.9.11-bin.tar.gz  jdk-17.0.17_linux-x64_bin.tar.gz node-v16.20.2-linux-x64.tar.xz

#  2. 安装jdk,maven 打包后端代码
root@ruoyi:~#  tar xf jdk-17.0.17_linux-x64_bin.tar.gz -C /usr/local/
root@ruoyi:~# mv /usr/local/jdk-17.0.17 /usr/local/java/
root@ruoyi:~#  tar xf apache-maven-3.9.11-bin.tar.gz -C /usr/local/java/
root@ruoyi:~#  mv /usr/local/java/apache-maven-3.9.11/ /usr/local/java/maven

#  3. 安装node.js 打包前端代码
root@ruoyi:~#  tar xf node-v16.20.2-linux-x64.tar.xz -C /usr/local/
root@ruoyi:~#  mv /usr/local/node-v16.20.2-linux-x64/ /usr/local/node

#  4. 添加环境变量
root@ruoyi:~#  vim /etc/profile  
export JAVA_HOME=/usr/local/java
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
export MAVEN_HOME=/usr/local/java/maven
export NODE_HOME=/usr/local/node
export NODE_PATH=$NODE_HOME/lib/node_modules/
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$MAVEN_HOME/bin:$NODE_HOME/bin:$PATH

#  5. 加载配置
root@ruoyi:~#  source /etc/profile
root@ruoyi:~#  mvn -v  #一定要能显示版本,查看maven版本Java项目构建工具
Apache Maven 3.9.11 (3e54c93a704957b63ee3494413a2b544fd3d825b)
Maven home: /usr/local/java/maven
Java version: 17.0.17, vendor: Oracle Corporation, runtime: /usr/local/java
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1160.el7.x86_64", arch: "amd64", family: "unix"
root@ruoyi:~#  node -v  #查看node.js版本;js运行环境
v16.20.2
root@ruoyi:~#  npm -v  #查看npm版本;node.js包管理工具
8.19.4

打包前端代码

bash 复制代码
root@ruoyi:~# cd ruoyi-vue/ruoyi-ui/
root@ruoyi:~/ruoyi-vue/ruoyi-ui# ls
babel.config.js  bin  build  package.json  public  README.md  src  vue.config.js

#  打包前端代码
root@ruoyi:~/ruoyi-vue/ruoyi-ui# npm install -registry=http://registry.npmmirror.com
root@ruoyi:~/ruoyi-vue/ruoyi-ui# npm run build:prod
root@ruoyi:~/ruoyi-vue/ruoyi-ui# ls  #生成了dist目录,前端页面就在该目录下
babel.config.js  bin  build  dist  node_modules  package.json  package-lock.json  public  README.md  src  vue.config.js

打包后端代码

bash 复制代码
root@ruoyi:~# cd ruoyi-vue/ruoyi-admin/src/main/resources/

#  1. 配置后端连接mysql,现在填的什么库名和账号密码待会都要在mysql中创建出来
root@ruoyi:~/ruoyi-vue/ruoyi-admin/src/main/resources#  vim application-druid.yml 
bash 复制代码
#  2. 配置后端连接redis
root@ruoyi:~/ruoyi-vue/ruoyi-admin/src/main/resources#  vim application.yml 


bash 复制代码
root@ruoyi:~/ruoyi-vue/ruoyi-admin/src/main/resources# cd /root/ruoyi-vue/
root@ruoyi:~/ruoyi-vue# ls
bin  LICENSE  README.md    ruoyi-common     ruoyi-generator  ruoyi-system  ry.bat  sql
doc  pom.xml  ruoyi-admin  ruoyi-framework  ruoyi-quartz     ruoyi-ui      ry.sh

#  3. 打包后端代码,会在ruoyi-admin/target/目录下生成ruoyi-admin.jar包
root@ruoyi:~/ruoyi-vue# mvn clean package

1.2 运行mysql容器

bash 复制代码
#  1. 拉取mysql镜像
root@ruoyi:~# docker pull mysql:8.0

#  2. 运行mysql-tmp的临时容器,目的是从官方MySQL镜像中,复制出默认的配置文件 my.cnf,用于本地持久化配置
root@ruoyi:~# docker run -itd --name mysql-tmp -e MYSQL_ROOT_PASSWORD=root mysql:8.0 
root@ruoyi:~# mkdir -p /data/mysql/{conf,data,log}  #创建存放配置文件,数据,日志的目录
root@ruoyi:~# ls /data/mysql/
conf  data  log
root@ruoyi:~# docker cp mysql-tmp:/etc/my.cnf /data/mysql/conf/   #将mysql-tmp映射出来
root@ruoyi:~# ls /data/mysql/conf/
my.cnf
root@ruoyi:~# mkdir -p /data/mysql/conf/conf.d  #创建mysql子配置文件的映射目录

#  3. 删除mysql-tmp容器
root@ruoyi:~# docker stop mysql-tmp
root@ruoyi:~# docker rm mysql-tmp

#  4. 运行mysql容器,实现端口映射、数据持久化、配置挂载、日志持久化
root@ruoyi:~# docker run --restart=always -itd \
  --name mysql \
  -p 3306:3306 \
  -v /data/mysql/conf/my.cnf:/etc/my.cnf \
  -v /data/mysql/conf/conf.d:/etc/mysql/conf.d \
  -v /data/mysql/data:/var/lib/mysql \
  -v /data/mysql/log/mysqld.log:/var/log/mysql/mysqld.log \
  -e MYSQL_ROOT_PASSWORD=Qing@123  mysql:8.0
root@ruoyi:~# docker ps  #查看容器运行状态,如果失败可以docker logs mysql查看报错
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
f47ff81513e1   mysql:8.0   "docker-entrypoint.s..."   2 minutes ago   Up 2 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
bash 复制代码
#  5. 测试能否登录msyql,并创建ruoyi库
root@ruoyi:~# docker exec -it mysql /bin/bash
bash-5.1# mysql -uroot -p'Qing@123'
mysql> use mysql
mysql> SELECT host, user FROM user WHERE user = 'root';
+-----------+------+
| host      | user |
+-----------+------+
| %         | root |
| localhost | root |
+-----------+------+
mysql> exit
Bye
bash-5.1# read escape sequence

#  也可以下载mysql连接工具,在宿主机上登录
root@ruoyi:~# apt install -y mysql-client
root@ruoyi:~# mysql -uroot -p'Qing@123' -P 3306 -h 192.168.136.134
mysql> CREATE DATABASE ruoyi CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;  #创建ruoyi库
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| ruoyi              |
| sys                |
+--------------------+
Bye
bash 复制代码
#  6. 导入ruoyi项目代码,创建后端连接的账号密码
root@ruoyi:~# cd ruoyi-vue/sql
root@ruoyi:~/ruoyi-vue/sql# mysql -uroot -p'Qing@123' -P 3306 -h 192.168.136.134 ruoyi < ry_20260320.sql
root@ruoyi:~/ruoyi-vue/sql# mysql -uroot -p'Qing@123' -P 3306 -h 192.168.136.134 ruoyi < quartz.sql 
root@ruoyi:~/RuoYi-Vue/sql# mysql -uroot -p'Qing@123' -P 3306 -h 192.168.136.134
mysql> use ruoyi
mysql> show tables;  # 查看是否导入成功
+--------------------------+
| Tables_in_ruoyi          |
+--------------------------+
| QRTZ_BLOB_TRIGGERS       |
| QRTZ_CALENDARS           |
| QRTZ_CRON_TRIGGERS       |
| QRTZ_FIRED_TRIGGERS      |
| QRTZ_JOB_DETAILS         |
| QRTZ_LOCKS               |
| QRTZ_PAUSED_TRIGGER_GRPS |
| QRTZ_SCHEDULER_STATE     |
| QRTZ_SIMPLE_TRIGGERS     |
| QRTZ_SIMPROP_TRIGGERS    |
| QRTZ_TRIGGERS            |
| gen_table                |
| gen_table_column         |
| sys_config               |
| sys_dept                 |
| sys_dict_data            |
| sys_dict_type            |
| sys_job                  |
| sys_job_log              |
| sys_logininfor           |
| sys_menu                 |
| sys_notice               |
| sys_notice_read          |
| sys_oper_log             |
| sys_post                 |
| sys_role                 |
| sys_role_dept            |
| sys_role_menu            |
| sys_user                 |
| sys_user_post            |
| sys_user_role            |
+--------------------------+

mysql> CREATE USER 'ruoyi'@'%' IDENTIFIED BY 'Ruoyi@123';  # 刚才在application-druid.yml中填写的什么用户就创建什么

mysql> GRANT ALL PRIVILEGES ON ruoyi.* TO 'ruoyi'@'%';  # 授权允许该用户从任意ip地址连接到mysql

mysql> flush privileges;
mysql> quit
Bye

1.3 运行redis容器

bash 复制代码
#  1. 拉取redis镜像
root@ruoyi:~# docker pull redis:6.2.7
root@ruoyi:~# mkdir -p  /data/redis/{conf,data}  # 创建存放配置文件,数据的目录

#  2. 编写配置文件
root@ruoyi:~# vim /data/redis/conf/redis.conf   
bind 0.0.0.0
port 6379
daemonize no
pidfile /var/run/redis.pid

save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data

loglevel notice
logfile ""

# 数据库数量
databases 16
appendonly no
appendfilename "appendonly.aof"
bash 复制代码
#  3. 运行redis容器
root@ruoyi:~# docker run -itd --name redis \
  -p 6379:6379  --restart=always \
  -v /data/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf  \
  redis:6.2.7 --appendonly yes

#  4. 测试redis连接性
root@ruoyi:~# apt install -y redis-tools  # 下载redis连接工具
root@ruoyi:~# redis-cli -h 192.168.136.134 -p 6379
192.168.136.134:6379> ping
PONG
192.168.136.134:6379> quit

1.4 运行前端容器

bash 复制代码
#  1. 拉取nginx镜像
root@ruoyi:~# docker pull nginx:1.24

#  2. 创建映射目录
root@ruoyi:~# mkdir -p /data/nginx/{conf,html,log}  #创建存放配置文件,页面,日志的目录
root@ruoyi:~# ls /data/nginx/
conf  html  log
root@ruoyi:~# mkdir -p /data/nginx/conf/conf.d
root@ruoyi:~# touch /data/nginx/log/{access.log,error.log}
root@ruoyi:~# cp -r /root/ruoyi-vue/ruoyi-ui/dist/ /data/nginx/html/  #将刚才打包好的前端包移到该目录下
root@ruoyi:~# ls /data/nginx/html/dist/
favicon.ico  html  index.html  index.html.gz  robots.txt  static
bash 复制代码
#  3. 编写配置文件
root@ruoyi:~# vim /data/nginx/conf/nginx.conf 
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
        worker_connections 768;
}

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        gzip on;
server {
    listen       80;
    listen  [::]:80;
    server_name  192.168.136.134;  #填写前端程序的地址

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root    /usr/share/nginx/html/dist;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
location /prod-api/ {
    proxy_pass http://192.168.136.134:8080/;  #连接后端程序的地址,application.yml中的端口是多少此处就填多少
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout 600s;
    proxy_read_timeout 600s;
}
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }  
}
}
bash 复制代码
#  4. 启动nginx容器
root@ruoyi:~# docker run --restart=always -itd --name nginx  -p 80:80 \
  -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
  -v /data/nginx/conf/conf.d/:/etc/nginx/conf.d/ \
  -v /data/nginx/html/:/usr/share/nginx/html/  \
  -v /data/nginx/log/access.log:/var/log/nginx/access.log \
  -v /data/nginx/log/error.log:/var/log/nginx/error.log nginx:1.24

1.5 运行后端容器

bash 复制代码
#  1. 准备jar包,jdk包
root@ruoyi:~# mkdir -p /data/docker-images/ruoyi-vue/
root@ruoyi:~# mv /root/ruoyi-admin/target/ruoyi-admin.jar /data/docker-images/ruoyi-vue/

# 此处我没有拉取openjdk:17是因为网络原因拉取不下来,大家可以自行试试,这里我用jdk包来创造jdk镜像
root@ruoyi:~# mv jdk-17.0.17_linux-x64_bin.tar.gz /data/docker-images/
root@ruoyi:~# cd /data/docker-images/ruoyi-vue/
root@ruoyi:/data/docker-images/ruoyi-vue# ls
Dockerfile  jdk-17.0.17_linux-x64_bin.tar.gz  ruoyi-admin.jar
bash 复制代码
#  2. 编写Dockerfile
root@ruoyi:/data/docker-images/ruoyi-vue# cat Dockerfile 
FROM debian:bullseye-slim

# 安装字体库依赖(在构建时安装)
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    libfreetype6 \
    fontconfig \
    ca-certificates \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 复制并解压 JDK
COPY jdk-17.0.17_linux-x64_bin.tar.gz /tmp/
RUN mkdir -p /usr/local/java && \
    tar -xzf /tmp/jdk-17.0.17_linux-x64_bin.tar.gz -C /usr/local/java && \
    mv /usr/local/java/jdk-17.0.17 /usr/local/java/jdk17 && \
    rm /tmp/jdk-17.0.17_linux-x64_bin.tar.gz

# 设置环境变量
ENV JAVA_HOME=/usr/local/java/jdk17
ENV PATH=$JAVA_HOME/bin:$PATH
ENV TZ=Asia/Shanghai
ENV LANG=C.UTF-8

# 复制应用
COPY ruoyi-admin.jar /app/ruoyi-admin.jar

# 创建日志目录
RUN mkdir -p /app/logs

WORKDIR /app

EXPOSE 8035

# 添加健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD java -version || exit 1

# 使用 exec 形式启动,并添加 headless 参数
ENTRYPOINT ["java", "-Djava.awt.headless=true", "-jar", "ruoyi-admin.jar"]
bash 复制代码
#  3. 构建镜像
root@ruoyi:/data/docker-images/ruoyi-vue# docker build -t ruoyi:v1 .
#  4. 运行ruoyi-vue容器
root@ruoyi:~# docker run -itd --name ruoyi-vue -p 8080:8080 ruoyi:v1  java -Djava.awt.headless=true -jar app.jar
root@ruoyi:~# docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
4d78a23242d3   ruoyi:v1      "java -jar ruoyi-adm..."   7 seconds ago    Up 5 seconds    0.0.0.0:8080->8080/tcp, :::8080->8080/tcp              ruoyi-vue
9f0aaf959fcb   nginx:1.24    "/docker-entrypoint...."   30 minutes ago   Up 30 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp                      nginx1
8610460d0d41   redis:6.2.7   "docker-entrypoint.s..."   45 minutes ago   Up 45 minutes   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp              redis
f47ff81513e1   mysql:8.0     "docker-entrypoint.s..."   58 minutes ago   Up 58 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql

浏览器访问ip:80,就可以登录ruoyi项目了

二、docker-compose运行若依项目

2.1 安装docker-compose

GitHub安装地址:https://github.com/docker/compose/releases

下拉选择适合自己系统的版本,我选的是v2.38.0

bash 复制代码
# 安装docker-compose
root@harbor:~# ls   
docker-compose-linux-x86_64
root@harbor:~# mv docker-compose-linux-x86_64 /usr/bin/   #将包移到/usr/bin
root@harbor:~# mv /usr/bin/docker-compose-linux-x86_64  /usr/bin/docker-compose   #改名成docker-compose
root@harbor:~# chmod +x /usr/bin/docker-compose
root@harbor:~# docker-compose version  #查看docker-compose版本
Docker Compose version v2.38.0

2.2 编写docker-compose.yml

bash 复制代码
root@ruoyi:~# mkdir /data/docker-compose
root@ruoyi:~# cd /data/docker-compose
root@ruoyi:/data/docker-compose# vim docker-compose.yml 
root@ruoyi:/data/docker-compose# cat docker-compose.yml 
version: '3.8'

services:
  # MySQL 数据库
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: Qing@123
    volumes:
      - /data/mysql/data/:/var/lib/mysql
      - /data/mysql/conf/my.cnf:/etc/my.cnf
      - /data/mysql/log/mysqld.log:/var/log/mysqld.log
      - /data/mysql/conf/conf.d/:/etc/mysql/conf.d
    command: 
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    networks:
      - ruoyi-network

  # Redis 缓存
  redis:
    image: redis:6.2.7
    container_name: redis
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - /data/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
      - /data/redis/data:/data
    command: redis-server /usr/local/etc/redis/redis.conf --appendonly yes
    networks:
      - ruoyi-network

  # Nginx 反向代理
  nginx:
    image: nginx:1.24
    container_name: nginx
    restart: always
    ports:
      - "80:80"
    volumes:
      - /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
      - /data/nginx/conf/conf.d/:/etc/nginx/conf.d/
      - /data/nginx/html/:/usr/share/nginx/html/
      - /data/nginx/log/access.log:/var/log/nginx/access.log
      - /data/nginx/log/error.log:/var/log/nginx/error.log
    depends_on:
      - ruoyi-vue
    networks:
      - ruoyi-network

  # 若依后端服务
  ruoyi-vue:
    image: ruoyi:v1
    container_name: ruoyi-vue
    restart: always
    ports:
      - "8080:8080"
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /data/ruoyi/logs:/logs
    command: java -Djava.awt.headless=true -jar app.jar
    depends_on:
      - mysql
      - redis
    networks:
      - ruoyi-network

# 自定义网络
networks:
  ruoyi-network:
    driver: bridge

2.3 运行docker-compose.yml

bash 复制代码
root@ruoyi:/data/docker-compose# docker-compose up -d
root@ruoyi:/data/docker-compose# docker-compose ps
WARN[0005] /data/docker-compose/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
NAME        IMAGE         COMMAND                  SERVICE     CREATED        STATUS                  PORTS
mysql       mysql:8.0     "docker-entrypoint.s..."   mysql       7 seconds ago   Up 5 seconds             0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp
nginx       nginx:1.24    "/docker-entrypoint...."   nginx       7 seconds ago   Up 5 seconds             0.0.0.0:80->80/tcp, [::]:80->80/tcp
redis       redis:6.2.7   "docker-entrypoint.s..."   redis       7 seconds ago   Up 5 seconds             0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp
ruoyi-vue   ruoyi:v1      "java -Djava.awt.hea..."   ruoyi-vue   7 seconds ago   Up 5 seconds (healthy)   8035/tcp, 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp

浏览器访问ip:80

由上述实验可以直观的看到:

  • 相比于手动运行单个Docker容器,Docker-Compose可通过单一配置文件统一管理MySQL、Redis、前后端服务,无需逐条执行复杂启动命令,大幅简化操作
  • 服务依赖、网络、端口、挂载等参数集中定义,结构清晰、易于维护
  • 一键实现所有服务启动、停止、重启,自动处理容器间依赖与网络通信,避免手动启动顺序错误
  • 环境可快速迁移、复制,降低部署出错率,让若依前后端分离项目的容器化部署更高效、规范、可复用

注:

文中若有疏漏,欢迎大家指正赐教。

本文为100%原创,转载请务必标注原创作者,尊重劳动成果。

求赞、求关注、求评论!你的支持是我更新的最大动力,评论区等你~

相关推荐
xuefeiniao2 小时前
Docker 部署宝塔面板 Nginx 反向代理 502 踩坑实录
nginx·docker·容器
csdn_aspnet2 小时前
GitOps宣言:Kubernetes配置的版本化革命
云原生·容器·kubernetes·gitops
H_老邪3 小时前
Linux 与 Docker 常用命令
linux·运维·服务器·docker
博语小屋3 小时前
I/O 多路转接之epoll
运维·服务器·数据库
yewq-cn3 小时前
linux 内核设备号
linux·运维·服务器
sky wide3 小时前
[特殊字符] Docker Swarm 集群搭建指南
java·docker·容器
新钛云服3 小时前
如何构建一套自动化的阿里云费用报告系统
运维·阿里云·自动化·云计算
allway24 小时前
Debian Regular Expressions
运维·debian·scala
文静小土豆4 小时前
Linux 进程终止指南:理解 kill 与 kill -9 的核心区别与正确用法
linux·运维·服务器