目录
[一、执行docker compose up后按时间顺序执行的文件:](#一、执行docker compose up后按时间顺序执行的文件:)
[1、Docker Compose 初始化](#1、Docker Compose 初始化)
[(1)Docker Compose 读取主配置文件:](#(1)Docker Compose 读取主配置文件:)
[(1)依赖顺序是通过 Docker Compose 配置文件中的 depends_on 指令来配置的:](#(1)依赖顺序是通过 Docker Compose 配置文件中的 depends_on 指令来配置的:)
二、Docker启动项目时,Mysql容器自动执行SQL生成数据库。
[1、docker-compose up -d --remove-orphans](#1、docker-compose up -d --remove-orphans)
[2.1 docker-compose down](#2.1 docker-compose down)
[2.2 docker-compose stop](#2.2 docker-compose stop)
[1、docker-compose ps](#1、docker-compose ps)
[2、docker-compose logs -f <服务名>](#2、docker-compose logs -f <服务名>)
[3、docker-compose exec](#3、docker-compose exec)
一、执行docker compose up后按时间顺序执行的文件:
1、Docker Compose 初始化
(1)Docker Compose 读取主配置文件:
读取docker-compose.yaml。
(2)加载环境变量:
读取.env文件。
2、基础设施服务启动
(1)依赖顺序是通过 Docker Compose 配置文件中的 depends_on 指令来配置的:
services:
# 后端服务依赖 MySQL、Redis、MinIO
project:
depends_on:
mysql:
condition: service_healthy # 等待 MySQL 健康检查通过
redis:
condition: service_healthy # 等待 Redis 健康检查通过
minio:
condition: service_healthy # 等待 MinIO 健康检查通过
# 前端服务依赖后端服务
project-web:
depends_on:
project:
condition: service_healthy # 等待后端服务健康检查通过
(2)服务定义的健康检测规则:
services:
mysql:
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s # 检查间隔
timeout: 10s # 超时时间
retries: 5 # 重试次数
redis:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 5
minio:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 10s
retries: 5
//test 是健康检查的 核心执行命令 ,它会定期运行来判断服务是否正常运行
例如:使用 mysqladmin ping 检查 MySQL 是否可连接
3、根据Dockerfile构建启动容器
(1)构建镜像
根据Dockerfile中的指令构建镜像:
FROM docker.m.daocloud.io/library/maven:3.9.9-eclipse-temurin-21-noble AS build
WORKDIR /app
# 项目代码通过 COPY 命令复制到容器内部
COPY /project /app/project
# 打包构建项目
WORKDIR /app/project
RUN mvn clean package -DskipTests
# Runtime stage
FROM docker.m.daocloud.io/library/eclipse-temurin:21-jre-noble
WORKDIR /app
#设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
# 复制 jar文件
COPY --from=build /app/project/hub/target/proj-server.jar /app/proj-server.jar
#创建日志目录
RUN mkdir -p /app/logs
# 声明容器内应用监听的端口
EXPOSE 8080
#健康检测
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD wget --quiet --tries=1 --spider http://localhost:8080/actuator/health || exit 1
#http://localhost:8080/actuator/health 是 Spring Boot Actuator 官方提供的健康检查端点
# Entrypoint
ENTRYPOINT ["java", \
"-XX:+UseContainerSupport", \
"-XX:MaxRAMPercentage=75.0", \
"-Djava.security.egd=file:/dev/./urandom", \
"-Duser.timezone=Asia/Shanghai", \
"-jar", \
"/app/proj-server.jar"]
//-------------------------------------------------------//
1、FROM ... AS build 使用 Maven 镜像作为构建基础
2、COPY console/backend /app/console/backend 复制后端代码到镜像
3、RUN mvn clean package -DskipTests 执行 Maven 编译打包
4、FROM ... AS runtime 使用 JRE 镜像作为运行时基础
5、COPY --from=build ... 从构建阶段复制 JAR 文件
6、EXPOSE 8080 声明暴露端口
7、ENTRYPOINT ["java", "-jar", ...] 设置启动命令
为什么需要设置时区
-
默认 Docker 容器使用 UTC 时间 (格林尼治标准时间)
-
如果不设置时区,日志中的时间会比北京时间晚 8 小时
-
Spring Boot 应用的日志、定时任务等都依赖系统时区
为什么创建日志目录
-
Spring Boot 应用默认会将日志输出到 logs/ 目录
-
如果目录不存在,应用启动时可能会报错
-
提前创建目录可以避免启动失败
健康检测
访问 /actuator/health 接口是为了 检测 Spring Boot 应用是否真正启动并正常运行 ,参数可以自己定义。
(2)启动容器
镜像构建完成后,Docker Compose 启动容器:
1. 创建容器 :基于构建好的镜像创建容器实例
2. 配置网络 :yaml定义容器之间如何通信
3. 设置环境变量 :如数据库连接信息、端口等
4. 挂载卷 (如果配置):如日志目录
5. 执行启动命令 :运行 ENTRYPOINT 中定义的命令(如 java -jar hub-server.jar )
6. 健康检查 :定期执行 HEALTHCHECK 命令检查服务状态
二、Docker启动项目时,Mysql容器自动执行SQL生成数据库。
原理:
.
官方 MySQL 镜像(以及 MariaDB、PostgreSQL 等)的启动逻辑中,包含一个名为 docker-entrypoint.sh 的入口脚本。这个脚本在数据库服务正式启动前运行,它的核心逻辑如下:
检测数据目录是否为空
脚本首先会检查数据目录(默认为 /var/lib/mysql)是否为空。
如果不为空:说明数据库已经初始化过了,脚本会直接启动 MySQL 服务。
如果为空:说明这是第一次运行,脚本会先进行数据库初始化(创建系统表等)。
执行初始化脚本
在初始化完成后、正式启动服务之前,脚本会查找一个特定的目录:/docker-entrypoint-initdb.d。
它会按文件名顺序扫描该目录下的文件。
支持格式:.sh(Shell 脚本)、.sql(SQL 语句)、.sql.gz(压缩的 SQL 语句)。
执行动作:找到这些文件后,它会使用 root 用户连接数据库,并自动执行里面的内容。
一般情况下我们在docker-compose.yml文件中将存储了SQL文件的文件夹映射到/docker-entrypoint-initdb.d中。
示例代码:
java
services:
db-test:
image: mysql:8.0 # 或者其他版本
environment:
MYSQL_ROOT_PASSWORD: your_password
MYSQL_DATABASE: test_db
volumes:
# 格式是: ./宿主机路径:容器内部路径
- ./docker/project/mysql/:/docker-entrypoint-initdb.d/
# 如果还有数据持久化需求,通常还会有这一行:
# - ./data/mysql:/var/lib/mysql
如果不写container_name给创建的容器取名,Docker会生成一个名字,规范如下:
项目名_服务名_编号
项目名:默认是你当前文件夹的名字(或者 docker-compose.yml 所在的目录名)。
服务名:就是你在 services 下面写的 db-prod 或 db-test。
编号:通常是 1。应用于进行扩展、发生冲突、需要更新的时候。
environment属性:
java
environment:
# 必须填
MYSQL_ROOT_PASSWORD: root_password
# 自动建库
MYSQL_DATABASE: my_app_db
# 自动建普通用户
MYSQL_USER: app_user
MYSQL_PASSWORD: app_password
# 解决兼容性问题
MYSQL_DEFAULT_AUTHENTICATION_PLUGIN: mysql_native_password
# 设置时区
TZ: Asia/Shanghai
# 允许 root 远程连接 (可选)
MYSQL_ROOT_HOST: "%"
三、常见指令:
1、docker-compose up -d --remove-orphans
--remove-orphans:这个参数原本是用来删除"孤儿容器"(即在配置文件中被删除了的服务,但还在运行的容器)。
副作用:在更新场景下,它也会顺手把那些被替换下来的、重命名为 _old 的旧容器清理掉。
(1)docker-compose是工具名称:官方提供的编排工具
(2)up是动作指令:启动/构建运行
(3)-d和--remove-orphans都是参数,-后面跟缩写,--后面跟全称
-d指--detach,意为后台运行。(1)如果不加 -d:命令会占用你的当前终端窗口。你会看到所有容器的日志输出在屏幕上,一旦你按 Ctrl+C 或者关闭窗口,服务就会停止。(2)加上 -d:容器会在后台作为守护进程运行。命令执行后会立即返回命令行提示符,你可以继续在这个窗口做其他事情,而服务会一直稳定运行,不受窗口关闭的影响。
2、停止服务
2.1 docker-compose down
(1)作用:停止所有容器、删除容器、删除网络。
注意:它默认不会删除数据卷(你的数据库数据还在),也不会删除镜像。
(2)手动加上-v会删除数据卷,--rmi all 会删除镜像。
2.2 docker-compose stop
(1)作用:仅仅是把运行中的容器"暂停"(状态变为 Exited)。
(2)恢复:下次想用的时候,输入 docker-compose start 就可以秒开,不用重新构建。
3、指定配置文件
docker-compose -f docker-compose.test.yml up -d
-f即告诉Docker不使用默认yml而是使用后面那个
4、指定服务
docker-compose up -d db
如果配置文件有db和testdb只会启动db
四、配置数据持久化
1、绑定挂载
(1)概念:
这种方式是将你电脑上的一个具体文件夹直接映射到容器里。
(2)使用方式:
在 docker-compose.yml 的 volumes 部分,使用 ./宿主机路径:容器内路径 的格式。
java
version: '3.8'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
# 将你电脑上的 ./my-data 目录映射到容器的 /var/lib/mysql
- ./my-data:/var/lib/mysql
效果:
MySQL 产生的所有数据文件,都会实实在在地保存在你项目目录下的 my-data 文件夹里。
2、命名卷
概念:
这种方式是让 Docker 来帮你管理一个有名字的存储空间,你不用关心它具体在你电脑硬盘的哪个位置。
配置方法:
在 docker-compose.yml 中,需要分两步:先在服务下声明挂载,再在文件末尾的顶层 volumes 中定义这个卷。
java
version: '3.8'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
# 1. 将名为 'db-data' 的卷挂载到容器的 /var/lib/mysql
- db-data:/var/lib/mysql
# 2. 在顶层定义 'db-data' 这个卷
volumes:
db-data:
效果:Docker 会自动创建一个叫 db-data 的存储空间(通常在 /var/lib/docker/volumes/ 下),并把数据存在里面。即使你用 docker-compose down 删除了容器,这个 db-data 卷和里面的数据依然存在。
注意:
无论使用哪种方式,在执行 docker-compose down 时加上 -v 参数,命名卷都会被删除,导致数据丢失!
五、故障排查
1、docker-compose ps
作用:查看状态
java
Up:容器在运行。如果服务不可用,通常是端口映射或应用内部逻辑问题。
Restarting:容器不断重启。通常是启动脚本报错,或者健康检查失败
Exited (1) / Exited (137):容器启动后立刻退出了。这是最常见的情况,需要看日志。
Exit Code 1:通常是应用程序报错(如代码异常、配置文件错误)。
Exit Code 137:内存溢出 (OOM)。容器使用的内存超过了限制,被系统强杀了。
2、docker-compose logs -f <服务名>
java
# 实时跟踪日志,加上 --tail 100 查看最近100行
docker-compose logs -f --tail 100 db
常见日志关键词:
Permission denied:权限问题(挂载目录不可写)。
Address already in use:端口冲突。
Connection refused:连不上数据库或依赖服务。
Error: database is uninitialized:MySQL 密码没设对或数据目录权限不对。
3、docker-compose exec
java
# 进入容器(优先试 bash,不行就试 sh)
docker-compose exec db bash
# 或者
docker-compose exec db sh
文件在不在:ls 看看挂载的配置文件或代码有没有正确加载。
端口通不通:netstat -tlnp 或 ss -tlnp 看看服务有没有监听在预期的端口上。
环境变量对不对:env 命令可以列出所有环境变量,检查密码、主机名是否传进去了。
内部连通性:在应用容器里 ping db 或 curl localhost:3306,看看能不能连上数据库。