【FDE系列】阶段2:Day 43:Docker Compose — 多容器一键编排

📚前言

📒FDE系列内容总纲:

【大纲】FDE 前沿部署工程师学习系列教程-CSDN博客

🚄前置课程列表:

见文档结尾附录。


🚀阶段2·Day 43:Docker Compose --- 多容器一键编排

FDE 学习系列教程 · 第二阶段 · 第 5 周 · Day 3 预计时长:3 小时 | 难度:★★★☆☆ | 前置知识:Day 41-42 容器操作与 Dockerfile
📌 一句话目标:看懂并编写 docker-compose.yml,用 Docker Compose 一键编排 FastAPI + MySQL 多容器应用,掌握服务依赖、环境变量、数据卷和常用管理命令。


🧑‍🤝‍🧑 开场:一个容器好养,一套容器难带

昨天你能把自己的 FastAPI 打成镜像了。但真实项目从来不是"一个容器包打天下"。回想你的工单系统:

复制代码
  工单系统需要:
  ┌──────────┐  连接   ┌──────────┐
  │ FastAPI  │ ──────► │  MySQL   │
  │  容器     │         │  容器     │
  └──────────┘         └──────────┘
       明天还要加:Nginx 容器(反向代理)、Redis 容器(缓存)......

如果用昨天的 docker run 手搓,你得:

复制代码
# ① 先建个网络让容器互通
docker network create fde-net
# ② 启动 MySQL(记一堆 -e、-v、--network 参数)
docker run -d --name db --network fde-net \
  -e MYSQL_ROOT_PASSWORD=root123 -e MYSQL_DATABASE=fde_db \
  -v db_data:/var/lib/mysql mysql:8.0
# ③ 等 MySQL 就绪(多久?只能靠猜)
# ④ 启动 API(又是一堆参数,还得保证数据库先起来)
docker run -d --name api --network fde-net -p 8000:8000 \
  -e DB_HOST=db ... fde-api:1.0

三个容器就要敲四五个长命令,换台机器全部重来一遍,顺序错了还连不上。Docker Compose 就是来终结这种手工活的:把所有容器的配置写进一个 YAML 文件,一条命令让整套环境按正确的姿势全部就位。

复制代码
  手工 docker run:              Docker Compose:
  一条条命令,参数靠脑子记        一个 docker-compose.yml 描述全部
  顺序、网络、卷手动管            up 一键启动 / down 一键销毁
  换机器要重新敲一遍              文件拷过去,up 一下原样复现

📖 一、Compose 是什么 & 版本说明

Docker Compose 是 Docker 官方的多容器编排工具。你用一个 YAML 文件声明"系统由哪些服务组成、每个服务用什么镜像、开什么端口、挂什么卷、彼此什么关系",Compose 负责把它们全部创建好、连进同一个网络。

复制代码
┌────────────────────────────────────────────────────────┐
│  docker-compose.yml (一份声明,描述整套系统)           │
│                                                        │
│   services:                                            │
│     api:   ← 服务1(FastAPI 容器)                     │
│     db:    ← 服务2(MySQL 容器)                       │
│     nginx: ← 服务3(Nginx 容器,明天加)               │
│                                                        │
│   docker compose up -d   → 三个容器 + 网络 + 数据卷     │
│                           一次性全部创建                │
└────────────────────────────────────────────────────────┘

💡 命令的新旧写法 :新版 Docker(带 Compose V2 插件)用 docker compose(中间空格),老版本 V1 用 docker-compose(中间横杠,独立程序)。你昨天验证过 docker compose version 有输出,所以本教程统一用新写法 docker compose。两种写法参数基本一致,看到老教程的 docker-compose 别慌,等价。

YAML 语法速览(30 秒入门)

Compose 文件是 YAML 格式,核心就两条规矩:

  1. 靠缩进表示层级 (每层通常 2 个空格,不能用 Tab

  2. 键值对用冒号加空格key: value(冒号后那个空格不能少)

    services: # 顶层
    api: # 缩进 2 格:services 的子项
    image: nginx # 再缩进 2 格:api 的配置
    ports: # 列表用 - 开头
    - "80:80"


🖥️ 二、最小例子:用 Compose 跑一个 Nginx

先跑个最小的,建立"yml → 容器"的直观感受。

复制代码
mkdir -p ~/docker_lab/compose_demo && cd ~/docker_lab/compose_demo

新建 docker-compose.yml

复制代码
services:
  web:
    image: nginx:alpine
    container_name: demo-nginx
    ports:
      - "8080:80"
    restart: unless-stopped

逐行对应到你昨天学的 docker run 参数:

docker run 写法 compose 写法
nginx:alpine(镜像) image: nginx:alpine
--name demo-nginx container_name: demo-nginx
-p 8080:80 ports: - "8080:80"
--restart unless-stopped restart: unless-stopped

启动:

复制代码
docker compose up -d
# [+] Running 2/2
#  ✔ Network compose_demo_default  Created
#  ✔ Container demo-nginx         Started

注意它自动建了一个网络compose_demo_default)------这就是 Compose 的省心之处。浏览器访问 http://localhost:8080 看到欢迎页。

