用html+css+js 写一个Docker 教程

图:

代码:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Docker 教程 - FastAPI 容器化</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        :root {
            --primary: #2496ed;
            --secondary: #0db7ed;
            --dark: #1d2733;
            --light: #f5f8fa;
            --success: #28a745;
            --warning: #ffc107;
            --danger: #dc3545;
            --shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }

        body {
            background: linear-gradient(135deg, #f0f7ff 0%, #e6f7ff 100%);
            color: #333;
            line-height: 1.6;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 20px;
        }

        /* Header Styles */
        header {
            background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
            color: white;
            padding: 1rem 0;
            box-shadow: var(--shadow);
            position: sticky;
            top: 0;
            z-index: 100;
        }

        .header-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .logo {
            display: flex;
            align-items: center;
            gap: 15px;
        }

        .logo i {
            font-size: 2.5rem;
        }

        .logo-text {
            font-size: 1.8rem;
            font-weight: 700;
            letter-spacing: 1px;
        }

        nav ul {
            display: flex;
            list-style: none;
            gap: 25px;
        }

        nav a {
            color: white;
            text-decoration: none;
            font-weight: 600;
            padding: 8px 15px;
            border-radius: 5px;
            transition: all 0.3s ease;
        }

        nav a:hover, nav a.active {
            background: rgba(255, 255, 255, 0.2);
        }

        /* Hero Section */
        .hero {
            background: linear-gradient(rgba(29, 39, 51, 0.85), rgba(29, 39, 51, 0.9)), url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><rect width="100" height="100" fill="%231d2733"/><path d="M0 50 L100 50 M50 0 L50 100" stroke="%232496ed" stroke-width="1" opacity="0.2"/></svg>');
            background-size: cover;
            color: white;
            padding: 5rem 0;
            text-align: center;
        }

        .hero h1 {
            font-size: 3.5rem;
            margin-bottom: 1.5rem;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }

        .hero p {
            font-size: 1.3rem;
            max-width: 800px;
            margin: 0 auto 2rem;
            opacity: 0.9;
        }

        .cta-button {
            display: inline-block;
            background: var(--success);
            color: white;
            padding: 12px 30px;
            border-radius: 30px;
            font-weight: 700;
            text-decoration: none;
            font-size: 1.1rem;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3);
        }

        .cta-button:hover {
            background: #218838;
            transform: translateY(-3px);
            box-shadow: 0 6px 20px rgba(40, 167, 69, 0.4);
        }

        /* Main Content */
        .content-section {
            padding: 4rem 0;
        }

        .section-title {
            text-align: center;
            margin-bottom: 3rem;
            color: var(--dark);
            font-size: 2.5rem;
            position: relative;
        }

        .section-title:after {
            content: '';
            display: block;
            width: 80px;
            height: 4px;
            background: linear-gradient(90deg, var(--primary), var(--secondary));
            margin: 15px auto 0;
            border-radius: 2px;
        }

        .card-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 30px;
            margin-top: 2rem;
        }

        .card {
            background: white;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: var(--shadow);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }

        .card:hover {
            transform: translateY(-10px);
            box-shadow: 0 12px 20px rgba(0, 0, 0, 0.15);
        }

        .card-header {
            background: linear-gradient(135deg, var(--primary), var(--secondary));
            color: white;
            padding: 20px;
            font-weight: 700;
            font-size: 1.3rem;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .card-body {
            padding: 25px;
        }

        .card-body ul {
            list-style-type: none;
            padding-left: 0;
        }

        .card-body li {
            padding: 8px 0;
            border-bottom: 1px dashed #eee;
            display: flex;
            align-items: flex-start;
            gap: 10px;
        }

        .card-body li:last-child {
            border-bottom: none;
        }

        .card-body li i {
            color: var(--primary);
            margin-top: 5px;
        }

        /* Code Sections */
        .code-section {
            background: var(--dark);
            border-radius: 12px;
            overflow: hidden;
            margin: 3rem 0;
            box-shadow: var(--shadow);
        }

        .code-header {
            background: rgba(0, 0, 0, 0.3);
            padding: 12px 20px;
            color: white;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .code-content {
            padding: 20px;
            overflow-x: auto;
        }

        pre {
            color: #f8f8f2;
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 1rem;
            line-height: 1.5;
        }

        .command {
            color: #a6e22e;
        }

        .comment {
            color: #75715e;
        }

        .option {
            color: #66d9ef;
        }

        .yaml-key {
            color: #cc7832;
        }

        .yaml-value {
            color: #a5c261;
        }

        .yaml-string {
            color: #a5c261;
        }

        .copy-btn {
            background: rgba(255, 255, 255, 0.1);
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s;
            font-size: 0.9rem;
        }

        .copy-btn:hover {
            background: rgba(255, 255, 255, 0.2);
        }

        /* Interactive Demo */
        .demo-container {
            background: white;
            border-radius: 12px;
            padding: 30px;
            box-shadow: var(--shadow);
            margin: 3rem 0;
        }

        .demo-title {
            text-align: center;
            margin-bottom: 25px;
            color: var(--dark);
        }

        .terminal {
            background: #1e1e1e;
            border-radius: 8px;
            padding: 20px;
            font-family: 'Consolas', monospace;
            color: #d4d4d4;
            min-height: 200px;
            max-height: 400px;
            overflow-y: auto;
            position: relative;
        }

        .terminal-header {
            display: flex;
            gap: 8px;
            margin-bottom: 15px;
        }

        .terminal-btn {
            width: 12px;
            height: 12px;
            border-radius: 50%;
        }

        .terminal-btn.red { background: #ff5f56; }
        .terminal-btn.yellow { background: #ffbd2e; }
        .terminal-btn.green { background: #27ca3f; }

        .terminal-content {
            margin-top: 10px;
        }

        .terminal-line {
            margin-bottom: 8px;
            display: flex;
        }

        .prompt {
            color: #4ec9b0;
            margin-right: 8px;
        }

        .user-input {
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid #444;
            color: white;
            padding: 8px 12px;
            border-radius: 4px;
            width: 100%;
            margin-top: 15px;
            font-family: 'Consolas', monospace;
        }

        .demo-controls {
            display: flex;
            gap: 15px;
            margin-top: 20px;
            flex-wrap: wrap;
        }

        .demo-btn {
            flex: 1;
            min-width: 150px;
            padding: 10px 15px;
            background: var(--primary);
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.2s;
        }

        .demo-btn:hover {
            background: #1a7bc0;
            transform: translateY(-2px);
        }

        .demo-btn.secondary {
            background: #6c757d;
        }

        .demo-btn.secondary:hover {
            background: #5a6268;
        }

        /* Footer */
        footer {
            background: var(--dark);
            color: white;
            padding: 3rem 0 1.5rem;
            margin-top: 4rem;
        }

        .footer-content {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 30px;
            margin-bottom: 2rem;
        }

        .footer-column h3 {
            margin-bottom: 1.5rem;
            font-size: 1.3rem;
            position: relative;
            padding-bottom: 10px;
        }

        .footer-column h3:after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 40px;
            height: 3px;
            background: var(--primary);
        }

        .footer-column ul {
            list-style: none;
        }

        .footer-column li {
            margin-bottom: 10px;
        }

        .footer-column a {
            color: #ccc;
            text-decoration: none;
            transition: color 0.2s;
        }

        .footer-column a:hover {
            color: white;
        }

        .copyright {
            text-align: center;
            padding-top: 2rem;
            border-top: 1px solid rgba(255, 255, 255, 0.1);
            color: #aaa;
            font-size: 0.9rem;
        }

        /* Responsive */
        @media (max-width: 768px) {
            .header-content {
                flex-direction: column;
                gap: 15px;
            }

            nav ul {
                flex-wrap: wrap;
                justify-content: center;
            }

            .hero h1 {
                font-size: 2.5rem;
            }

            .hero p {
                font-size: 1.1rem;
            }

            .demo-controls {
                flex-direction: column;
            }

            .demo-btn {
                width: 100%;
            }
        }

        /* Animation */
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .card, .code-section, .demo-container {
            animation: fadeIn 0.5s ease forwards;
        }

        .card:nth-child(1) { animation-delay: 0.1s; }
        .card:nth-child(2) { animation-delay: 0.2s; }
        .card:nth-child(3) { animation-delay: 0.3s; }
        .card:nth-child(4) { animation-delay: 0.4s; }
        .card:nth-child(5) { animation-delay: 0.5s; }
        .card:nth-child(6) { animation-delay: 0.6s; }
    </style>
</head>
<body>
    <!-- Header -->
    <header>
        <div class="container header-content">
            <div class="logo">
                <i class="fab fa-docker"></i>
                <div class="logo-text">Docker教程</div>
            </div>
            <nav>
                <ul>
                    <li><a href="#" class="active">首页</a></li>
                    <li><a href="#concepts">基本概念</a></li>
                    <li><a href="#commands">常用命令</a></li>
                    <li><a href="#dockerfile">Dockerfile</a></li>
                    <li><a href="#yml">Docker Compose</a></li>
                    <li><a href="#demo">交互演示</a></li>
                </ul>
            </nav>
        </div>
    </header>

    <!-- Hero Section -->
    <section class="hero">
        <div class="container">
            <h1>掌握 Docker 容器化技术</h1>
            <p>从入门到精通的完整指南,学习如何使用 Docker 构建、部署和运行应用程序</p>
            <a href="#concepts" class="cta-button">开始学习 <i class="fas fa-arrow-right"></i></a>
        </div>
    </section>

    <!-- Concepts Section -->
    <section id="concepts" class="content-section">
        <div class="container">
            <h2 class="section-title">Docker 核心概念</h2>
            <div class="card-grid">
                <div class="card">
                    <div class="card-header"><i class="fas fa-box"></i> 镜像 (Image)</div>
                    <div class="card-body">
                        <ul>
                            <li><i class="fas fa-check-circle"></i> Docker镜像是只读模板</li>
                            <li><i class="fas fa-check-circle"></i> 包含运行应用所需的全部内容</li>
                            <li><i class="fas fa-check-circle"></i> 基于UnionFS的分层结构</li>
                            <li><i class="fas fa-check-circle"></i> 可从Docker Hub获取</li>
                        </ul>
                    </div>
                </div>
                <div class="card">
                    <div class="card-header"><i class="fas fa-cube"></i> 容器 (Container)</div>
                    <div class="card-body">
                        <ul>
                            <li><i class="fas fa-check-circle"></i> 镜像的运行实例</li>
                            <li><i class="fas fa-check-circle"></i> 轻量级且隔离的环境</li>
                            <li><i class="fas fa-check-circle"></i> 可以启动、停止和删除</li>
                            <li><i class="fas fa-check-circle"></i> 每个容器相互隔离</li>
                        </ul>
                    </div>
                </div>
                <div class="card">
                    <div class="card-header"><i class="fas fa-warehouse"></i> 仓库 (Registry)</div>
                    <div class="card-body">
                        <ul>
                            <li><i class="fas fa-check-circle"></i> 存储和分发镜像的服务</li>
                            <li><i class="fas fa-check-circle"></i> Docker Hub是公共仓库</li>
                            <li><i class="fas fa-check-circle"></i> 支持私有仓库部署</li>
                            <li><i class="fas fa-check-circle"></i> 类似GitHub的镜像管理</li>
                        </ul>
                    </div>
                </div>
                <div class="card">
                    <div class="card-header"><i class="fas fa-file-code"></i> Dockerfile</div>
                    <div class="card-body">
                        <ul>
                            <li><i class="fas fa-check-circle"></i> 构建镜像的脚本文件</li>
                            <li><i class="fas fa-check-circle"></i> 包含构建指令和元数据</li>
                            <li><i class="fas fa-check-circle"></i> 支持分层构建和缓存</li>
                            <li><i class="fas fa-check-circle"></i> 实现自动化构建流程</li>
                        </ul>
                    </div>
                </div>
                <div class="card">
                    <div class="card-header"><i class="fas fa-network-wired"></i> 网络 (Network)</div>
                    <div class="card-body">
                        <ul>
                            <li><i class="fas fa-check-circle"></i> 容器间通信机制</li>
                            <li><i class="fas fa-check-circle"></i> 支持多种网络驱动</li>
                            <li><i class="fas fa-check-circle"></i> 容器IP隔离与发现</li>
                            <li><i class="fas fa-check-circle"></i> 端口映射实现外部访问</li>
                        </ul>
                    </div>
                </div>
                <div class="card">
                    <div class="card-header"><i class="fas fa-boxes"></i> 数据卷 (Volume)</div>
                    <div class="card-body">
                        <ul>
                            <li><i class="fas fa-check-circle"></i> 持久化容器数据</li>
                            <li><i class="fas fa-check-circle"></i> 独立于容器生命周期</li>
                            <li><i class="fas fa-check-circle"></i> 高效的数据共享</li>
                            <li><i class="fas fa-check-circle"></i> 支持本地和云存储</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Commands Section -->
    <section id="commands" class="content-section" style="background: #f8f9fa;">
        <div class="container">
            <h2 class="section-title">常用 Docker 命令</h2>

            <div class="code-section">
                <div class="code-header">
                    <span>镜像操作</span>
                    <button class="copy-btn" onclick="copyCode('image-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="image-code"><span class="comment"># 从仓库拉取镜像</span>
<span class="command">docker pull</span> <span class="option">[镜像名]:[标签]</span>

<span class="comment"># 列出本地镜像</span>
<span class="command">docker images</span>

<span class="comment"># 构建镜像</span>
<span class="command">docker build</span> <span class="option">-t [镜像名]:[标签] [Dockerfile路径]</span>

<span class="comment"># 删除镜像</span>
<span class="command">docker rmi</span> <span class="option">[镜像ID或名称]</span>

<span class="comment"># 查看镜像历史</span>
<span class="command">docker history</span> <span class="option">[镜像名]</span></pre>
                </div>
            </div>

            <div class="code-section">
                <div class="code-header">
                    <span>容器操作</span>
                    <button class="copy-btn" onclick="copyCode('container-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="container-code"><span class="comment"># 创建并启动容器</span>
<span class="command">docker run</span> <span class="option">-d --name [容器名] [镜像名]</span>

<span class="comment"># 列出运行中的容器</span>
<span class="command">docker ps</span>

<span class="comment"># 列出所有容器</span>
<span class="command">docker ps -a</span>

<span class="comment"># 停止容器</span>
<span class="command">docker stop</span> <span class="option">[容器名或ID]</span>

<span class="comment"># 启动已停止的容器</span>
<span class="command">docker start</span> <span class="option">[容器名或ID]</span>

<span class="comment"># 删除容器</span>
<span class="command">docker rm</span> <span class="option">[容器名或ID]</span>

<span class="comment"># 查看容器日志</span>
<span class="command">docker logs</span> <span class="option">[容器名或ID]</span>

<span class="comment"># 进入容器终端</span>
<span class="command">docker exec</span> <span class="option">-it [容器名或ID] /bin/bash</span></pre>
                </div>
            </div>

            <div class="code-section">
                <div class="code-header">
                    <span>容器与主机交互</span>
                    <button class="copy-btn" onclick="copyCode('interact-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="interact-code"><span class="comment"># 端口映射 (-p 主机端口:容器端口)</span>
<span class="command">docker run</span> <span class="option">-d -p 8080:80 nginx</span>

<span class="comment"># 挂载数据卷 (-v 主机目录:容器目录)</span>
<span class="command">docker run</span> <span class="option">-v /host/path:/container/path [镜像名]</span>

<span class="comment"># 设置环境变量 (-e)</span>
<span class="command">docker run</span> <span class="option">-e "ENV_VAR=value" [镜像名]</span>

<span class="comment"># 查看容器详细信息</span>
<span class="command">docker inspect</span> <span class="option">[容器名或ID]</span></pre>
                </div>
            </div>
        </div>
    </section>

    <!-- Dockerfile Section -->
    <section id="dockerfile" class="content-section">
        <div class="container">
            <h2 class="section-title">Dockerfile 示例</h2>
            <p style="text-align: center; max-width: 800px; margin: 0 auto 2rem; font-size: 1.1rem;">
                Dockerfile 是一个文本文件,包含构建镜像的所有指令。以下是一个FastAPI应用的Dockerfile示例(使用国内淘宝镜像源):
            </p>

            <div class="code-section">
                <div class="code-header">
                    <span>FastAPI 应用 Dockerfile(国内淘宝源)</span>
                    <button class="copy-btn" onclick="copyCode('dockerfile-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="dockerfile-code"><span class="comment"># 使用官方Python运行时作为父镜像</span>
<span class="command">FROM</span> python:3.11-slim

<span class="comment"># 设置工作目录</span>
<span class="command">WORKDIR</span> /app

<span class="comment"># 复制依赖文件</span>
<span class="command">COPY</span> requirements.txt .

<span class="comment"># 安装应用依赖(使用国内淘宝镜像源加速)</span>
<span class="command">RUN</span> pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

<span class="comment"># 复制应用源代码</span>
<span class="command">COPY</span> . .

<span class="comment"># 暴露端口8000</span>
<span class="command">EXPOSE</span> 8000

<span class="comment"># 定义容器启动时运行的命令</span>
<span class="command">CMD</span> ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]</pre>
                </div>
            </div>

            <div class="code-section">
                <div class="code-header">
                    <span>requirements.txt 示例(国内淘宝源)</span>
                    <button class="copy-btn" onclick="copyCode('requirements-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="requirements-code"><span class="comment"># FastAPI 应用依赖(使用阿里云镜像源)</span>
<span class="comment"># 安装命令: pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/</span>

fastapi==0.104.1
uvicorn[standard]==0.24.0
pydantic==2.5.0
python-multipart==0.0.6

<span class="comment"># 可选:数据库相关</span>
# sqlalchemy==2.0.23
# alembic==1.12.1

<span class="comment"># 可选:测试相关</span>
# pytest==7.4.3
# httpx==0.25.1</pre>
                </div>
            </div>

            <div class="code-section">
                <div class="code-header">
                    <span>应用结构示例</span>
                    <button class="copy-btn" onclick="copyCode('structure-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="structure-code"><span class="comment"># 项目目录结构</span>
my-fastapi-app/
├── app/
│   ├── __init__.py
│   ├── main.py          <span class="comment"># FastAPI 主应用文件</span>
│   ├── models.py        <span class="comment"># 数据模型</span>
│   ├── routes.py        <span class="comment"># API 路由</span>
│   └── database.py      <span class="comment"># 数据库连接</span>
├── tests/
│   ├── __init__.py
│   └── test_main.py     <span class="comment"># 测试文件</span>
├── .env                 <span class="comment"># 环境变量</span>
├── .gitignore
├── Dockerfile
├── docker-compose.yml   <span class="comment"># 可选:多容器编排</span>
├── requirements.txt
└── README.md

<span class="comment"># main.py 示例</span>
from fastapi import FastAPI

app = FastAPI(title="My FastAPI App")

@app.get("/")
def read_root():
    return {"message": "Hello, Dockerized FastAPI!"}

@app.get("/health")
def health_check():
    return {"status": "healthy"}</pre>
                </div>
            </div>
        </div>
    </section>

    <!-- Docker Compose Section -->
    <section id="yml" class="content-section" style="background: #f8f9fa;">
        <div class="container">
            <h2 class="section-title">Docker Compose 示例</h2>
            <p style="text-align: center; max-width: 800px; margin: 0 auto 2rem; font-size: 1.1rem;">
                Docker Compose 用于定义和运行多容器应用。以下是一个包含FastAPI、PostgreSQL和Redis的docker-compose.yml示例:
            </p>

            <div class="code-section">
                <div class="code-header">
                    <span>docker-compose.yml 示例(使用国内源)</span>
                    <button class="copy-btn" onclick="copyCode('compose-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="compose-code"><span class="comment"># docker-compose.yml 版本定义</span>
<span class="command">version:</span> <span class="yaml-string">'3.8'</span>

<span class="comment">#服务定义</span>
<span class="command">services:</span>
  <span class="comment"># FastAPI 应用服务</span>
  <span class="command">app:</span>
    <span class="comment"># 使用当前目录的Dockerfile构建镜像</span>
    <span class="command">build:</span> <span class="yaml-string">.</span>
    <span class="comment">#容器名称</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-app</span>
    <span class="comment"># 端口映射</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"8000:8000"</span>
    <span class="comment"># 环境变量</span>
    <span class="command">environment:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">DATABASE_URL=postgresql://postgres:password@db:5432/fastapi_db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">REDIS_URL=redis://redis:6379/0</span>
      <span class="yaml-string">-</span> <span class="yaml-string">PYTHONUNBUFFERED=1</span>
    <span class="comment"># 依赖关系</span>
    <span class="command">depends_on:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">redis</span>
    <span class="comment">#重启策略</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>
    <span class="comment"># 挂载卷(用于开发环境)</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">./app:/app</span>

  <span class="comment"># PostgreSQL 数据库服务</span>
  <span class="command">db:</span>
    <span class="command">image:</span> <span class="yaml-string">postgres:15-alpine</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-db</span>
    <span class="command">environment:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_DB=fastapi_db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_USER=postgres</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_PASSWORD=password</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"5432:5432"</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">postgres_data:/var/lib/postgresql/data</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>

  <span class="comment"># Redis 缓存服务</span>
  <span class="command">redis:</span>
    <span class="command">image:</span> <span class="yaml-string">redis:7-alpine</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-redis</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"6379:6379"</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">redis_data:/data</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>

<span class="comment"># 定义命名卷</span>
<span class="command">volumes:</span>
  <span class="command">postgres_data:</span>
  <span class="command">redis_data:</span></pre>
                </div>
            </div>

            <div class="code-section">
                <div class="code-header">
                    <span>优化版 docker-compose.yml(生产环境)</span>
                    <button class="copy-btn" onclick="copyCode('compose-prod-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="compose-prod-code"><span class="comment"># docker-compose.yml 版本定义</span>
<span class="command">version:</span> <span class="yaml-string">'3.8'</span>

<span class="comment"># 服务定义</span>
<span class="command">services:</span>
  <span class="comment"># FastAPI 应用服务(生产环境)</span>
  <span class="command">app:</span>
    <span class="command">build:</span>
      <span class="command">context:</span> <span class="yaml-string">.</span>
      <span class="command">dockerfile:</span> <span class="yaml-string">Dockerfile.prod</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-app-prod</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"8000:8000"</span>
    <span class="command">environment:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">DATABASE_URL=postgresql://postgres:${DB_PASSWORD}@db:5432/fastapi_db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">REDIS_URL=redis://redis:6379/0</span>
      <span class="yaml-string">-</span> <span class="yaml-string">ENVIRONMENT=production</span>
      <span class="yaml-string">-</span> <span class="yaml-string">PYTHONUNBUFFERED=1</span>
    <span class="command">depends_on:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">redis</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>
    <span class="command">healthcheck:</span>
      <span class="command">test:</span> <span class="yaml-string">["CMD", "curl", "-f", "http://localhost:8000/health"]</span>
      <span class="command">interval:</span> <span class="yaml-string">30s</span>
      <span class="command">timeout:</span> <span class="yaml-string">10s</span>
      <span class="command">retries:</span> <span class="yaml-string">3</span>

  <span class="comment"># PostgreSQL 数据库服务(生产环境)</span>
  <span class="command">db:</span>
    <span class="command">image:</span> <span class="yaml-string">postgres:15-alpine</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-db-prod</span>
    <span class="command">environment:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_DB=fastapi_db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_USER=postgres</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_PASSWORD=${DB_PASSWORD}</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"5432:5432"</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">postgres_data:/var/lib/postgresql/data</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>
    <span class="command">healthcheck:</span>
      <span class="command">test:</span> <span class="yaml-string">["CMD-SHELL", "pg_isready -U postgres"]</span>
      <span class="command">interval:</span> <span class="yaml-string">30s</span>
      <span class="command">timeout:</span> <span class="yaml-string">10s</span>
      <span class="command">retries:</span> <span class="yaml-string">3</span>

  <span class="comment"># Redis 缓存服务(生产环境)</span>
  <span class="command">redis:</span>
    <span class="command">image:</span> <span class="yaml-string">redis:7-alpine</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-redis-prod</span>
    <span class="command">command:</span> <span class="yaml-string">redis-server --appendonly yes</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"6379:6379"</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">redis_data:/data</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>

<span class="comment"># 定义命名卷</span>
<span class="command">volumes:</span>
  <span class="command">postgres_data:</span>
  <span class="command">redis_data:</span></pre>
                </div>
            </div>

            <div class="code-section">
                <div class="code-header">
                    <span>开发环境 docker-compose.yml</span>
                    <button class="copy-btn" onclick="copyCode('compose-dev-code')">复制代码</button>
                </div>
                <div class="code-content">
                    <pre id="compose-dev-code"><span class="comment"># docker-compose.yml 版本定义</span>
<span class="command">version:</span> <span class="yaml-string">'3.8'</span>

<span class="comment"># 服务定义</span>
<span class="command">services:</span>
  <span class="comment"># FastAPI 应用服务(开发环境)</span>
  <span class="command">app:</span>
    <span class="command">build:</span> <span class="yaml-string">.</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-app-dev</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"8000:8000"</span>
    <span class="command">environment:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">DATABASE_URL=postgresql://postgres:password@db:5432/fastapi_db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">REDIS_URL=redis://redis:6379/0</span>
      <span class="yaml-string">-</span> <span class="yaml-string">ENVIRONMENT=development</span>
      <span class="yaml-string">-</span> <span class="yaml-string">PYTHONUNBUFFERED=1</span>
    <span class="command">depends_on:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">redis</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">./app:/app</span>
      <span class="yaml-string">-</span> <span class="yaml-string">./requirements.txt:/app/requirements.txt</span>
    <span class="command">command:</span> <span class="yaml-string">uvicorn main:app --host 0.0.0.0 --port 8000 --reload</span>

  <span class="comment"># PostgreSQL 数据库服务(开发环境)</span>
  <span class="command">db:</span>
    <span class="command">image:</span> <span class="yaml-string">postgres:15-alpine</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-db-dev</span>
    <span class="command">environment:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_DB=fastapi_db</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_USER=postgres</span>
      <span class="yaml-string">-</span> <span class="yaml-string">POSTGRES_PASSWORD=password</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"5432:5432"</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">postgres_data_dev:/var/lib/postgresql/data</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>

  <span class="comment"># Redis 缓存服务(开发环境)</span>
  <span class="command">redis:</span>
    <span class="command">image:</span> <span class="yaml-string">redis:7-alpine</span>
    <span class="command">container_name:</span> <span class="yaml-string">fastapi-redis-dev</span>
    <span class="command">ports:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">"6379:6379"</span>
    <span class="command">volumes:</span>
      <span class="yaml-string">-</span> <span class="yaml-string">redis_data_dev:/data</span>
    <span class="command">restart:</span> <span class="yaml-string">unless-stopped</span>

<span class="comment"># 定义命名卷(开发环境)</span>
<span class="command">volumes:</span>
  <span class="command">postgres_data_dev:</span>
  <span class="command">redis_data_dev:</span></pre>
                </div>
            </div>

            <div class="demo-container">
                <h3 class="demo-title">使用 Docker Compose 管理 FastAPI 应用</h3>
                <div class="terminal">
                    <div class="terminal-header">
                        <div class="terminal-btn red"></div>
                        <div class="terminal-btn yellow"></div>
                        <div class="terminal-btn green"></div>
                    </div>
                    <div class="terminal-content" id="compose-terminal-content">
                        <div class="terminal-line">
                            <span class="prompt">$</span> <span>ls -la</span>
                        </div>
                        <div class="terminal-line">
                            <span>total 32</span>
                        </div>
                        <div class="terminal-line">
                            <span>drwxr-xr-x  5 user user  160 Dec5 10:30 .</span>
                        </div>
                        <div class="terminal-line">
                            <span>drwxr-xr-x 15 user user  480 Dec  5 10:28 ..</span>
                        </div>
                        <div class="terminal-line">
                            <span>-rw-r--r--  1 user user  123 Dec  5 10:28 .env</span>
                        </div>
                        <div class="terminal-line">
                            <span>-rw-r--r--  1 user user  256 Dec  5 10:28 Dockerfile</span>
                        </div>
                        <div class="terminal-line">
                            <span>-rw-r--r--  1 user user  512 Dec  5 10:28 docker-compose.yml</span>
                        </div>
                        <div class="terminal-line">
                            <span>drwxr-xr-x  3 user user   96 Dec  5 10:28 app/</span>
                        </div>
                        <div class="terminal-line">
                            <span>-rw-r--r--  1 user user   45 Dec  5 10:28 requirements.txt</span>
                        </div>
                        <div class="terminal-line">
                            <span class="prompt">$</span> <span>docker-compose up -d</span>
                        </div>
                        <div class="terminal-line">
                            <span>Creating network "fastapi-app_default" with the default driver</span>
                        </div>
                        <div class="terminal-line">
                            <span>Creating volume "postgres_data" with default driver</span>
                        </div>
                        <div class="terminal-line">
                            <span>Creating volume "redis_data" with default driver</span>
                        </div>
                        <div class="terminal-line">
                            <span>Creating fastapi-db ... done</span>
                        </div>
                        <div class="terminal-line">
                            <span>Creating fastapi-redis ... done</span>
                        </div>
                        <div class="terminal-line">
                            <span>Creating fastapi-app ... done</span>
                        </div>
                        <div class="terminal-line">
                            <span class="prompt">$</span> <span>docker-compose ps</span>
                        </div>
                        <div class="terminal-line">
                            <span>NAME                COMMAND                  SERVICE STATUS          PORTS</span>
                        </div>
                        <div class="terminal-line">
                            <span>fastapi-app         "uvicorn main:app --..."   app       Up 5 seconds     0.0.0.0:8000->8000/tcp</span>
                        </div>
                        <div class="terminal-line">
                            <span>fastapi-db          "docker-entrypoint.s..."   db        Up 5 seconds     0.0.0.0:5432->5432/tcp</span>
                        </div>
                        <div class="terminal-line">
                            <span>fastapi-redis       "docker-entrypoint.s..."   redis     Up 5 seconds     0.0.0.0:6379->6379/tcp</span>
                        </div>
                        <div class="terminal-line">
                            <span class="prompt">$</span> <span>curl http://localhost:8000/health</span>
                        </div>
                        <div class="terminal-line">
                            <span>{"status":"healthy"}</span>
                        </div>
                        <div class="terminal-line">
                            <span class="prompt">$</span> <span>docker-compose logs app</span>
                        </div>
                        <div class="terminal-line">
                            <span>app | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)</span>
                        </div>
                        <div class="terminal-line">
                            <span>app         | INFO:     Application startup complete.</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Interactive Demo -->
    <section id="demo" class="content-section">
        <div class="container">
            <h2 class="section-title">Docker 交互演示</h2>

            <div class="demo-container">
                <h3 class="demo-title">在终端中运行 Docker 和 Docker Compose 命令</h3>
                <div class="terminal">
                    <div class="terminal-header">
                        <div class="terminal-btn red"></div>
                        <div class="terminal-btn yellow"></div>
                        <div class="terminal-btn green"></div>
                    </div>
                    <div class="terminal-content" id="demo-terminal-content">
                        <div class="terminal-line">
                            <span class="prompt">root@docker:~#</span> <span>docker --version</span>
                        </div>
                        <div class="terminal-line">
                            <span>Docker version 24.0.5, build ced0996</span>
                        </div>
                        <div class="terminal-line">
                            <span class="prompt">root@docker:~#</span> <span>docker-compose --version</span>
                        </div>
                        <div class="terminal-line">
                            <span>Docker Compose version v2.23.0</span>
                        </div>
                        <div class="terminal-line">
                            <span class="prompt">root@docker:~#</span> <span>docker ps</span>
                        </div>
                        <div class="terminal-line">
                            <span>CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES</span>
                        </div>
                    </div>
                </div>
                <input type="text" class="user-input" id="command-input" placeholder="输入Docker命令 (如: docker-compose up -d, docker ps, docker images)...">

                <div class="demo-controls">
                    <button class="demo-btn" onclick="executeCommand()">执行命令</button>
                    <button class="demo-btn secondary" onclick="clearTerminal()">清空终端</button>
                    <button class="demo-btn secondary" onclick="resetDemo()">重置演示</button>
                </div>

                <div style="margin-top: 20px; background: #e9f7fe; border-radius: 8px; padding: 15px; border-left: 4px solid var(--primary);">
                    <h4 style="margin-bottom: 10px; color: var(--dark);">演示说明</h4>
                    <p style="font-size: 0.95rem;">此交互演示模拟了Docker命令执行环境。尝试输入以下命令:</p>
                    <ul style="padding-left: 20px; margin-top: 10px; font-size: 0.95rem;">
                        <li><code>docker ps</code> - 列出运行中的容器</li>
                        <li><code>docker images</code> - 列出本地镜像</li>
                        <li><code>docker-compose up -d</code> - 启动多容器应用</li>
                        <li><code>docker-compose ps</code> - 查看Compose服务状态</li>
                        <li><code>docker-compose logs</code> - 查看服务日志</li>
                        <li><code>docker-compose down</code> - 停止并删除容器</li>
                    </ul>
                </div>
            </div>
        </div>
    </section>

    <!-- Footer -->
    <footer>
        <div class="container">
            <div class="footer-content">
                <div class="footer-column">
                    <h3>关于 Docker</h3>
                    <p>Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。</p>
                </div>
                <div class="footer-column">
                    <h3>学习资源</h3>
                    <ul>
                        <li><a href="#">Docker 官方文档</a></li>
                        <li><a href="#">Docker Hub</a></li>
                        <li><a href="#">FastAPI 官方文档</a></li>
                        <li><a href="#">阿里云镜像源</a></li>
                        <li><a href="#">Python 容器化指南</a></li>
                    </ul>
                </div>
                <div class="footer-column">
                    <h3>常用命令</h3>
                    <ul>
                        <li><a href="#">docker build</a></li>
                        <li><a href="#">docker run</a></li>
                        <li><a href="#">docker-compose up</a></li>
                        <li><a href="#">docker-compose down</a></li>
                        <li><a href="#">docker exec</a></li>
                    </ul>
                </div>
                <div class="footer-column">
                    <h3>社区与支持</h3>
                    <ul>
                        <li><a href="#">Docker 社区论坛</a></li>
                        <li><a href="#">Stack Overflow</a></li>
                        <li><a href="#">FastAPI GitHub</a></li>
                        <li><a href="#">阿里云镜像站</a></li>
                        <li><a href="#">Python 容器化社区</a></li>
                    </ul>
                </div>
            </div>
            <div class="copyright">
                <p>&copy; 2023 Docker 教程 | 本教程仅供学习使用 | Docker 是 Docker Inc. 的注册商标</p>
                <p style="margin-top: 10px; font-size: 0.85rem;">使用国内淘宝镜像源加速 pip 安装: https://mirrors.aliyun.com/pypi/simple/</p>
            </div>
        </div>
    </footer>

    <script>
        // 平滑滚动
        document.querySelectorAll('a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                document.querySelector(this.getAttribute('href')).scrollIntoView({
                    behavior: 'smooth'
                });
            });
        });

        // 导航栏高亮
        window.addEventListener('scroll', function() {
            const sections = document.querySelectorAll('section');
            const navLinks = document.querySelectorAll('nav a');

            let current = '';

            sections.forEach(section => {
                const sectionTop = section.offsetTop;
                const sectionHeight = section.clientHeight;

                if (pageYOffset >= (sectionTop - sectionHeight / 3)) {
                    current = section.getAttribute('id');
                }
            });

            navLinks.forEach(link => {
                link.classList.remove('active');
                if (link.getAttribute('href') === `#${current}`) {
                    link.classList.add('active');
                }
            });
        });

        // 复制代码功能
        function copyCode(id) {
            const code = document.getElementById(id).textContent;
            navigator.clipboard.writeText(code).then(() => {
                const btn = document.querySelector(`button[onclick="copyCode('${id}')"]`);
                const originalText = btn.textContent;
                btn.textContent = '已复制!';
                setTimeout(() => {
                    btn.textContent = originalText;
                }, 2000);
            });
        }

        // 模拟的Docker命令响应
        const commandResponses = {
            'docker ps': `CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                    NAMES
a1b2c3d4e5f6   my-fastapi-app    "uvicorn main:app --..."   2 minutes ago    Up 2 minutes    0.0.0.0:8000->8000/tcp   fastapi-container
f0e9d8c7b6a5   redis:alpine      "docker-entrypoint.s..."   15 minutes ago   Up 15 minutes   6379/tcp                 redis-cache`,

            'docker images': `REPOSITORY       TAG       IMAGE ID       CREATED        SIZE
my-fastapi-app   latest    9e8f7a6b5c4d   2 hours ago    285MB
python           3.11-slim 8c2b0a5a9c3d   3 days ago     124MB
redis            alpine    c30b63d3e3b3   3 weeks ago    32.4MB`,

            'docker run -d my-fastapi-app': `b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6`,

            'docker ps -a': `CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS                      PORTS                    NAMES
b3d4e5f6a7b8   my-fastapi-app    "uvicorn main:app --..."   10 seconds ago   Up 9 seconds                0.0.0.0:8000->8000/tcp   fastapi-container
a1b2c3d4e5f6   my-fastapi-app    "uvicorn main:app --..."   2 minutes ago    Up 2 minutes                0.0.0.0:8000->8000/tcp   fastapi-container
f0e9d8c7b6a5   redis:alpine      "docker-entrypoint.s..."   15 minutes ago   Exited (0) 5 minutes ago                             redis-cache`,

            'docker stop': `Error response from daemon: No such container: stop`,

            'docker stop b3d4e5f6a7b8': `b3d4e5f6a7b8`,

            'docker rm': `Error response from daemon: No such container: rm`,

            'docker rm b3d4e5f6a7b8': `b3d4e5f6a7b8`,

            'docker rmi': `Error response from daemon: No such image: rmi`,

            'docker images -q': `9e8f7a6b5c4d
8c2b0a5a9c3d
c30b63d3e3b3`,

            'docker-compose up -d': `Creating network "fastapi-app_default" with the default driver
Creating volume "postgres_data" with default driver
Creating volume "redis_data" with default driver
Creating fastapi-db ... done
Creating fastapi-redis ... done
Creating fastapi-app ... done`,

            'docker-compose ps': `NAME                COMMAND                  SERVICE   STATUS          PORTS
fastapi-app         "uvicorn main:app --..."   app       Up 5 seconds     0.0.0.0:8000->8000/tcp
fastapi-db          "docker-entrypoint.s..."   db        Up 5 seconds     0.0.0.0:5432->5432/tcp
fastapi-redis       "docker-entrypoint.s..."   redis     Up 5 seconds     0.0.0.0:6379->6379/tcp`,

            'docker-compose logs app': `app         | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
app         | INFO:     Application startup complete.
app         | INFO:     Application startup complete.
app         | INFO:     Application startup complete.`,

            'docker-compose down': `Stopping fastapi-app ... done
Stopping fastapi-db ... done
Stopping fastapi-redis ... done
Removing fastapi-app ... done
Removing fastapi-db ... done
Removing fastapi-redis ... done
Removing network fastapi-app_default
Removing volume postgres_data
Removing volume redis_data`,

            'default': `Command not found: {command}. Try 'docker --help' for available commands.
Available demo commands:
- docker ps
- docker ps -a
- docker images
- docker images -q
- docker run -d my-fastapi-app
- docker-compose up -d
- docker-compose ps
- docker-compose logs
- docker-compose down
- docker stop [container_id]
- docker rm [container_id]`
        };

        // 执行命令
        function executeCommand() {
            const input = document.getElementById('command-input');
            const command = input.value.trim();
            const terminal = document.getElementById('demo-terminal-content');

            if (!command) return;

            // 添加命令到终端
            const commandLine = document.createElement('div');
            commandLine.className = 'terminal-line';
            commandLine.innerHTML = `<span class="prompt">root@docker:~#</span> <span>${command}</span>`;
            terminal.appendChild(commandLine);

            // 处理命令
            let response = '';

            if (command.startsWith('docker ps')) {
                response = commandResponses['docker ps'];
            } else if (command.startsWith('docker images')) {
                if (command.includes('-q')) {
                    response = commandResponses['docker images -q'];
                } else {
                    response = commandResponses['docker images'];
                }
            } else if (command.startsWith('docker run')) {
                const containerId = Math.random().toString(16).substring(2, 18);
                response = containerId;
            } else if (command.startsWith('docker stop')) {
                const parts = command.split(' ');
                if (parts.length > 1 && parts[1] !== 'stop') {
                    response = commandResponses['docker stop ' + parts[1]];
                } else {
                    response = commandResponses['docker stop'];
                }
            } else if (command.startsWith('docker rm')) {
                const parts = command.split(' ');
                if (parts.length > 1 && parts[1] !== 'rm') {
                    response = commandResponses['docker rm ' + parts[1]];
                } else {
                    response = commandResponses['docker rm'];
                }
            } else if (command.startsWith('docker rmi')) {
                response = commandResponses['docker rmi'];
            } else if (command.startsWith('docker-compose up')) {
                response = commandResponses['docker-compose up -d'];
            } else if (command.startsWith('docker-compose ps')) {
                response = commandResponses['docker-compose ps'];
            } else if (command.startsWith('docker-compose logs')) {
                response = commandResponses['docker-compose logs app'];
            } else if (command.startsWith('docker-compose down')) {
                response = commandResponses['docker-compose down'];
            } else if (command.startsWith('docker') || command.startsWith('docker-compose')) {
                response = commandResponses['default'].replace('{command}', command);
            } else {
                response = `Command not found: ${command}. This demo only supports docker commands.`;
            }

            // 添加响应到终端
            const responseLine = document.createElement('div');
            responseLine.className = 'terminal-line';
            responseLine.innerHTML = `<span>${response}</span>`;
            terminal.appendChild(responseLine);

            // 滚动到底部
            terminal.scrollTop = terminal.scrollHeight;

            // 清空输入框
            input.value = '';
        }

        // 清空终端
        function clearTerminal() {
            const terminal = document.getElementById('demo-terminal-content');
            terminal.innerHTML = '';
        }

        // 重置演示
        function resetDemo() {
            const terminal = document.getElementById('demo-terminal-content');
            terminal.innerHTML = `
                <div class="terminal-line">
                    <span class="prompt">root@docker:~#</span> <span>docker --version</span>
                </div>
                <div class="terminal-line">
                    <span>Docker version 24.0.5, build ced0996</span>
                </div>
                <div class="terminal-line">
                    <span class="prompt">root@docker:~#</span> <span>docker-compose --version</span>
                </div>
                <div class="terminal-line">
                    <span>Docker Compose version v2.23.0</span>
                </div>
                <div class="terminal-line">
                    <span class="prompt">root@docker:~#</span> <span>docker ps</span>
                </div>
                <div class="terminal-line">
                    <span>CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES</span>
                </div>
            `;
            document.getElementById('command-input').value = '';
        }

        // 输入框回车事件
        document.getElementById('command-input').addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                executeCommand();
            }
        });
    </script>
</body>
</html>
相关推荐
芥子沫2 小时前
《玩转Docker》[应用篇18]:项目管理应用推荐LeanTime安装部署和使用
docker·项目管理
菜鸟小芯2 小时前
【GLM-5 陪练式前端新手入门】第二篇:CSS 让网页从 “能用” 变 “好看”
前端·css
Lee川2 小时前
CSS奇幻漂流记:扬帆样式之海,解锁视觉魔法
css
Joker Zxc2 小时前
【前端基础(Javascript部分)】1、JavaScript的基础知识(组成、应用、编写方式、注释)
开发语言·前端·javascript
Lee川2 小时前
深入浅出:从JavaScript内存模型理解“深拷贝”的必要性与实现
javascript
用户5757303346243 小时前
🔥 面试官:手写 Promise 封装 AJAX?这 5 个考点 90% 的人跪了!
javascript
上单带刀不带妹3 小时前
【Axios 实战】网络图片地址转 File 对象,附跨域解决方案
开发语言·前端·javascript·vue
岱宗夫up3 小时前
【前端基础】HTML + CSS + JavaScript 基础(一)
前端·css·html
SuperEugene3 小时前
前端模块化与 import/export入门:从「乱成一团」到「清晰可维护」
前端·javascript·面试·vue