Docker笔记

目录

[一、执行docker compose up后按时间顺序执行的文件:](#一、执行docker compose up后按时间顺序执行的文件:)

[1、Docker Compose 初始化](#1、Docker Compose 初始化)

[(1)Docker Compose 读取主配置文件:](#(1)Docker Compose 读取主配置文件:)

(2)加载环境变量:

2、基础设施服务启动

[(1)依赖顺序是通过 Docker Compose 配置文件中的 depends_on 指令来配置的:](#(1)依赖顺序是通过 Docker Compose 配置文件中的 depends_on 指令来配置的:)

(2)服务定义的健康检测规则:

3、根据Dockerfile构建启动容器

(1)构建镜像

为什么需要设置时区

为什么创建日志目录

健康检测

(2)启动容器

二、Docker启动项目时,Mysql容器自动执行SQL生成数据库。

原理:

示例代码:

environment属性:

三、常见指令:

[1、docker-compose up -d --remove-orphans](#1、docker-compose up -d --remove-orphans)

2、停止服务

[2.1 docker-compose down](#2.1 docker-compose down)

[2.2 docker-compose stop](#2.2 docker-compose stop)

3、指定配置文件

4、指定服务

四、配置数据持久化

1、绑定挂载

(1)概念:

(2)使用方式:

效果:

2、命名卷

概念:

配置方法:

注意:

五、故障排查

[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,看看能不能连上数据库。
相关推荐
WAIT_TIME2 小时前
昇腾910B虚拟卡(vNPU)创建以及Docker挂载
docker·容器·昇腾·runtime·虚拟显卡·vnpu
ch.ju2 小时前
Java程序设计(第3版)第二章——选择结构
java
llm大模型算法工程师weng2 小时前
Java高并发架构设计:从理论到实战的全链路解决方案
java·开发语言
CQU_JIAKE2 小时前
4.17【a]
java
Devin~Y2 小时前
从Spring Boot到Spring AI:音视频AIGC内容社区Java大厂面试三轮连环问(含Kafka/Redis/安全/可观测性答案)
java·spring boot·redis·spring cloud·kafka·spring security·resilience4j
Rsun045512 小时前
14、Java 模板方法模式从入门到实战
java·python·模板方法模式
沐雪轻挽萤2 小时前
17. C++17新特性-并行算法 (Parallel Algorithms)
java·开发语言·c++
StockTV2 小时前
SpringBoot对接黄金白银期货数据API
java·spring boot·后端
hsjcjh3 小时前
窗口函数-详细讲解分析
java·服务器·前端