常用管理命令先混个眼熟:

复制代码
docker compose ps          # 看这套服务的容器状态
docker compose logs -f     # 看所有服务日志(-f 实时)
docker compose stop        # 停止(容器保留)
docker compose start       # 再启动
docker compose down        # 停止并删除容器+网络(数据卷默认保留)
docker compose up -d       # 改了配置后重新生效

docker compose down 清掉,进入正题。


🖥️ 三、实战:FastAPI + MySQL 两容器编排

现在把昨天的 fde-api 和一个 MySQL 数据库编排起来。注意:容器之间通过服务名互相访问,这是 Compose 最巧妙的地方,先看项目结构:

复制代码
~/docker_lab/fde_stack/
├── main.py
├── requirements.txt
├── Dockerfile            ← 昨天写的(构建 api 镜像用)
├── .dockerignore
├── init.sql              ← 数据库初始化脚本(待会写)
└── docker-compose.yml    ← 今天的主角

第 1 步:main.py(连上数据库的版本)

复制代码
from fastapi import FastAPI
import os
import mysql.connector
import uvicorn

app = FastAPI(title="FDE API + MySQL", version="1.0")


def get_db():
    """从环境变量读取数据库连接信息(配置不写死)"""
    return mysql.connector.connect(
        host=os.getenv("DB_HOST", "db"),
        port=int(os.getenv("DB_PORT", "3306")),
        user=os.getenv("DB_USER", "root"),
        password=os.getenv("DB_PASSWORD", "root123"),
        database=os.getenv("DB_NAME", "fde_db"),
    )


@app.get("/")
def root():
    return {"msg": "FDE Stack", "services": ["api", "mysql"]}


@app.get("/health")
def health():
    """健康检查:API 活着 + 数据库连得上"""
    try:
        conn = get_db()
        conn.ping()
        conn.close()
        return {"status": "ok", "db": "connected"}
    except Exception as e:
        return {"status": "degraded", "db": str(e)}


@app.get("/devices")
def list_devices():
    conn = get_db()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("SELECT id, name, type, temperature FROM devices LIMIT 10")
    rows = cursor.fetchall()
    conn.close()
    return {"devices": rows, "count": len(rows)}


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

requirements.txt

复制代码
fastapi==0.115.0
uvicorn==0.30.0
mysql-connector-python==9.1.0

Dockerfile(昨天的,直接用):

复制代码
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
    -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . .
EXPOSE 8000
CMD ["python", "main.py"]

第 2 步:init.sql(数据库建表 + 初始数据)

MySQL 官方镜像有个贴心机制:容器第一次启动时,会自动执行 /docker-entrypoint-initdb.d/ 目录下的 .sql 文件。我们把建表语句放进去,数据库一就绪就自动初始化。

