前端Docker教程
Docker教程前端有这篇就够了!!!
Docker
前言
日趋复杂的运维开发环境,对虚拟服务器及应用服务的要求更加的多元化。我们需要更加容易扩展、性能优越、方便监控的管理服务,容器化应用、容器化运维应运而生。
【工欲善其事,必先利其器】需要准备的环境(三选一):
- Linux环境(Centos 7以上/Debian 8以上/Ubuntu 16.04LTS以上版本)
- Windows 64位专业版/企业版/教育版(Build 15063以上)
- macOS Sierra 10.12以上的版本
如果,你有了上面的环境,就可以很快速的学习。
【收获什么】:
- 理解/安装docker容器技术
- 秒级快速部署mysql、nginx、tomcat等服务
- 搭建自己的git服务器
- 使用容器技术发布nodejs + mongodb + koa + vue的应用
概念
1. 什么是容器化?
容器化是将应用程序或服务、其依赖项及其配置(抽象化为部署清单文件)一起打包为容器映像的一种软件开发方法。
软件容器充当软件部署的标准单元,其中可以包含不同的代码和依赖项。 按照这种方式容器化软件,开发人员和 IT 专业人员只需进行极少修改或不修改,即可将其部署到不同的环境。
容器化应用程序在容器主机上运行,而容器主机在 OS(Linux 或 Windows)上运行。因此,容器的占用比虚拟机 (VM) 映像小得多。
【容器化的特点】:
- 一致的运行环境
- 可伸缩性
- 更方便的移植
- 隔离性
2. 了解Docker
Docker是用GO语言开发的应用容器引擎,基于容器化,沙箱机制的应用部署技术。可适用于自动化测试、打包,持续集成和发布应用程序等场景,包括阿里云,亚马逊在内的云计算服务商都采用了docker来打造serverless服务平台。它不仅仅可以部署项目,还可以用于数据库搭建,nginx服务搭建,nodejs、php等编程语言环境搭建。
PS: docker现已改名为moby
Docker中的三个重要概念:
镜像(image):
分片的(只读)文件系统,由Dockerfile创建,它独立、易扩展、更效率
容器(container):
由Docker进程创建和管理的:文件系统 + 系统资源 + 网络配置 + 日志管理 Docker是docker镜像的运行环境,所以容器的概念就比较好理解了
仓库(registry):
用来远端存储docker镜像版本控制、变更管理、为持续集成与快速部署提供便利
容器与镜像的关系类似于面向对象编程中的对象与类。
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
3. Docker vs 虚拟机
【区别】:
- 容器是应用层的抽象,它将代码和依赖关系打包在一起。 多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器在用户空间中作为独立进程运行。 容器占用的空间比VM少(容器映像的大小通常为几十MB),可以处理更多的应用程序,并且需要更少的VM和操作系统。
- 虚拟机(VM)是物理硬件的抽象,将一台服务器转变为多台服务器。 管理程序允许多台VM在单台机器上运行。 每个VM都包含操作系统的完整副本,应用程序,必要的二进制文件和库 - 占用数十GB。 虚拟机也可能很慢启动。
【总结】:
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 |
一般为 MB
|
一般为 GB
|
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
开发/环境定制 | 方便(命令行、面向对象式) | 进入虚拟机 |
【相同点】:
- 文件隔离/文件共享(沙箱)
- 资源隔离
- 网络隔离
- 支持多种宿主环境(扩展)
- 快照/镜像(版本控制/变更管理)
【不同点】:
- 不同的资源管理/依赖//释放(虚拟机占用更多的系统资源)
- 不同的应用运行环境
- Docker是写时复制
- 不同的日志方式(Docker收集日志,而虚拟机需要在虚拟系统里面看日志)
- 不同的交互方式(Docker偏shell,虚拟机偏GUI)
4. Docker的工作原理(重点)
Docker是容器化部署技术,它主要作用在于通过运行容器来实现应用部署,而容器基于镜像运行。
简单地说,就是将你的项目和依赖包(基础镜像)打成一个带有启动指令的项目镜像,然后在服务器创建一个容器,让镜像在容器内运行,从而实现项目的部署。
服务器就是容器的宿主机,docker容器与宿主机之间是相互隔离的。
Docker 的基础是Linux容器(LXC:Linux Containers)等技术。
一般情况流程:
Docker流程:
这其中,发生了什么?
- Docker会自己拉取镜像,若本地已经存在该镜像,则不用到网上去拉取
- 创建新的容器
- 分配文件系统并且挂着一个可读写的层,任何修改容器的操作都会被记录在这个读写层上,你可以保存这些修改成新的镜像,也可以选择不保存,那么下次运行改镜像的时候所有修改操作都会被消除
- 分配网络\桥接接口,创建一个允许容器与本地主机通信的网络接口
- 设置ip地址,从池中寻找一个可用的ip地址附加到容器上,换句话说,localhost并不能访问到容器
- 运行你指定的程序
- 捕获并且提供应用输出,包括输入、输出、报错信息
Docker的价值:
从应用架构角度:统一复杂的构建环境;
从应用部署角度:解决依赖不同、构建麻烦的问题,结合自动化工具(如jenkins)提高效率。
从集群管理角度:规范的服务调度,服务发现,负载均衡
应用
1. Docker安装和配置(偷个懒)
安装教程地址:
www.runoob.com/docker/maco…
配置镜像加速地址:
www.runoob.com/docker/dock…
2. Docker的命令
1. 查看docker版本
docker --version
复制代码
2. 运行第一个Docker应用
// 使用docker run命令docker run hell-world// 下载ubuntu镜像打印“from ububtu”
// -i: 以交互模式运行容器,通常与 -t 同时使用
// -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用docker run -it ubuntu echo "from ubuntu" 复制代码
3. 查看容器运行状态
使用docker ps
命令来查看正在运行的容器的状态,-a
参数来查看所有的已经运行的容器(无论是否停止)
4. 重要命令
run
创建一个新的容器并运行一个命令
exec
可以进入到容器里面去
-it
是提供交互式的终端工具
-d
是让镜像容器在后台去持续运行
--name
指定容器的名称
-p
容器内部端口映射到主机的端口
-v
挂载宿主机的文件目录到镜像里面去
-e
设置环境变量
// 运行镜像
docker run -it -d --name test ubuntu
// 进入容器
docker exec -it test /bin/bash
// 把本机的Downloads文件映射到ubuntu的home文件下
docker run -v ~/Downloads/:/home -itd --name test1 ubuntu复制代码
5.容器的管理
- 启动
start
- 停止
stop
- 重启
restart
- 删除已停止容器
rm
docker stop test
复制代码
3. 常见的应用场景介绍
Docker提供了轻量级的虚拟化,相比于虚拟机,可以在同一台机器上创建更多数量的容器。
【常见的应用场景】:
- 快速部署
- 隔离应用
- 提高开发效率
- 版本控制
1. 快速部署
我们尝试着来部署一个mysql:
docker run -d --name mysql-test -e MYSQL_ROOT_PASSWORD=123456 mysql
复制代码
同样的道理,我们来部署一个nginx:
注意:这里没有映射服务端口,所以在80
端口是看不到index.html
中的内容的。需要加入-p
参数来映射端口!!
docker run -d --name web -p 8000:80 -v ${your_dir}:/usr/share/nginx/html nginx
复制代码
2. 隔离应用
我们可以同时跑两个mysql,两个nginx,指定不同的端口进行映射:
把mysql-test1
映射到8001
端口,把mysql-test2
映射到8002
端口。
docker run -d --name mysql-test1 -p 8001:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
docker run -d --name mysql-test2 -p 8002:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
复制代码
把web1映射到8100端口,把web2映射到8200端口。
docker run -d --name web1 -p 8100:80 -v ${your_dir}:/usr/share/nginx/html nginx
docker run -d --name web2 -p 8200:80 -v ${your_dir}:/usr/share/nginx/html nginx
复制代码
3. 提高开发效率
一致的运行环境
由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。
更快速的启动时间
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
更高效的复用系统资源
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
仓库/镜像机制
使用仓库可以方便的在任何有docker进程的虚拟机/服务器/主机上运行docker应用,环境的统一,让它们的部署变的非常的简单。
4. 版本控制
Docker容器还可以像git仓库一样,可以让你提交变更到Docker镜像中并通过不同的版本来管理它们,来看看下面的例子:
我们之前创建了一个mysql
,现在,我们使用commit
命令就可以给它做一个快照,打上一个tag
。
在后面的课程中,我们会详细的介绍Docker的常见命令
4. 制作Docker镜像
Dockerfile 是一个由一堆命令+参数构成的脚本,使用
docker build
即可执行脚本构建镜像,自动的去做一些事,主要用于进行持续集成。
一般,Dockerfile 共包括四部分:
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行指令
1. Dockerfile文件示例:
FROM node:10LABEL maintainer=atiedan666666@163.com# 创建 app 目录
WORKDIR /app# 把 package.json,package-lock.json(npm@5+) 或 yarn.lock 复制到工作目录(相对路径)
COPY ["package.json","*.lock","./"]# 打包 app 源码
# 特别注意:要指定工作目录中的文件名
COPY src ./src# 使用.dockerignore文件,上面两个COPY合并成一个
# COPY . .# 使用Yarn安装 app 依赖
# 如果你需要构建生产环境下的代码,请使用:
# --prod参数
RUN yarn --prod --registry=https://registry.npm.taobao.org# 对外暴露端口 -p 4000:3000
EXPOSE 3000CMD [ "node", "src/index.js" ]
复制代码
2. 本地生成node应用
当Node.js遇见Docker,下面介绍Docker在前端中的应用:
一个简单的Koa应用:
const Koa = require('koa');
const app = new Koa();// response
app.use(ctx => {ctx.body = 'Hello Koa!!';
});app.listen(3000);
复制代码
3. 打包镜像
使用docker build
打包:
docker build -t ${your_name}/${image_name}:${tag} .
复制代码
这里的your_name
代表的是远程仓库中的用户名,或者仓库地址; image_name
为镜像名称,tag
是给镜像打的标签,用于版本控制。.
代表当前目录例如:
docker build -t tiedan/node-demo:1.0 .
复制代码
4. 使用镜像
使用docker run
运行
// 运行
docker run -d --name nodedemo -p 4000:3000 tiedan/node-demo:1.0
// 查看
docker ps
复制代码
5. Docker-compose
通过 Docker-Compose 用户可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。
Compose 中有两个重要的概念:
- 服务 (service) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
- 项目 (project) :由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
Docker Compose 是 Docker 的独立产品,因此需要安装 Docker 之后在单独安装 Docker Compose .
1. 安装
Window和Mac 的 Docker 桌面版和 Docker Toolbox 已经包括 Compose 和其他 Docker 应用程序,因此 Mac 用户不需要单独安装 Compose, Linux 上我们可以从 Github 上下载它的二进制包来使用,
#下载
sudo curl -L https://github.com/docker/compose/releases/download/1.20.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
#安装
chmod +x /usr/local/bin/docker-compose
#查看版本
docker-compose --version
复制代码
2. 使用
docker-compose.yml
改写:
version: '3'
services:mysql:image: mysqlcontainer_name: test-mysqlports:- "8001:3306"environment:- MYSQL_ROOT_PASSWORD=123456
复制代码
在此文件的当前目录下,使用docker-compose up -d
来执行。
生命周期管理:
创建:run
/up
启动/停止/删除/重启:start/stop/rm/restart
检视/日志:logs
/ps
3. 应用
搭建本地mongo + mongo-express服务
# docker-compose.mongo.yml配置文件
version: '3.1'
services:mongo:image: mongorestart: alwaysenvironment:MONGO_INITDB_ROOT_USERNAME: rootMONGO_INITDB_ROOT_PASSWORD: 123456mongo-express:image: mongo-expressrestart: alwaysports:- 8081:8081environment:ME_CONFIG_MONGODB_ADMINUSERNAME: rootME_CONFIG_MONGODB_ADMINPASSWORD: 123456
复制代码
执行:
# 执行 docker-compose.mongo.yml 如果不加 docker-compose -f 默认执行 docker-compose.mongo.yml
docker-compose -f docker-compose.mongo.yml up -d
复制代码
4. 搭建git服务器
项目地址: github.com/sameersbn/d…
docker-compose.git.yml
文件
// 运行该文件 docker-compose -f docker-compose.git.yml up -d
version: '2.3'services:redis:restart: alwaysimage: redis:5.0.9command:- --loglevel warningvolumes:- redis-data:/var/lib/redis:Zpostgresql:restart: alwaysimage: sameersbn/postgresql:12-20200524volumes:- postgresql-data:/var/lib/postgresql:Zenvironment:- DB_USER=gitlab- DB_PASS=password- DB_NAME=gitlabhq_production- DB_EXTENSION=pg_trgm,btree_gistgitlab:restart: alwaysimage: sameersbn/gitlab:13.11.2depends_on:- redis- postgresqlports:- "10080:80"- "10022:22"volumes:- gitlab-data:/home/git/data:Zhealthcheck:test: ["CMD", "/usr/local/sbin/healthcheck"]interval: 5mtimeout: 10sretries: 3start_period: 5menvironment:- DEBUG=false- DB_ADAPTER=postgresql- DB_HOST=postgresql- DB_PORT=5432- DB_USER=gitlab- DB_PASS=password- DB_NAME=gitlabhq_production- REDIS_HOST=redis- REDIS_PORT=6379- TZ=Asia/Kolkata- GITLAB_TIMEZONE=Kolkata- GITLAB_HTTPS=false- SSL_SELF_SIGNED=false- GITLAB_HOST=localhost- GITLAB_PORT=10080- GITLAB_SSH_PORT=10022- GITLAB_RELATIVE_URL_ROOT=- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphanumeric-string- GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string- GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alphanumeric-string- GITLAB_ROOT_PASSWORD=12345678- GITLAB_ROOT_EMAIL=atiedan666666@163.com- GITLAB_NOTIFY_ON_BROKEN_BUILDS=true- GITLAB_NOTIFY_PUSHER=false- GITLAB_EMAIL=notifications@example.com- GITLAB_EMAIL_REPLY_TO=noreply@example.com- GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com- GITLAB_BACKUP_SCHEDULE=daily- GITLAB_BACKUP_TIME=01:00- SMTP_ENABLED=false- SMTP_DOMAIN=www.example.com- SMTP_HOST=smtp.gmail.com- SMTP_PORT=587- SMTP_USER=mailer@example.com- SMTP_PASS=password- SMTP_STARTTLS=true- SMTP_AUTHENTICATION=login- IMAP_ENABLED=false- IMAP_HOST=imap.gmail.com- IMAP_PORT=993- IMAP_USER=mailer@example.com- IMAP_PASS=password- IMAP_SSL=true- IMAP_STARTTLS=false- OAUTH_ENABLED=false- OAUTH_AUTO_SIGN_IN_WITH_PROVIDER=- OAUTH_ALLOW_SSO=- OAUTH_BLOCK_AUTO_CREATED_USERS=true- OAUTH_AUTO_LINK_LDAP_USER=false- OAUTH_AUTO_LINK_SAML_USER=false- OAUTH_EXTERNAL_PROVIDERS=- OAUTH_CAS3_LABEL=cas3- OAUTH_CAS3_SERVER=- OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false- OAUTH_CAS3_LOGIN_URL=/cas/login- OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate- OAUTH_CAS3_LOGOUT_URL=/cas/logout- OAUTH_GOOGLE_API_KEY=- OAUTH_GOOGLE_APP_SECRET=- OAUTH_GOOGLE_RESTRICT_DOMAIN=- OAUTH_FACEBOOK_API_KEY=- OAUTH_FACEBOOK_APP_SECRET=- OAUTH_TWITTER_API_KEY=- OAUTH_TWITTER_APP_SECRET=- OAUTH_GITHUB_API_KEY=- OAUTH_GITHUB_APP_SECRET=- OAUTH_GITHUB_URL=- OAUTH_GITHUB_VERIFY_SSL=- OAUTH_GITLAB_API_KEY=- OAUTH_GITLAB_APP_SECRET=- OAUTH_BITBUCKET_API_KEY=- OAUTH_BITBUCKET_APP_SECRET=- OAUTH_BITBUCKET_URL=- OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=- OAUTH_SAML_IDP_CERT_FINGERPRINT=- OAUTH_SAML_IDP_SSO_TARGET_URL=- OAUTH_SAML_ISSUER=- OAUTH_SAML_LABEL="Our SAML Provider"- OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient- OAUTH_SAML_GROUPS_ATTRIBUTE=- OAUTH_SAML_EXTERNAL_GROUPS=- OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL=- OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME=- OAUTH_SAML_ATTRIBUTE_STATEMENTS_USERNAME=- OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME=- OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME=- OAUTH_CROWD_SERVER_URL=- OAUTH_CROWD_APP_NAME=- OAUTH_CROWD_APP_PASSWORD=- OAUTH_AUTH0_CLIENT_ID=- OAUTH_AUTH0_CLIENT_SECRET=- OAUTH_AUTH0_DOMAIN=- OAUTH_AUTH0_SCOPE=- OAUTH_AZURE_API_KEY=- OAUTH_AZURE_API_SECRET=- OAUTH_AZURE_TENANT_ID=volumes:redis-data:postgresql-data:gitlab-data:
复制代码
5. 实战案例
docker-compose在前端里面的使用:
Nodejs + mongodb + koa + vue的应用组合:
docker-compose.yml
version: '3'
services:web:image: web:1.0ports:- "8080:80"server:image: server:1.0ports:- "3000:3000"depends_on:- mongodblinks:- mongodb:dbmongodb:image: mongorestart: alwaysenvironment:MONGO_INITDB_ROOT_USERNAME: rootMONGO_INITDB_ROOT_PASSWORD: 123456
复制代码
depends_on
决定了容器加载的先后顺序,这里mongdb
、web
先加载,mongdb
创建完成之后,再来创建server
。
欢迎下方关注公众号获取资料 或者 B站关注 前端铁蛋儿直接看视频
前端Docker教程相关推荐
- 【组队学习】【24期】Docker教程
Docker教程 开源内容: https://github.com/datawhalechina/team-learning-program/tree/master/Docker 基本信息 贡献人员: ...
- 简明docker教程
简明docker教程 一.什么是docker 二.docker与虚拟机比较 三.安装docker 四.基本概念 1.镜像 2.容器 3.数据卷 4.挂载 五.参考资料 有收获的话请加颗小星星,没有收获 ...
- 一小时Docker教程
cSphere.cn – 国内首个docker管理平台 Menu 一小时Docker教程 Docker基础 这篇基础文章是方便用户在使用cSphere平台之前,了解docker基础知识. 针对已经有一 ...
- 推荐20个很有帮助的 Web 前端开发教程
在平常的搜索中,我碰到过很多有趣的信息,应用程序和文档,我把它们整理在下面这个列表.这是收藏的遇到的有用内容的一个伟大的方式,可以在你需要的时候方便查阅.相信你会在这个列表中发现对你很有用的资料. 您 ...
- 简明docker教程 1
<!-- TOC --> 简明docker教程 一.什么是docker 二.docker与虚拟机比较 三.安装docker 四.基本概念 1.镜像 2.容器 3.数据卷 4.挂载 五.参考 ...
- 威联通装linux百度网盘,威联通NAS使用百度云Docker教程,超简单!
原标题:威联通NAS使用百度云Docker教程,超简单! 作为国内一家独大的公有云,百度云是大家现在常用的云存储了.相信很多人的资源都有一部分存在上面,不过由于公有云的性质在那里,在对于数据安全抱有怀 ...
- 【docker教程】docker视频教程(ubuntu)数据卷挂载、数据卷容器volume、端口映射(镜像叠加,分层复用)rootfs、bootfs(没看完)
黑马程序员Docker容器化技术,从零学会Docker教程 可以先看1-13课.以及 docker概述 文章目录 docker概述 ubuntu安装docker docker架构 配置docker镜像 ...
- 前端如何实现音乐盒胶盘的转动_郑州Web前端入门教程之如何实现图片优化?
统计数据显示,图片内容已经占据互联网内容总量的62%,因此想要优化网站性能,图片绝对是优化的热点和重点.图片优化是Web前端工程师必须要掌握的知识点,在接下来的郑州Web前端入门教程就给大家讲解一下如 ...
- Docker教程介绍
Docker教程介绍 教程环境准备 linux 系统 virtualbox 软件安装 教程介绍 0-安装Vagrant,安装 centos 系统. 1-docker 介绍 2-docker 安装 3- ...
- 前端图片有时候能显示有时候不显示_web前端基础教程:两种数据存储思路
Web前端开发基础,Web前端基础教程 数据存储是数据流在加工过程中产生的临时文件或加工过程中需要查找的信息.数据以某种格式记录在计算机内部或外部存储介质上.数据存储要命名,这种命名要反映信息特征的组 ...
最新文章
- 普元EOS开发积累第一篇(常见错误解决方法) 持续更新
- AppleWatch开发教程之Watch应用对象新增内容介绍以及编写运行代码
- CatalanStirling数
- IDEA代码生成插件CodeMaker
- [Python人工智能] 十.Tensorflow+Opencv实现CNN自定义图像分类案例及与机器学习KNN图像分类算法对比
- Less Css 教程
- svd奇异值分解_传统推荐算法(一)SVD推荐(1)解读奇异值分解
- 什么是SQL Server事务日志中的虚拟日志文件?
- 数据结构:实验三 二叉树操作实现
- U盘+WINPE 安装UEFI Ubuntu系统教程
- Java、LotusScript和JavaScript中的自定义事件编程
- 【零基础入门MyBatis系列】第三篇——使用MyBatis完成CRUD
- 谷粒学苑 —— 3、后台系统前端项目创建
- Matlab中text函数在图像中固定位置添加信息的用法
- AcWing 1934. 贝茜放慢脚步
- 关于圆周卷积和fft求卷积的一些看法
- redux与flux
- Django学习笔记(下)
- 深入理解JUC的8锁现象
- 数字信号处理知识点总结(四):快速傅里叶变换(FFT)