2个小时1.5w字| React Golang 全栈微服务实战
文章目录
- 前言
- Golang 入门教程
- 1. 下载与环境配置
- 安装 Go
- Windows 安装
- macOS 安装
- Linux 安装
- 理解 GOROOT 和 GOPATH
- GOROOT
- GOPATH
- Go Modules 与 GOPATH 的关系
- 查看和设置 Go 环境变量
- 配置 GOPATH
- 2. 语法与包管理
- Go 基础语法
- 运行 Go 程序
- 构建 Go 程序
- 包管理 (Go Modules)
- 常用标准库
- 推荐学习资源
- 扩展练习
- Kratos 微服务框架入门
- 1. Kratos 核心介绍
- 1.1 核心理念
- 1.2 主要特性
- 1.3 设计架构
- 2. 项目初始化方法
- 2.1 安装 Kratos 命令行工具
- 2.2 创建新项目
- 2.3 添加 API 定义
- 2.4 生成 API 代码
- 3. CLI 工具详解
- 3.1 主要命令
- 3.2 Proto 相关命令
- 3.3 工具依赖
- 4. 依赖注入
- 4.1 Wire 基础
- 4.2 Provider 定义
- 4.3 Wire 注入点
- 4.4 生成注入代码
- 5. 项目结构详解
- 5.1 标准目录结构
- 5.2 各目录职责
- 6. 项目运行链路分析
- 6.1 启动流程
- 6.2 请求处理流程
- 6.3 HTTP服务示例
- 6.4 完整服务架构
- 扩展阅读与资源
- React 入门教程
- 1. 下载与环境配置
- 安装 Node.js 和 pnpm
- 创建新的 React 应用
- 2. React 基本语法与包管理
- 基本概念
- 函数组件示例
- 使用 State Hook
- 使用 Effect Hook
- 包管理与依赖
- 本目录代码示例说明
- 如何运行示例代码
- pnpm 常用命令参考
- 学习资源
- 练习建议
- Next.js 入门教程
- 1. 项目目录与优雅实践
- Next.js 项目结构 (App Router)
- Next.js App Router 优雅实践
- 2. 快速启动案例前端
- 安装 Node.js 和 pnpm
- 创建 Next.js 项目
- 项目结构设置
- 创建首页
- 创建页面
- 创建布局
- 创建动态路由
- 创建 API 路由
- 数据获取
- 安装依赖
- 运行开发服务器
- 构建和部署
- pnpm 优势
- pnpm 常用命令
- Node.js 与 Next.js 的关系
- Node.js 与 Next.js 的基本关系
- Next.js 的运行时环境
- 开发环境 (`pnpm dev`)
- 生产环境 (`pnpm build` 然后 `pnpm start`)
- 渲染模式与Node.js的关系
- Node.js 环境的限制
- 部署架构
- 本目录示例代码说明
- App Router 和 Pages Router 的区别
- 进阶资源
- 练习建议
- 容器知识入门教程
- Docker 背景介绍
- 什么是 Docker
- Docker 的发展历史
- 为什么需要 Docker
- Docker vs 虚拟机
- 1. Docker 安装
- Windows 安装
- macOS 安装
- Linux 安装 (Ubuntu)
- 验证安装
- 2. 常用 Docker 命令
- 镜像相关命令
- 容器相关命令
- Docker Compose 命令
- 网络和存储命令
- 示例项目说明
- 如何运行示例项目
- 项目文件说明
- Dockerfile
- docker-compose.yml
- app.js
- Docker 网络详解
- Docker 网络的主要作用
- 常用网络类型
- 网络驱动类型
- Docker 卷详解
- Docker 卷的主要作用
- 卷的使用方式
- 卷的类型
- Docker 进阶概念
- 相关资源
- 练习建议
- 全栈博客案例
- 代码仓库
前言
本文分为6个小节,带你全方位入门 React & Golang 微服务全栈开发。
- golang
- kratos
- react
- next.js
- docker
- 博客案例
每一个小节均有丰富的代码案例,仓库地址如下:https://github.com/BaiZe1998/go-learning
Golang|AI 主题知识星球:白泽说 试运营当中,私信咨询,免费加入。
Golang 入门教程
1. 下载与环境配置
安装 Go
Windows 安装
- 访问 Go 官方下载页面
- 下载 Windows 安装包 (MSI)
- 运行安装程序,按照提示完成安装
- 安装完成后,打开命令提示符,输入
go version
确认安装成功
macOS 安装
- 访问 Go 官方下载页面
- 下载 macOS 安装包 (PKG)
- 运行安装程序,按照提示完成安装
- 或者使用 Homebrew:
brew install go
- 安装完成后,打开终端,输入
go version
确认安装成功
Linux 安装
-
访问 Go 官方下载页面
-
下载对应的 Linux 压缩包
-
解压到
/usr/local
:sudo tar -C /usr/local -xzf go1.x.x.linux-amd64.tar.gz
-
添加环境变量到
~/.profile
或~/.bashrc
:export PATH=$PATH:/usr/local/go/bin
-
使环境变量生效:
source ~/.profile
或source ~/.bashrc
-
验证安装:
go version
理解 GOROOT 和 GOPATH
GOROOT
GOROOT 是 Go 语言的安装目录,它包含了 Go 标准库、编译器、工具等。安装 Go 时会自动设置这个环境变量。
-
作用:告诉 Go 工具链在哪里可以找到 Go 的标准库和工具
-
默认位置:
- Windows:
C:\go
- macOS/Linux:
/usr/local/go
或 Homebrew 安装位置
- Windows:
-
查看 GOROOT:
go env GOROOT
-
手动设置(通常不需要,除非安装在非标准位置):
- Windows: 添加系统环境变量
GOROOT=C:\path\to\go
- macOS/Linux: 在
~/.profile
或~/.bashrc
中添加export GOROOT=/path/to/go
- Windows: 添加系统环境变量
GOPATH
GOPATH 是 Go 的工作目录,用于存放 Go 代码、包和依赖等。
-
作用:
- 在 Go Modules 出现前(Go 1.11之前),所有 Go 项目必须位于 GOPATH 内
- 在 Go Modules 时代,GOPATH 主要用于存储下载的依赖包和编译后的二进制文件
-
默认位置:
- Windows:
%USERPROFILE%\go
(例如:C:\Users\YourName\go
) - macOS/Linux:
$HOME/go
(例如:/home/username/go
或/Users/username/go
)
- Windows:
-
GOPATH 目录结构:
src
: 存放源代码(如你的项目和依赖包的源码)pkg
: 存放编译后的包文件bin
: 存放编译后的可执行文件
-
设置多个 GOPATH:
可以设置多个目录,用冒号(Unix)或分号(Windows)分隔# Unix/macOS export GOPATH=$HOME/go:$HOME/projects/go# Windows set GOPATH=%USERPROFILE%\go;D:\projects\go
Go Modules 与 GOPATH 的关系
从 Go 1.11 开始,Go 引入了 Go Modules 作为官方的依赖管理解决方案,逐渐弱化了 GOPATH 的作用:
-
Go Modules 模式下:
- 项目可以位于任何目录,不必在 GOPATH 内
- 依赖通过
go.mod
文件管理,而不是通过 GOPATH 目录结构 - 下载的依赖缓存在
$GOPATH/pkg/mod
目录 - 编译的命令仍安装到
$GOPATH/bin
-
环境变量 GO111MODULE:
GO111MODULE=off
: 禁用模块支持,使用 GOPATH 模式GO111MODULE=on
: 启用模块支持,忽略 GOPATHGO111MODULE=auto
: 在 GOPATH 内禁用模块支持,在 GOPATH 外启用模块支持
查看和设置 Go 环境变量
# 查看所有 Go 环境变量
go env# 查看特定环境变量
go env GOPATH
go env GOROOT# 设置环境变量(Go 1.14+)
go env -w GOPATH=/custom/path
配置 GOPATH
GOPATH 是工作目录,用于存放 Go 代码、包和依赖等:
- 创建 GOPATH 目录,例如:
mkdir -p $HOME/go
- 设置环境变量:
- Windows: 添加
GOPATH
系统环境变量,值为你创建的目录路径 - macOS/Linux: 在
~/.profile
或~/.bashrc
中添加export GOPATH=$HOME/go
- Windows: 添加
- GOPATH 目录结构:
src
: 源代码pkg
: 包文件bin
: 可执行文件
2. 语法与包管理
Go 基础语法
查看 hello.go
文件了解 Go 的基本语法,包括:
- 包声明与导入
- 变量声明与使用
- 基本数据类型
- 控制流(条件语句、循环)
- 函数定义与调用
- 切片与数组操作
运行 Go 程序
go run hello.go
构建 Go 程序
go build hello.go
./hello # 运行编译后的可执行文件
包管理 (Go Modules)
从 Go 1.11 开始,Go 引入了 Go Modules 作为官方的依赖管理解决方案:
-
初始化一个新模块:
go mod init example.com/myproject
-
添加依赖:
go get github.com/some/dependency
-
整理和更新依赖:
go mod tidy
-
查看所有依赖:
go list -m all
常用标准库
fmt
: 格式化输入输出io
: 基本 I/O 接口os
: 操作系统功能net/http
: HTTP 客户端和服务器encoding/json
: JSON 编解码time
: 时间相关功能sync
: 同步原语
推荐学习资源
- Go 官方文档
- Go by Example
- Go Tour
扩展练习
- 修改
hello.go
添加更多功能 - 创建一个简单的 HTTP 服务器
- 实现文件读写操作
- 使用 Go 实现一个简单的 CLI 工具
Kratos 微服务框架入门
Kratos 是一个轻量级的、模块化的、可插拔的Go微服务框架,专注于帮助开发人员快速构建微服务。本教程将带你深入了解 Kratos 的核心概念和使用方法。
1. Kratos 核心介绍
Kratos 是哔哩哔哩开源的一款Go微服务框架,具有以下核心特点:
1.1 核心理念
- 简洁:提供了简洁、统一的接口定义和使用方式
- 模块化:各个组件可独立使用,也可组合使用
- 可扩展:支持各类中间件和插件的扩展
- 高性能:追求极致的性能优化
1.2 主要特性
- 传输层:支持 HTTP 和 gRPC 服务,并提供统一抽象
- 中间件:丰富的内置中间件,如日志、指标、跟踪、限流等
- 注册发现:支持多种服务注册与发现机制
- 配置管理:灵活的配置加载和动态配置
- 错误处理:统一的错误处理和错误码管理
- API定义:使用 Protocol Buffers 作为 API 定义语言
- 依赖注入:使用 Wire 进行依赖管理和注入
1.3 设计架构
Kratos 采用领域驱动设计 (DDD) 的六边形架构,将应用分为以下层次:
- API层:定义服务接口,通常使用Proto文件
- Service层:处理服务业务逻辑的实现
- Biz层:核心业务逻辑和领域模型
- Data层:数据访问层,负责与持久化存储交互
- Server层:传输层,提供HTTP/gRPC服务
2. 项目初始化方法
Kratos 提供了完善的项目初始化流程,帮助开发者快速创建项目骨架。
2.1 安装 Kratos 命令行工具
# 安装最新版本的 Kratos 命令行工具
go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
2.2 创建新项目
# 创建名为 myproject 的新项目
kratos new myproject# 进入项目目录
cd myproject
2.3 添加 API 定义
# 创建 API 文件
kratos proto add api/myproject/v1/myproject.proto
2.4 生成 API 代码
在编写完 proto 文件后,使用 kratos 命令生成相应代码:
# 生成客户端代码
kratos proto client api/myproject/v1/myproject.proto# 生成服务端代码
kratos proto server api/myproject/v1/myproject.proto -t internal/service
3. CLI 工具详解
Kratos CLI 是 Kratos 框架的命令行工具,提供了丰富的功能帮助开发者提高效率。
3.1 主要命令
命令 | 说明 | 用法示例 |
---|---|---|
new | 创建新项目 | kratos new myproject |
proto | 管理 Proto 文件与代码生成 | kratos proto add/client/server |
run | 运行项目 | kratos run |
build | 构建项目 | kratos build |
upgrade | 更新 Kratos 工具 | kratos upgrade |
3.2 Proto 相关命令
# 添加新的 proto 文件
kratos proto add api/helloworld/v1/greeter.proto# 生成 client 代码
kratos proto client api/helloworld/v1/greeter.proto# 生成 server 代码
kratos proto server api/helloworld/v1/greeter.proto -t internal/service# 生成所有代码
kratos proto all api/helloworld/v1/greeter.proto -t internal/service
3.3 工具依赖
使用 Kratos 相关功能需要安装以下组件:
# 安装 protoc 编译器依赖
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2@latest
4. 依赖注入
Kratos 使用 Wire 框架进行依赖注入,实现了组件的松耦合和代码的可测试性。
4.1 Wire 基础
Wire 是 Google 开发的编译时依赖注入工具,通过代码生成而非反射实现依赖注入。
4.2 Provider 定义
在 Kratos 中,各个组件通过 Provider 函数提供实例:
// data层 provider
func NewData(conf *conf.Data, logger log.Logger) (*Data, func(), error) {// 实例化数据层cleanup := func() {// 清理资源}return &Data{}, cleanup, nil
}// biz层 provider
func NewGreeterUsecase(repo GreeterRepo, logger log.Logger) *GreeterUsecase {return &GreeterUsecase{repo: repo}
}// service层 provider
func NewGreeterService(uc *biz.GreeterUsecase, logger log.Logger) *GreeterService {return &GreeterService{uc: uc}
}
4.3 Wire 注入点
在 cmd/server/wire.go
中定义依赖注入:
// ProviderSet 是各层的依赖集合
var ProviderSet = wire.NewSet(data.ProviderSet,biz.ProviderSet,service.ProviderSet,server.ProviderSet,
)// 应用实例化函数
func initApp(*conf.Server, *conf.Data, log.Logger) (*kratos.App, error) {panic(wire.Build(ProviderSet, newApp))
}
4.4 生成注入代码
# 生成依赖注入代码
cd cmd/server
wire
5. 项目结构详解
Kratos 项目结构遵循 DDD 六边形架构,组织清晰。
5.1 标准目录结构
├── api # API 定义目录 (protobuf)
│ └── helloworld
│ └── v1
│ └── greeter.proto
├── cmd # 应用程序入口
│ └── server
│ ├── main.go
│ ├── wire.go # 依赖注入
│ └── wire_gen.go # 自动生成的依赖注入代码
├── configs # 配置文件目录
│ └── config.yaml
├── internal # 私有应用代码
│ ├── biz # 业务逻辑层 (领域模型)
│ │ ├── biz.go
│ │ └── greeter.go
│ ├── conf # 配置处理代码
│ │ ├── conf.proto
│ │ └── conf.pb.go
│ ├── data # 数据访问层 (持久化)
│ │ ├── data.go
│ │ └── greeter.go
│ ├── server # 传输层(HTTP/gRPC)
│ │ ├── server.go
│ │ ├── http.go
│ │ └── grpc.go
│ └── service # 服务实现层
│ └── greeter.go
├── third_party # 第三方 proto 文件
└── go.mod
5.2 各目录职责
- api: 定义服务 API 接口,使用 Protocol Buffers
- cmd: 程序入口,包含 main 函数和依赖注入
- configs: 配置文件
- internal: 私有代码,不对外暴露
- biz: 核心业务逻辑,包含领域模型和业务规则
- data: 数据访问层,实现数据库操作和缓存
- server: 服务器定义,包括 HTTP 和 gRPC 服务器配置
- service: 服务实现,连接 API 和业务逻辑
- third_party: 第三方依赖的 proto 文件
6. 项目运行链路分析
Kratos 应用从启动到处理请求的完整流程。
6.1 启动流程
- 初始化配置:加载 configs 目录的配置文件
- 依赖注入:通过 Wire 构建应用依赖关系
- 创建服务器:初始化 HTTP/gRPC 服务器
- 注册服务:注册 API 实现
- 启动服务:启动服务监听
// main.go 中的启动流程
func main() {// 1. 初始化 loggerlogger := log.NewStdLogger(os.Stdout)// 2. 加载配置c := config.New(config.WithSource(file.NewSource(flagconf)))if err := c.Load(); err != nil {panic(err)}// 3. 通过依赖注入创建 app 实例app, cleanup, err := wireApp(c, logger)if err != nil {panic(err)}defer cleanup()// 4. 启动应用if err := app.Run(); err != nil {panic(err)}
}
6.2 请求处理流程
HTTP 请求从接收到响应的完整流程:
- 接收请求:HTTP/gRPC 服务器接收请求
- 中间件处理:请求经过中间件链(日志、跟踪、限流等)
- 路由匹配:根据路径匹配对应处理器
- 参数解析:解析和验证请求参数
- 服务层处理:Service 层实现请求处理
- 业务逻辑:调用 Biz 层的领域逻辑
- 数据访问:通过 Data 层访问数据库或缓存
- 响应构建:构建响应数据
- 中间件后处理:响应经过中间件链
- 返回响应:返回给客户端
6.3 HTTP服务示例
以下是一个简化的 HTTP 服务示例:
import ("github.com/go-kratos/kratos/v2""github.com/go-kratos/kratos/v2/log""github.com/go-kratos/kratos/v2/middleware/recovery""github.com/go-kratos/kratos/v2/transport/http"
)func main() {// 初始化 loggerlogger := log.NewStdLogger(os.Stdout)// 创建 HTTP 服务器httpSrv := http.NewServer(http.Address(":8000"),http.Middleware(recovery.Recovery(), // 异常恢复中间件),)// 注册路由r := httpSrv.Route("/")r.GET("/hello", func(ctx http.Context) error {return ctx.String(200, "Hello Kratos!")})// 创建 Kratos 应用app := kratos.New(kratos.Name("example"),kratos.Server(httpSrv),kratos.Logger(logger),)// 启动应用if err := app.Run(); err != nil {log.Error(err)}
}
6.4 完整服务架构
在实际项目中,请求处理链路涉及多个组件和层次:
客户端 → 负载均衡 → HTTP/gRPC服务器 → 中间件链 → 路由 → Service层 → Biz层 → Data层 → 数据库/缓存↑ ↓
服务注册/发现 ← ← ← ← ← ← ← ← ← ← ← ← ← ← 响应 ← ← ← ← ← ←
扩展阅读与资源
- Kratos GitHub
- Kratos 文档
- Kratos 示例
- Protocol Buffers
- Wire 依赖注入
React 入门教程
React 是由 Facebook 开发的一个用于构建用户界面的 JavaScript 库。React 使开发人员能够构建快速、可扩展的 Web 应用程序。
1. 下载与环境配置
要开始使用 React,您需要一个现代的 JavaScript 环境和 Node.js 开发环境。
安装 Node.js 和 pnpm
首先,安装 Node.js(包含 npm):
- Windows/macOS: 从 Node.js 官网 下载并安装
- macOS (使用 Homebrew):
brew install node
- Linux:
sudo apt install nodejs npm
或sudo yum install nodejs npm
验证安装:
node -v
然后安装 pnpm (性能更好的包管理器):
# 使用npm安装pnpm
npm install -g pnpm# 验证pnpm安装
pnpm --version
创建新的 React 应用
使用 Create React App 工具创建新的 React 应用:
# 创建新项目
pnpm create react-app my-react-app# 进入项目目录
cd my-react-app# 启动开发服务器
pnpm start
或者使用 Vite 创建(更快的启动速度,推荐):
# 使用 Vite 创建 React 项目
pnpm create vite my-react-app --template react# 进入项目目录
cd my-react-app# 安装依赖
pnpm install# 启动开发服务器
pnpm dev
2. React 基本语法与包管理
基本概念
-
组件 (Components):React 应用由组件构成
- 函数组件(推荐)
- 类组件
-
JSX:JavaScript 的语法扩展,允许在 JS 中编写类似 HTML 的代码
-
Props:向组件传递数据的方式
-
State:组件的内部状态
-
Hooks:在函数组件中使用状态和其他 React 特性的 API
函数组件示例
import React from 'react';function Greeting(props) {return <h1>你好,{props.name}!</h1>;
}export default Greeting;
使用 State Hook
import React, { useState } from 'react';function Counter() {const [count, setCount] = useState(0);return (<div><p>你点击了 {count} 次</p><button onClick={() => setCount(count + 1)}>点击我</button></div>);
}
使用 Effect Hook
import React, { useState, useEffect } from 'react';function Timer() {const [seconds, setSeconds] = useState(0);useEffect(() => {const interval = setInterval(() => {setSeconds(seconds => seconds + 1);}, 1000);return () => clearInterval(interval);}, []);return <div>计时器:{seconds} 秒</div>;
}
包管理与依赖
React 项目使用 pnpm 管理依赖(pnpm比npm和yarn更快、更高效):
# 安装依赖
pnpm add react-router-dom# 安装开发依赖
pnpm add -D typescript @types/react# 更新所有依赖
pnpm update# 运行脚本
pnpm run dev
pnpm的主要优势:
- 磁盘空间高效:pnpm使用内容寻址存储来避免重复安装
- 快速安装:比npm和yarn快2-3倍
- 严格的依赖管理:更好的避免依赖地狱问题
- 支持monorepo:内置对工作空间的支持
常用的包:
- react-router-dom: 路由管理
- axios: HTTP 请求
- zustand 或 redux-toolkit: 状态管理
- styled-components 或 emotion: CSS-in-JS 解决方案
- MUI 或 Ant Design: UI 组件库
本目录代码示例说明
本目录包含两个主要文件:
-
App.jsx: 包含三个示例组件
- 计数器:展示基本的状态管理
- 计时器:展示 useEffect 的使用
- 待办事项列表:展示更复杂的状态管理
-
App.css: 为组件提供样式
如何运行示例代码
要运行本示例,需要将这些文件集成到一个 React 项目中:
-
创建新的 React 应用:
pnpm create vite react-demo --template react cd react-demo pnpm install
-
替换
src/App.jsx
和src/App.css
为本目录中的文件 -
启动应用:
pnpm dev
pnpm 常用命令参考
# 初始化新项目
pnpm init# 安装依赖
pnpm add [package]# 安装开发依赖
pnpm add -D [package]# 全局安装
pnpm add -g [package]# 运行脚本
pnpm [script]# 移除依赖
pnpm remove [package]# 更新依赖
pnpm update# 查看过时依赖
pnpm outdated
学习资源
- React 官方文档
- React Hooks 文档
- pnpm 官方文档
- Vite 官方文档
- React Router 文档
练习建议
- 修改计数器组件,添加最大值和最小值限制
- 为待办事项添加优先级功能
- 添加一个新的表单组件,练习表单处理
- 尝试使用 Context API 在组件之间共享状态
Next.js 入门教程
Next.js 是一个基于 React 的轻量级框架,用于构建静态和服务器渲染的应用程序。它提供了丰富的功能,如服务器端渲染、静态网站生成、API 路由、自动代码分割等。本教程基于 Next.js 13+ 的 App Router。
1. 项目目录与优雅实践
Next.js 项目结构 (App Router)
一个典型的 Next.js 项目结构如下:
my-nextjs-app/
│
├── app/ # App Router 目录(基于文件约定的路由)
│ ├── layout.tsx # 根布局组件
│ ├── page.tsx # 首页 (/)
│ ├── about/ # 关于页面路由
│ │ └── page.tsx # 关于页面 (/about)
│ ├── blogs/ # 博客路由
│ │ ├── [id]/ # 动态路由
│ │ │ └── page.tsx # 博客文章页面
│ │ ├── new/ # 创建新博客
│ │ │ └── page.tsx # 创建博客页面
│ │ └── page.tsx # 博客列表页面
│ ├── api/ # API 路由
│ │ └── route.ts # API 处理器
│ ├── globals.css # 全局样式
│ └── error.tsx # 错误处理页面
│
├── components/ # React 组件
│ ├── ui/ # UI 组件
│ └── ClientComponent.tsx # 客户端组件示例
│
├── lib/ # 工具函数和库
│ └── utils.ts
│
├── public/ # 静态资源
│ ├── favicon.ico
│ └── images/
│
├── .next/ # Next.js 构建输出 (git ignored)
├── node_modules/ # 依赖 (git ignored)
├── package.json # 项目依赖和脚本
├── pnpm-lock.yaml # pnpm 锁文件
├── next.config.js # Next.js 配置
├── tsconfig.json # TypeScript 配置
└── README.md # 项目说明
Next.js App Router 优雅实践
-
文件系统路由约定
app/page.tsx
→/
(首页)app/about/page.tsx
→/about
(关于页面)app/blogs/[id]/page.tsx
→/blogs/:id
(动态路由)- 特殊文件:
layout.tsx
: 布局组件loading.tsx
: 加载状态error.tsx
: 错误处理not-found.tsx
: 404页面
-
数据获取方法
- React Server Components 中的直接获取
generateStaticParams
: 静态路径生成revalidatePath
/revalidateTag
: 按需重新验证- 客户端数据获取: SWR 或 React Query
-
API 路由
app/api/*/route.ts
文件定义 API 端点- 使用
NextResponse
进行响应处理
-
布局系统
- 嵌套布局
- 平行路由和拦截路由
- 模板和分组
-
渲染策略
- 服务器组件(默认)
- 客户端组件 (‘use client’)
- 流式渲染和部分渲染
2. 快速启动案例前端
安装 Node.js 和 pnpm
首先,确保你已安装 Node.js 和 pnpm:
# 安装 pnpm (如果尚未安装)
npm install -g pnpm# 验证安装
pnpm --version
创建 Next.js 项目
使用 pnpm 创建新的 Next.js 项目:
# 使用 create-next-app 创建TypeScript项目
pnpm create next-app my-nextjs-app --typescript# 进入项目目录
cd my-nextjs-app
在创建项目过程中,会提示你选择一些选项。请确保选择 “Yes” 当询问是否使用 App Router 时。
项目结构设置
默认情况下,create-next-app
生成的项目已经包含基本结构。您可以根据需要添加额外的目录。
创建首页
首页是访问者首先看到的页面,在 app/page.tsx
文件中创建:
// app/page.tsx
import Link from 'next/link';export default function Home() {return (<div className="container mx-auto px-4 py-8"><section className="py-12 text-center"><h1 className="text-4xl font-bold mb-4">欢迎来到我的博客</h1><p className="text-lg text-gray-600 mb-8">探索技术、设计和创意的世界</p><Link href="/blog" className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">浏览博客文章</Link></section><section className="py-8"><h2 className="text-2xl font-bold mb-6 text-center">最新文章</h2><div className="grid md:grid-cols-3 gap-6"><div className="border rounded-lg p-6 hover:shadow-md transition-shadow"><h3 className="text-xl font-semibold mb-3">Next.js入门指南</h3><p className="text-gray-600 mb-4">了解如何使用Next.js构建现代Web应用</p><Link href="/blog/1" className="text-blue-600 hover:underline">→</Link></div><div className="border rounded-lg p-6 hover:shadow-md transition-shadow"><h3 className="text-xl font-semibold mb-3">React服务器组件详解</h3><p className="text-gray-600 mb-4">深入理解React服务器组件的工作原理</p><Link href="/blog/2" className="text-blue-600 hover:underline">→</Link></div><div className="border rounded-lg p-6 hover:shadow-md transition-shadow"><h3 className="text-xl font-semibold mb-3">TypeScript与Next.js</h3><p className="text-gray-600 mb-4">如何在Next.js项目中充分利用TypeScript</p><Link href="/blog/3" className="text-blue-600 hover:underline">→</Link></div></div></section><section className="py-8"><h2 className="text-2xl font-bold mb-6 text-center">关于客户端组件</h2><div className="border rounded-lg p-6"><p className="text-gray-700 mb-4">Next.js的App Router架构区分<strong>服务器组件</strong>和<strong>客户端组件</strong>。默认情况下,所有组件都是服务器组件,在服务器上渲染并发送到客户端。</p><p className="text-gray-700 mb-4">当需要使用浏览器API、添加交互性或使用React hooks时,应该使用客户端组件。通过在文件顶部添加 <code className="bg-gray-100 px-2 py-1 rounded">'use client'</code> 指令来声明客户端组件。</p><div className="bg-gray-50 p-4 rounded-lg"><h3 className="font-semibold mb-2">客户端组件示例:</h3><pre className="bg-gray-800 text-white p-4 rounded overflow-x-auto"><code>{`'use client'import { useState, useEffect } from 'react'export default function ClientComponent() {const [count, setCount] = useState(0)return (<div><h3>计数器: {count}</h3><button onClick={() => setCount(count + 1)}>增加</button></div>)
}`}</code></pre></div></div></section><section className="py-8"><h2 className="text-2xl font-bold mb-6 text-center">功能演示</h2><div className="grid md:grid-cols-2 gap-6"><div className="border rounded-lg p-6 hover:shadow-md transition-shadow"><h3 className="text-xl font-semibold mb-3">博客列表</h3><p className="text-gray-600 mb-4">查看使用服务器组件和模拟数据实现的博客列表页面</p><Link href="/blog" className="text-blue-600 hover:underline">查看示例 →</Link></div><div className="border rounded-lg p-6 hover:shadow-md transition-shadow"><h3 className="text-xl font-semibold mb-3">客户端组件</h3><p className="text-gray-600 mb-4">了解如何在Next.js中使用客户端组件实现交互功能</p><Link href="/client-example" className="text-blue-600 hover:underline">查看示例 →</Link></div></div></section></div>);
}
首页包含了以下元素:
- 欢迎区域,包含标题和指向博客列表的链接
- 最新文章区域,展示最近的博客文章
创建页面
在 app
目录中创建 page.tsx
文件以添加新页面:
// app/about/page.tsx
export default function AboutPage() {return (<div><h1>关于我们</h1><p>这是 Next.js 示例项目的关于页面。</p></div>)
}
创建布局
使用 layout.tsx
文件创建布局:
// app/layout.tsx
import type { ReactNode } from 'react';interface RootLayoutProps {children: ReactNode;
}export default function RootLayout({ children }: RootLayoutProps) {return (<html lang="zh"><body><header><nav>{/* 导航栏组件 */}</nav></header><main>{children}</main><footer>© {new Date().getFullYear()} 我的 Next.js 应用</footer></body></html>)
}
创建动态路由
使用方括号语法创建动态路由:
// app/blogs/[id]/page.tsx
import { notFound } from 'next/navigation';
import Link from 'next/link';// 模拟博客数据
const blogPosts = [{ id: '1', title: 'Next.js入门指南',content: `<p>Next.js是一个基于React的强大框架,它提供了许多内置功能,使得构建现代Web应用变得更加简单。</p><h2>主要特性</h2><ul><li>服务器端渲染 (SSR)</li><li>静态站点生成 (SSG)</li><li>API路由</li><li>文件系统路由</li><li>内置CSS和Sass支持</li><li>代码分割和打包优化</li></ul><p>使用Next.js,你可以快速开发出高性能的React应用,无需复杂的配置。</p>`,author: {name: '张三',avatar: 'https://randomuser.me/api/portraits/men/1.jpg'},publishedAt: '2023-05-15',tags: ['Next.js', 'React', '前端开发']},{ id: '2', title: 'React服务器组件详解',content: `<p>React服务器组件是React的一项新特性,它允许开发者创建在服务器上渲染的组件,从而提高性能并减少客户端JavaScript的体积。</p><h2>服务器组件的优势</h2><ol><li>减少客户端JavaScript包大小</li><li>直接访问服务器资源(数据库、文件系统等)</li><li>自动代码分割</li><li>改善首次加载性能</li></ol><p>在Next.js的App Router中,所有组件默认都是服务器组件,除非你显式声明为客户端组件。</p>`,author: {name: '李四',avatar: 'https://randomuser.me/api/portraits/women/2.jpg'},publishedAt: '2023-06-22',tags: ['React', '服务器组件', '性能优化']},{ id: '3', title: 'TypeScript与Next.js',content: `<p>TypeScript是JavaScript的超集,添加了静态类型检查,在Next.js项目中使用TypeScript可以带来诸多好处。</p><h2>TypeScript的优势</h2><ul><li>静态类型检查,减少运行时错误</li><li>更好的IDE支持,包括代码补全和智能提示</li><li>更容易维护的代码库</li><li>自文档化的代码</li></ul><h2>在Next.js中使用TypeScript</h2><p>Next.js原生支持TypeScript,你可以直接创建.tsx或.ts文件,无需额外配置。</p><p>对于页面和API路由,你可以使用TypeScript接口来定义props和请求参数的类型。</p>`,author: {name: '王五',avatar: 'https://randomuser.me/api/portraits/men/3.jpg'},publishedAt: '2023-07-10',tags: ['TypeScript', 'Next.js', '类型安全']}
];// 获取博客帖子函数
const getBlogPost = (id: string) => {return blogPosts.find(post => post.id === id);
};// 博客详情页面组件
export default function BlogPostPage({ params }: { params: { id: string } }) {const post = getBlogPost(params.id);// 如果没有找到文章,返回404if (!post) {notFound();}return (<div className="container mx-auto px-4 py-8"><article className="max-w-3xl mx-auto"><div className="mb-8"><Link href="/blog" className="text-blue-600 hover:underline mb-4 inline-block">← 返回博客列表</Link><h1 className="text-4xl font-bold mb-4">{post.title}</h1><div className="flex items-center mb-6"><img src={post.author.avatar} alt={post.author.name}className="w-10 h-10 rounded-full mr-3"/><div><p className="font-medium">{post.author.name}</p><p className="text-gray-500 text-sm">发布于 {post.publishedAt}</p></div></div><div className="flex flex-wrap gap-2 mb-8">{post.tags.map(tag => (<span key={tag} className="bg-blue-100 text-blue-800 text-sm px-3 py-1 rounded-full">{tag}</span>))}</div></div><div className="prose prose-lg max-w-none"dangerouslySetInnerHTML={{ __html: post.content }}/><div className="mt-12 pt-8 border-t border-gray-200"><h3 className="text-xl font-bold mb-4">分享这篇文章</h3><div className="flex space-x-4"><button className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">分享到微信</button><button className="px-4 py-2 bg-blue-400 text-white rounded hover:bg-blue-500">分享到微博</button></div></div></article></div>);
}
创建 API 路由
在 app/api
目录中创建 API 端点:
// app/api/hello/route.ts
// app/api/route.ts
import { NextRequest, NextResponse } from 'next/server'// 模拟用户数据
const users = [{ id: '1', name: '张三', email: 'zhangsan@example.com' },{ id: '2', name: '李四', email: 'lisi@example.com' },{ id: '3', name: '王五', email: 'wangwu@example.com' }
];export async function GET() {return NextResponse.json({ success: true,data: users,timestamp: new Date().toISOString()})
}export async function POST(request: NextRequest) {try {const body = await request.json()// 验证请求数据if (!body.name) {return NextResponse.json({ success: false, error: '名称不能为空' },{ status: 400 })}// 模拟创建新用户const newUser = {id: (users.length + 1).toString(),name: body.name,email: body.email || null}// 在真实应用中,这里会将用户添加到数据库// 这里只是模拟return NextResponse.json({ success: true, data: newUser }, { status: 201 })} catch (error) {return NextResponse.json({ success: false, error: '请求处理失败' },{ status: 500 })}
}
数据获取
在服务器组件中进行数据获取(默认情况下,page.tsx
是服务器组件):
// app/blog/page.tsx - 服务器组件
import Link from 'next/link';
import BlogActions from './components/BlogActions';// 模拟博客数据
const blogs = [{ id: '1', title: 'Next.js入门指南',excerpt: '了解如何使用Next.js构建现代Web应用',author: {name: '张三',avatar: 'https://randomuser.me/api/portraits/men/1.jpg'},publishedAt: '2023-05-15',tags: ['Next.js', 'React', '前端开发']},{ id: '2', title: 'React服务器组件详解',excerpt: '深入理解React服务器组件的工作原理',author: {name: '李四',avatar: 'https://randomuser.me/api/portraits/women/2.jpg'},publishedAt: '2023-06-22',tags: ['React', '服务器组件', '性能优化']},{ id: '3', title: 'TypeScript与Next.js',excerpt: '如何在Next.js项目中充分利用TypeScript',author: {name: '王五',avatar: 'https://randomuser.me/api/portraits/men/3.jpg'},publishedAt: '2023-07-10',tags: ['TypeScript', 'Next.js', '类型安全']}
];// 模拟获取博客列表函数
async function getBlogs() {// 模拟网络延迟await new Promise(resolve => setTimeout(resolve, 500));return blogs;
}export default async function BlogsPage() {// 获取博客数据const blogList = await getBlogs();return (<div className="container mx-auto px-4 py-8"><div className="flex justify-between items-center mb-8"><h1 className="text-3xl font-bold">博客列表</h1><Link href="/blog/new" className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition">创建新博客</Link></div><div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">{blogList.map(blog => (<div key={blog.id} className="border rounded-lg overflow-hidden hover:shadow-md transition"><div className="p-6"><h2 className="text-xl font-bold mb-3">{blog.title}</h2><p className="text-gray-600 mb-4">{blog.excerpt}</p><div className="flex flex-wrap gap-2 mb-4">{blog.tags.map(tag => (<span key={tag} className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">{tag}</span>))}</div><div className="flex items-center text-sm text-gray-500 mb-4"><img src={blog.author.avatar} alt={blog.author.name}className="w-6 h-6 rounded-full mr-2"/><span>{blog.author.name}</span><span className="mx-2">•</span><span>{new Date(blog.publishedAt).toLocaleDateString('zh-CN')}</span></div><div className="flex space-x-2"><Link href={`/blog/${blog.id}`} className="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm">查看全文</Link><Link href={`/blog/edit/${blog.id}`} className="px-3 py-1 bg-green-500 text-white rounded hover:bg-green-600 text-sm">编辑</Link><BlogActions blogId={blog.id} /></div></div></div>))}</div>{blogList.length === 0 && (<div className="text-center py-12"><p className="text-gray-500 mb-4">暂无博客内容</p><Link href="/blog/new" className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">创建第一篇博客</Link></div>)}<div className="mt-8 text-center"><Link href="/" className="text-blue-600 hover:underline">返回首页</Link></div></div>);
}
使用客户端组件进行交互:
// blog/components/BlogActions.tsx
'use client';interface BlogActionsProps {blogId: string;
}export default function BlogActions({ blogId }: BlogActionsProps) {const handleDelete = () => {alert(`删除功能尚未实现:${blogId}`);// 这里可以实现实际的删除逻辑};return (<button className="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600 text-sm"onClick={handleDelete}>删除</button>);
}
安装依赖
使用 pnpm 安装项目依赖:
# 安装依赖
pnpm add axios swr# 安装开发依赖
pnpm add -D typescript @types/react eslint
运行开发服务器
pnpm dev
构建和部署
# 构建应用
pnpm build# 启动生产环境服务器
pnpm start
pnpm 优势
pnpm相比npm和yarn有以下优势:
- 磁盘空间效率:pnpm使用硬链接和内容寻址存储,减少了重复的依赖
- 安装速度快:比npm和yarn快2-3倍
- 更严格的依赖管理:通过使用符号链接确保依赖访问更安全
- 内置monorepo支持:无需额外工具即可管理多包项目
pnpm 常用命令
# 初始化项目
pnpm init# 安装所有依赖
pnpm install# 添加依赖
pnpm add [package]# 添加开发依赖
pnpm add -D [package]# 更新依赖
pnpm update# 运行脚本
pnpm [script]# 删除依赖
pnpm remove [package]
Node.js 与 Next.js 的关系
Node.js 与 Next.js 的基本关系
Next.js 是构建在 Node.js 之上的 React 框架。这种关系可以从多个方面理解:
- 运行时环境:Next.js 使用 Node.js 作为其服务器端运行时环境
- 构建工具:Next.js 利用 Node.js 生态系统中的工具(如 webpack、babel)进行代码构建和转换
- 包管理:Next.js 项目通过 npm、yarn 或 pnpm 等 Node.js 包管理器管理依赖
- API 实现:Next.js 的服务器端 API 路由基于 Node.js 的 HTTP 模块实现
Next.js 的运行时环境
Next.js 确实在 Node.js 环境中启动了一个服务器来接收来自浏览器的请求。这个过程在不同模式下有所不同:
开发环境 (pnpm dev
)
在开发模式下:
- Next.js 启动一个 Node.js HTTP 服务器(默认监听 3000 端口)
- 该服务器具有热模块替换(HMR)功能,允许实时更新
- 当浏览器请求到达时,Next.js 服务器根据请求的路径:
- 对于页面请求:执行服务器端渲染(SSR)或提供静态生成(SSG)的内容
- 对于 API 请求:执行相应的 API 路由处理函数
- 对于静态资源:提供 public 目录中的文件
- 开发服务器还处理源代码编译、打包和监视文件变化
浏览器请求 → Node.js服务器(Next.js) → 路由解析 → 页面渲染/API处理 → 响应返回
生产环境 (pnpm build
然后 pnpm start
)
在生产模式下:
-
pnpm build
预先构建所有可能的页面和资源- 静态生成(SSG)的页面被预渲染为HTML
- 服务器组件被优化和序列化
- JavaScript包被优化和代码分割
-
pnpm start
启动一个优化的 Node.js 生产服务器- 这个服务器比开发服务器轻量得多
- 它主要负责:
- 提供预构建的静态资源
- 处理动态SSR请求
- 执行API路由
浏览器请求 → Node.js生产服务器 → 提供预构建资源/动态渲染 → 响应返回
渲染模式与Node.js的关系
-
服务器端渲染(SSR)
- 每次请求都在 Node.js 环境中执行React组件渲染
- 生成HTML并发送给浏览器
- 适用于需要最新数据的页面
-
静态站点生成(SSG)
- 在构建时在 Node.js 环境中预渲染HTML
- 请求来临时直接提供静态HTML
- 适用于内容不经常变化的页面
-
增量静态再生成(ISR)
- 结合SSG和SSR的优点
- 预渲染HTML,但在指定间隔后在Node.js环境中重新生成
-
客户端渲染
- 初始HTML由服务器提供
- 后续渲染和数据获取在浏览器中发生
- 减轻Node.js服务器负载
Node.js 环境的限制
在使用Next.js时,需要注意Node.js环境的一些特点和限制:
-
服务器组件 vs 客户端组件
- 服务器组件在Node.js环境中运行,可以访问文件系统、环境变量等
- 客户端组件无法访问Node.js特有的功能和API
-
API路由的Node.js能力
- API路由在Node.js环境中执行,可以使用完整的Node.js功能
- 包括数据库连接、文件系统操作、复杂计算等
-
边缘运行时
- Next.js还支持Edge Runtime(一种轻量级运行时)
- Edge Runtime比Node.js更受限,但部署和冷启动更快
部署架构
Next.js应用的部署涉及到Node.js服务器的管理:
-
传统服务器
- 部署完整的Node.js服务器
- 例如在AWS EC2、DigitalOcean等上运行
-
无服务器函数
- 将Next.js应用部署为无服务器函数
- 例如AWS Lambda、Vercel等
-
静态导出
- 完全静态导出,不需要Node.js服务器
- 使用
next export
命令 - 适用于不需要SSR或API路由的项目
本目录示例代码说明
本目录包含以下示例文件:
-
page.tsx: 一个简单的 Next.js 首页示例,展示了:
- 页面组件结构
- 使用
next/head
管理头部元素 - 使用
next/link
进行客户端导航 - React hooks 在 Next.js 中的使用
-
[id].tsx: 展示动态路由的实现,包括:
- 动态路由参数获取
- 静态生成 (generateStaticParams)
- 数据获取模式
-
route.ts: API 路由示例,展示了:
- 基于请求方法的处理逻辑
- 响应处理
- 错误处理
注意:这些示例基于 App Router 模式实现。
App Router 和 Pages Router 的区别
特性 | App Router (app/) | Pages Router (pages/) |
---|---|---|
组件模型 | React Server Components | 客户端组件 |
数据获取 | 组件中的 fetch 函数 | getServerSideProps/getStaticProps |
布局 | layout.tsx | _app.tsx 和布局组件 |
嵌套布局 | 多个 layout.tsx | 需手动实现 |
加载状态 | loading.tsx | 需手动实现 |
错误处理 | error.tsx | 需手动实现或使用 Error Boundaries |
API 路由 | route.ts 处理程序 | pages/api/*.ts |
进阶资源
- Next.js 官方文档
- Next.js App Router 文档
- Next.js 学习课程
- pnpm 官方文档
- Vercel 平台(Next.js 的创建者提供的托管服务)
- Next.js GitHub 仓库
练习建议
- 创建一个包含多个页面的 Next.js 应用(使用 App Router)
- 实现动态路由和数据获取
- 添加多级嵌套布局
- 创建 API 路由
- 实现错误处理和加载状态
- 将项目部署到 Vercel 或其他托管平台
容器知识入门教程
容器技术是现代应用开发和部署的基石,本教程将介绍 Docker 容器的基础知识。
Docker 背景介绍
什么是 Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 或 Windows 操作系统的机器上。Docker 使用了 Linux 内核的多种功能(如 Namespaces、Cgroups)来创建独立的容器。
Docker 的发展历史
- 2013年:Docker 由 dotCloud 公司(后更名为 Docker Inc.)推出,最初是 dotCloud 平台的内部项目
- 2014年:Docker 1.0 发布,正式进入生产环境
- 2015年:Docker Compose、Docker Swarm 和 Docker Machine 等工具发布,生态系统开始繁荣
- 2016年:引入内置的编排功能
- 2017年:集成 Kubernetes 支持
- 至今:持续迭代发展,成为容器化技术的事实标准
为什么需要 Docker
在 Docker 出现之前,开发者面临以下问题:
- 环境不一致:开发、测试、生产环境的差异导致"在我电脑上能运行"的问题
- 部署复杂:应用依赖安装复杂,配置繁琐
- 资源利用率低:传统虚拟化方案资源占用高,启动慢
- 应用隔离困难:不同应用之间相互影响
- 扩展性差:难以快速扩容和缩容
Docker 通过容器化技术解决了这些问题:
- 一致的环境:无论在哪里运行,容器内的环境都是一样的
- 轻量级:容器共享主机系统内核,比传统虚拟机占用资源少,启动更快
- 隔离:容器之间彼此隔离,不会相互影响
- 可移植性:构建一次,到处运行
- 微服务支持:适合现代微服务架构,每个服务独立容器化
Docker vs 虚拟机
特性 | Docker 容器 | 虚拟机 |
---|---|---|
启动时间 | 秒级 | 分钟级 |
存储空间 | MB级 | GB级 |
性能 | 接近原生 | 有所损耗 |
系统资源 | 共享宿主机内核 | 独立内核 |
隔离性 | 进程级隔离 | 完全隔离 |
运行密度 | 单机可运行数十至数百个容器 | 单机通常运行数个虚拟机 |
1. Docker 安装
Windows 安装
- 下载 Docker Desktop for Windows
- 双击安装程序并按照提示完成安装
- 安装完成后,Docker Desktop 会自动启动
- 在系统托盘中可以看到 Docker 图标,表示 Docker 服务正在运行
macOS 安装
- 下载 Docker Desktop for Mac
- 将下载的
.dmg
文件拖到应用程序文件夹 - 启动 Docker Desktop 应用
- 等待 Docker 初始化完成,顶部状态栏会显示 Docker 图标
Linux 安装 (Ubuntu)
# 更新软件包索引
sudo apt-get update# 安装依赖
sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg \lsb-release# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 设置稳定版仓库
echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 安装 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io# 将当前用户添加到 docker 组(避免每次都使用 sudo)
sudo usermod -aG docker $USER
# 需要重新登录使配置生效
验证安装
# 查看 Docker 版本
docker --version# 运行测试容器
docker run hello-world
2. 常用 Docker 命令
镜像相关命令
# 搜索镜像
docker search ubuntu# 拉取镜像
docker pull ubuntu:latest# 列出本地镜像
docker images# 删除镜像
docker rmi ubuntu:latest# 构建镜像
docker build -t myapp:1.0 .
容器相关命令
# 创建并启动容器
docker run -d -p 8080:80 --name mywebserver nginx# 列出所有运行中的容器
docker ps# 列出所有容器(包括已停止的)
docker ps -a# 停止容器
docker stop mywebserver# 启动已停止的容器
docker start mywebserver# 重启容器
docker restart mywebserver# 删除容器
docker rm mywebserver# 进入容器交互式终端
docker exec -it mywebserver bash# 查看容器日志
docker logs mywebserver# 查看容器资源使用情况
docker stats mywebserver
Docker Compose 命令
# 启动所有服务
docker-compose up -d# 停止所有服务
docker-compose down# 查看服务状态
docker-compose ps# 查看服务日志
docker-compose logs# 重建服务
docker-compose build
网络和存储命令
# 创建网络
docker network create mynetwork# 列出网络
docker network ls# 创建卷
docker volume create mydata# 列出卷
docker volume ls
示例项目说明
本目录包含一个简单的 Docker 示例项目,包括:
- Dockerfile: 定义如何构建应用容器镜像
- docker-compose.yml: 定义多容器应用的服务、网络和卷
- app.js: 一个简单的 Node.js Express 应用
- package.json: Node.js 应用依赖定义
如何运行示例项目
-
确保已安装 Docker 和 Docker Compose
-
在此目录下运行:
docker-compose up -d
-
访问应用:
- Web 应用: http://localhost:3000
- 健康检查: http://localhost:3000/health
项目文件说明
Dockerfile
这个文件定义了如何构建应用容器:
- 使用 Node.js 16 Alpine 作为基础镜像
- 设置工作目录
- 复制和安装依赖
- 配置环境变量
- 指定启动命令
docker-compose.yml
这个文件定义了完整的应用栈:
- Web 应用服务 (使用 Dockerfile 构建)
- PostgreSQL 数据库服务
- Redis 缓存服务
- 网络配置
- 卷配置(持久存储)
app.js
一个简单的 Express 服务器,展示容器环境信息和健康检查端点。
Docker 网络详解
Docker 网络是容器化环境中的关键组件,提供了容器间的通信基础设施。
Docker 网络的主要作用
- 容器间通信:允许不同容器在不暴露端口到主机的情况下相互通信
- 隔离环境:可以创建完全隔离的网络环境,提高应用安全性
- 服务发现:容器可以通过容器名称而非IP地址相互访问,简化服务发现
- 多主机连接:使用overlay网络可以连接不同主机上的容器
- 网络策略控制:可以精细控制哪些容器可以相互通信
常用网络类型
# 查看可用的网络驱动
docker info | grep "Network"# 创建自定义网络
docker network create --driver bridge my-network# 在创建容器时连接到指定网络
docker run --network=my-network -d --name container1 nginx# 将已有容器连接到网络
docker network connect my-network container2
网络驱动类型
- bridge: 默认网络驱动,适用于同一主机上的容器
- host: 直接使用主机网络,移除容器与主机间的网络隔离
- overlay: 用于Docker Swarm环境中,连接多个Docker守护进程
- macvlan: 允许容器拥有独立的MAC地址,直接连接到物理网络
- none: 禁用所有网络
Docker 卷详解
Docker卷提供了容器数据的持久化存储解决方案,解决了容器销毁后数据丢失的问题。
Docker 卷的主要作用
- 数据持久化:即使容器被删除,存储在卷中的数据依然保留
- 数据共享:多个容器可以挂载相同的卷,实现数据共享
- 备份与恢复:简化数据备份和恢复流程
- 性能优化:与容器内部存储相比,卷通常提供更好的I/O性能
- 存储解耦:将应用与数据分离,提高系统灵活性和可维护性
卷的使用方式
# 创建卷
docker volume create my-data# 查看卷的详细信息
docker volume inspect my-data# 在容器中使用卷
docker run -d --name my-container -v my-data:/app/data nginx# 使用绑定挂载(挂载主机目录)
docker run -d --name my-container -v $(pwd):/app/data nginx# 备份卷中的数据
docker run --rm -v my-data:/source -v $(pwd):/backup alpine tar -czvf /backup/my-data-backup.tar.gz -C /source .
卷的类型
- 命名卷: 由Docker管理的命名存储空间
- 绑定挂载: 直接映射主机文件系统的路径到容器
- tmpfs挂载: 将数据存储在主机的内存中,不写入文件系统
使用卷时要考虑权限、备份策略和数据生命周期管理,以确保数据安全和可靠性。
Docker 进阶概念
- Docker 多阶段构建:优化镜像大小和构建过程
- Docker 网络:bridge、host、overlay 等不同网络驱动
- Docker 卷:持久化数据存储
- Docker Swarm:Docker 原生集群和编排工具
- Docker 安全:最佳实践和安全配置
- Docker Registry:镜像仓库和分发
相关资源
- Docker 官方文档
- Docker Hub
- Docker Compose 文档
- Dockerfile 最佳实践
练习建议
- 尝试为不同语言的应用创建 Dockerfile
- 练习使用 Docker Compose 设置多容器应用
- 探索 Docker 卷和网络
- 学习如何在生产环境中安全地部署 Docker 容器
全栈博客案例
代码仓库
go-learning:https://github.com/BaiZe1998/go-learning/tree/main/doutok-course/basic-knowledge