复制代码
-- init.sql:首次启动自动执行
CREATE TABLE IF NOT EXISTS devices (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    type VARCHAR(20) NOT NULL,
    temperature DECIMAL(5,1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO devices (name, type, temperature) VALUES
('注塑机A1', '注塑', 65.0),
('注塑机A2', '注塑', 82.0),
('注塑机A3', '注塑', 91.0),
('冲压机B1', '冲压', 75.0),
('冲压机B2', '冲压', 88.0);

第 3 步:docker-compose.yml(核心)

复制代码
# ==========================================
# FDE 技术栈:FastAPI + MySQL
# ==========================================
services:

  # ---------- 服务 1:API ----------
  api:
    build: .                       # 不用现成镜像,用当前目录 Dockerfile 现场构建
    container_name: fde-api
    ports:
      - "8000:8000"
    environment:                   # 注入容器的环境变量
      DB_HOST: db                  # ⭐ 主机名直接写服务名 db!
      DB_PORT: 3306
      DB_USER: root
      DB_PASSWORD: root123
      DB_NAME: fde_db
    depends_on:                    # 依赖:先启动 db,再启动 api
      - db
    restart: unless-stopped        # 容器挂了/机器重启后自动拉起

  # ---------- 服务 2:MySQL 数据库 ----------
  db:
    image: mysql:8.0               # 直接用官方镜像,不用自己 build
    container_name: fde-mysql
    environment:
      MYSQL_ROOT_PASSWORD: root123   # root 密码(必填)
      MYSQL_DATABASE: fde_db         # 启动时自动创建这个数据库
    ports:
      - "3306:3306"
    volumes:
      # 命名卷:数据库数据持久化(容器删了数据不丢)
      - db_data:/var/lib/mysql
      # 绑定挂载:把初始化脚本放进镜像规定的目录
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped

# 顶层声明用到的命名卷(Compose 会自动创建)
volumes:
  db_data:

第 4 步:一键启动

复制代码
docker compose up -d --build
# --build:启动前先根据 Dockerfile 构建 api 镜像
# 首次会拉 mysql:8.0 镜像(几百MB,耐心等)

观察启动过程:

复制代码
[+] Running 4/4
 ✔ Network fde_stack_default      Created
 ✔ Volume "fde_stack_db_data"     Created
 ✔ Container fde-mysql            Started
 ✔ Container fde-api              Started

看状态:

复制代码
docker compose ps
# NAME         STATUS         PORTS
# fde-api      Up 5 seconds   0.0.0.0:8000->8000/tcp
# fde-mysql    Up 8 seconds   0.0.0.0:3306->3306/tcp

⚠️ 第一次启动 MySQL 需要 10~30 秒初始化。API 可能比数据库先就绪而连接失败,下一节专门讲怎么处理。先等半分钟再验证。

第 5 步:验证整条链路

复制代码
# ① API 自己活着
curl http://localhost:8000/
# {"msg":"FDE Stack","services":["api","mysql"]}

# ② API 能连上数据库
curl http://localhost:8000/health
# {"status":"ok","db":"connected"}

# ③ 数据库里的初始数据能通过 API 查出来
curl http://localhost:8000/devices
# {"devices":[{"id":1,"name":"注塑机A1",...},...],"count":5}

通了! 一条 docker compose up,应用和数据库两个容器全部就位、自动建库建表、网络互通。这就是编排的威力。


📖 四、核心机制:服务名就是主机名

上面配置里最神奇的一行是 DB_HOST: db------为什么主机名写 db 就行?IP 都不用知道?

复制代码
┌────────────────────────────────────────────────────────┐
│  Compose 自动创建一个专用网络,把所有服务接进去          │
│  并提供一个内置 DNS:服务名 ↔ 容器 IP 自动解析           │
│                                                        │
│   容器 api 想连数据库:                                  │
│   代码写 host="db"                                     │
│        │                                               │
│        ▼                                               │
│   内置 DNS:db 是哪个容器?→ fde-mysql 的内网 IP        │
│        │                                               │
│        ▼                                               │
│   api ───────────────────────────────► fde-mysql:3306  │
│                                                        │
│   服务名 db 来自 compose 文件里 db: 这个 key            │
└────────────────────────────────────────────────────────┘

📌 关键认知 :同一 Compose 网络里的容器,互相访问时主机名直接写服务名dbapi),端口写容器内端口(3306,不是映射到宿主机的那个)。容器 IP 会变,但服务名永不过期------这比写死 IP 靠谱一万倍。

注意区分:你在Windows 浏览器 访问 API 用 localhost:8000(走端口映射);容器之间 互通用 服务名:容器端口(走内部网络,不需要 ports 映射)。


📖 五、depends_on 的坑:启动了 ≠ 就绪了

你可能发现了:刚 up 的头几秒,/health 可能报数据库连不上。原因在于 depends_on 的真实语义:

复制代码
  depends_on:
    - db

  它只保证【启动顺序】:db 容器先启动,api 容器后启动
  它【不保证】db 已经可以接受连接!

  时间线:
  0s   db 容器启动(mysqld 进程开始初始化,要 20 秒)
  1s   api 容器启动,立刻去连 db:3306 → 拒绝连接 ❌
  20s  MySQL 才真正就绪

三种应对方法,从简到优:

方法 1:API 加重试(最实用,推荐)

让应用连接数据库时带重试逻辑------连不上等几秒再试。生产应用本来就该有这个容错。可以用 restart: unless-stopped 让 api 容器崩溃后自动重启,直到数据库就绪。

方法 2:Compose 的健康检查条件(V2 支持)

给 db 配 healthcheck,让 api 等数据库"真正健康"再启动:

复制代码
  db:
    image: mysql:8.0
    # ... 其他配置
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-proot123"]
      interval: 5s
      timeout: 5s
      retries: 10

  api:
    # ... 其他配置
    depends_on:
      db:
        condition: service_healthy    # 等 db 健康检查通过才启动

方法 3:自己 sleep(土办法,不推荐)

复制代码
  api:
    command: sh -c "sleep 20 && python main.py"

💡 FDE 实操建议:学习阶段用方法 1(重启策略 + 应用重试)最简单;正式交付推荐方法 2(healthcheck + condition),语义最准确。


📖 六、docker-compose.yml 配置项速查

配置项 作用 对应 docker run
image 用现成镜像 直接写镜像名
build: . 从 Dockerfile 构建 先 build 再 run
container_name 容器名 --name
ports 宿主机:容器端口映射 -p
volumes 数据卷/绑定挂载 -v
environment 环境变量(键值对) -e
env_file 从文件批量读环境变量 --env-file
depends_on 启动顺序/就绪依赖 无(手工控制)
restart 重启策略 --restart
networks 自定义网络 --network
command 覆盖镜像默认启动命令 镜像名后的命令
working_dir 工作目录 -w

环境变量的两种安全写法

写法 A:直接写在 yml 里(学习用,简单直观,就是你现在用的)

复制代码
    environment:
      DB_PASSWORD: root123

写法 B:敏感信息用 .env 文件,别提交到 Git(生产推荐)

项目根目录建 .env

复制代码
DB_PASSWORD=root123
MYSQL_ROOT_PASSWORD=root123

compose 文件里用 ${变量名} 引用:

复制代码
  db:
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}

.env 加进 .gitignore.dockerignore,密码就不会进版本库。再提供一个 .env.example(不含真实密码的模板)给同事参考。

📌 12-Factor 原则:配置(尤其是密码、地址等随环境变化的东西)通过环境变量注入,而不是写死在代码里。这样同一份镜像,开发/测试/生产环境靠不同环境变量切换,镜像本身一个字都不用改。


🖥️ 七、Compose 常用命令全掌握

复制代码
# ---------- 生命周期 ----------
docker compose up -d              # 构建+后台启动整套服务
docker compose up -d --build      # 强制重新构建镜像后启动(代码更新后用)
docker compose down               # 停止并删除容器+网络(卷保留,数据还在)
docker compose down -v            # ⚠️ 连数据卷一起删(数据库数据清空!)
docker compose stop               # 停止(容器保留,可 start)
docker compose start              # 启动已停止的
docker compose restart            # 重启所有服务
docker compose restart api        # 只重启 api 一个服务

# ---------- 查看 ----------
docker compose ps                 # 服务状态
docker compose logs -f            # 所有服务实时日志
docker compose logs -f api        # 只看 api
docker compose logs --tail=20 db  # db 最后 20 行
docker compose top                # 各容器里跑的进程

# ---------- 执行 ----------
docker compose exec api bash      # 进入 api 容器
docker compose exec db mysql -uroot -proot123 fde_db   # 直接进 MySQL 命令行
docker compose build              # 只构建镜像,不启动

数据持久化验证(重要实验)

复制代码
# ① 通过 API 插入一条数据(用 mysql 客户端或 exec 进去插)
docker compose exec db mysql -uroot -proot123 fde_db \
  -e "INSERT INTO devices (name,type,temperature) VALUES ('测试机X','测试',50);"

# ② down 销毁容器(注意:不加 -v)
docker compose down

# ③ 重新 up
docker compose up -d

# 等数据库就绪后查询
curl http://localhost:8000/devices
# 测试机X 还在!数据活在 db_data 卷里,与容器生死无关 ✅

这个实验一定要亲手做------它会让你彻底理解"容器是临时的,数据是持久的"。


📝 本课小结

知识点 一句话记住
Compose 作用 一个 yml 编排多个容器,up 一键起 down 一键灭
services 每个服务对应一个容器(api/db/...)
image vs build 现成镜像用 image,自己的应用用 build: .
ports 宿主机:容器 端口映射
volumes 命名卷持久化数据;绑定挂载挂配置/脚本
environment 注入环境变量,配置与代码分离
depends_on 只管启动顺序,不管是否就绪
服务名即主机名 容器互访写服务名:容器端口
自动网络 Compose 自动建网络和 DNS
数据初始化 MySQL 自动执行 initdb.d 下的 .sql
healthcheck 配合 condition: service_healthy 等就绪
down vs down -v 前者保留数据,后者清空数据卷
更新部署 改代码 → up -d --build 重建变动的服务

🧠 核心认知 :Compose 把"一套系统"作为管理单元。docker-compose.yml 就是你这套环境的唯一事实来源 ------它把"用哪些镜像、怎么连、数据放哪、什么顺序"全部声明清楚,纳入 Git 管理后,团队任何人、任何机器,一条 up 就能得到一模一样的环境。这就是"基础设施即代码"思想的入门。


📋 课后练习

练习 1:独立搭起双容器栈(约 40 分钟)

不看教程,新建目录完成 FastAPI + MySQL 的 Compose 编排:

  1. 准备 5 个文件(main.py / requirements.txt / Dockerfile / init.sql / docker-compose.yml)

  2. docker compose up -d --build 启动

  3. /health/devices 验证链路(数据库没就绪就稍等或重启 api)

  4. docker compose exec db mysql -uroot -p... 进数据库手动插一条设备,再通过 API 查到它

练习 2:持久化实验(约 15 分钟)

  1. 插入一条新设备,docker compose down(不加 -v),再 up

  2. 确认数据还在

  3. docker volume ls 找到这个项目的数据卷,说出它的命名规律(通常是 目录名_卷名

  4. 思考:什么情况下才该用 down -v

练习 3:加一个 phpMyAdmin 服务(约 25 分钟)

在 compose 文件里加第三个服务,用浏览器图形化管理 MySQL:

复制代码
  pma:
    image: phpmyadmin:latest
    container_name: fde-pma
    ports:
      - "8080:80"
    environment:
      PMA_HOST: db              # 指向数据库的服务名
      PMA_PORT: 3306
    depends_on:
      - db
    restart: unless-stopped

启动后浏览器打开 http://localhost:8080,用 root / root123 登录,图形界面查看 fde_db 里的 devices 表。


🔭 下节预告

现在你的整套服务在 8000、3306、8080 各种端口上跑。明天补两大块拼图:

  1. Nginx 反向代理:让用户访问标准 80 端口就能打到你的 API,顺便学会负载均衡的原理

  2. Git 版本控制:你的代码、Dockerfile、compose 文件都需要版本管理------提交历史、分支、回滚、推送远程仓库,告别"文件夹复制改名"式备份

学完明天,"部署"和"代码管理"两件事的工具链就齐了。明天见!


🌍附录:前置课程列表

阶段一:认知启蒙(AI 认知与 FDE 角色)
AI 认知

【FDE系列】阶段1Day 1:AI 层级关系 --- 四个嵌套的圈-CSDN博客

【FDE系列】阶段1Day 2:AI 三阶段发展史 --- 会认 → 会判断 → 会创造-CSDN博客

【FDE系列】阶段1Day 3:符号 AI vs 机器学习 --- 两条路线的本质区别-CSDN博客

【FDE系列】阶段1Day 4:Transformer 的历史意义 --- 2017 年的分水岭-CSDN博客

【FDE系列】阶段1Day 5:本周复习与自测 --- 检验你的 AI 认知地基-CSDN博客

【FDE系列】阶段1Day 6:Transformer 架构 --- 一张图纸盖出千千万万栋楼-CSDN博客

【FDE系列】阶段1Day 7:LLM 本质 --- 文字接龙机器-CSDN博客

【FDE系列】阶段1Day 8:Token --- 模型眼中的最小单位-CSDN博客

【FDE系列】阶段1Day 9:AI 幻觉 --- 为什么会一本正经地胡说八道-CSDN博客

【FDE系列】阶段1Day 10:上下文窗口 --- 模型的记忆力上限 + 本周复习-CSDN博客

【FDE系列】阶段1Day 11:Prompt --- 给模型立规矩-CSDN博客

【FDE系列】阶段1Day 12:Memory --- 让模型记住上下文

【FDE系列】阶段1Day 13:RAG --- 给模型配图书管理员-CSDN博客

【FDE系列】阶段1Day 14:Tool Use --- 让模型动手操作-CSDN博客

【FDE系列】阶段1Day 15:MCP --- 统一的工具接口标准 + 第三周复习-CSDN博客

FDE 基础概念

【FDE系列】阶段1Day 16:什么是 FDE --- 把 AI 变成客户结果的人-CSDN博客

【FDE系列】阶段1Day 17:FDE vs 传统实施 --- 三大本质区别-CSDN博客

【FDE系列】阶段1Day 18:FDE 三重身份 + C6 胜任力模型-CSDN博客

【FDE系列】阶段1Day 19:七阶段行动路径 + 行业经验的价值-CSDN博客

【FDE系列】阶段1Day 20:阶段总结与产出物 --- 第一阶段收官-CSDN博客


阶段二:技术地基(Python + FastAPI + SQL + Docker + API 集成)
Python基础

【FDE系列】阶段2:Day 21:Python 环境搭建 --- 写出你的第一行代码-CSDN博客

【FDE系列】阶段2:Day 22:变量、数据类型、条件判断 --- Python 的"记忆"和"判断"-CSDN博客

【FDE系列】阶段2:Day 23:循环与函数 --- 让代码跑 100 遍、把逻辑打包复用-CSDN博客

【FDE系列】阶段2:Day 24:数据结构 --- 列表、字典、集合、元组-CSDN博客

【FDE系列】阶段2:Day 25:文件读写与 JSON --- 让程序连通外部数据(第一周收官)-CSDN博客

【FDE系列】阶段2:Day 26:模块化编程 --- 把代码拆成"抽屉柜"-CSDN博客

【FDE系列】阶段2:Day 27:异常处理与日志 --- 让程序"摔不烂、查得到"-CSDN博客

FastAPI入门到进阶

【FDE系列】阶段2:Day 28:FastAPI 入门 --- 把你的函数变成 API 服务-CSDN博客

【FDE系列】阶段2:Day 29:FastAPI 进阶 --- Pydantic 模型与完整 CRUD 实战-CSDN博客

【FDE系列】阶段2:Day 30:生产代码规范 --- 测试、类型注解、配置管理(第二周收官)-CSDN博客

SQL基础

【FDE系列】阶段2:Day 31:SQL 基础 --- 增删改查一把梭-CSDN博客

【FDE系列】阶段2:Day 32:多表查询 --- JOIN 与聚合-CSDN博客

【FDE系列】阶段2:Day 33:进阶查询 --- 窗口函数与 CTE-CSDN博客

【FDE系列】阶段2:Day 34:数据清洗 --- 把脏数据捋干净-CSDN博客

【FDE系列】阶段2:Day 35:Python + SQL --- 工单接入 MySQL + 本周收官-CSDN博客

Linux基础

【FDE系列】阶段2:Day 36:Linux 入门与文件操作 --- 扔掉鼠标的第一天-CSDN博客

【FDE系列】阶段2:Day 37:权限、进程与文本三剑客-CSDN博客

【FDE系列】阶段2:Day 38:Shell 脚本 --- 把命令串起来自动跑-CSDN博客

【FDE系列】阶段2:Day 39:Linux 综合实战 --- 让服务无人值守-CSDN博客

【FDE系列】阶段2:Day 40:Shell 进阶 --- 生产级脚本与本周收官-CSDN博客

Docker

【FDE系列】阶段2:Day 41:Docker 入门 --- 把环境装进盒子-CSDN博客

【FDE系列】阶段2:Day 42:Dockerfile 实战 --- 把你的应用打包成镜像-CSDN博客

相关推荐
YOLO数据集集合1 小时前
天空红外小目标检测数据集 | 红外小目标 天空目标检测 无人机检测 鸟类识别 低空安防9099期
人工智能·目标检测·计算机视觉·目标跟踪·无人机·无人机视角·直升机检测
徐健峰1 小时前
Windows 安装 Codex CLI 教程:npm 安装、首次登录与常见报错排查【无图精华版】
人工智能·gpt
微三云 - 廖会灵 (私域系统开发)1 小时前
企业大模型应用工程化思考:跳出 Demo 陷阱,构建「业务‑资产‑Agent」三层落地架构
人工智能·矩阵·重构
IamZJT_1 小时前
03| 新消息来了:让 Demo 会追问、等待和继续调查
人工智能
Ai-_Man1 小时前
您您这可以把Mistral AI的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。
人工智能·ai·小程序·电脑
IamZJT_1 小时前
Agent 系统工程 05|上下文压缩以后,怎样知道关键信息有没有丢?
人工智能
花间相见1 小时前
【计算基础|网络04】—— HTTP接口实战(下):接口测试、鉴权与跨域排错
java·linux·人工智能·后端·python·计算机网络·postman
suaizai_1 小时前
AI编程新范式:6大MCP工具实战揭秘
人工智能