docker的部署和使用

Docker 学习教程

Docker容器化解决方案

1.容器简介

首先,我们必须清楚,docker它本身并不是一个容器,它的出现只是用来管理容器的一个工具。
容器是什么?
官方解释:容器是在Linu系统之上,利用cgroup、namespace这种机制共同作用组成的沙箱环境,
		来运行类似mysql、tomcat这些程序的一个【进程】/【线程】。
		
操作系统底层很久之前就已经有了cgroup,namespace这两种机制
cgroup是用来给进程/线程分配cpu、内存、磁盘空间的。
namespace是给这些程序起一个命名,形成命名空间,让程序只在这个命名空间里运行。与其他的程序互相不干扰。
我们称这种机制就叫做容器机制

*******************************************************************************************************
那为什么以前就有了这个机制,没人发现利用呢,因为在当时的科技发展环境的种种因素下,没人注意到这种机制所带来的变化,
且当时的环境也没有到需要这个机制的时候。时势造英雄嘛
********************************************************************************************************


容器呢简单说,就是一个进程,从系统里分出来的/隔离出来的,从一个镜像里运行
这个镜像包括了这个进程运行时所需要的一系列依赖项,配置等等。
因此它具有高度的可移植性、复用性、隔离性。一次打包,到处运行.....

因为容器的这种隔离性,我们可以在物理机资源允许的情况下,理论上可以创建无数个容器。

2.Docker简介

我们常说的docker 他是一种容器化工具,用于创建和管理容器
另外,docker也是国外这家编写docker工具的公司的名称
容器技术,可提供基于镜像的部署模式,可以跨越多种不同的环境,独立运行多种进程、多个应用程序,同时保持各个容器之间的安全性。

Docker的目标(三个)
构建	:做一个docker镜像
运输	:docker pull or push
运行	:docker run

3.Docker部署配置

3.1 安装docker工具
  • 我使用的是CentOS7,内核版本为 3.10.0-693.el7.x86_64
  • 你可以单独创建台CentOS出来,作为本教程的学习环境。
# 开始安装,哦哦哦哦哦,对了,我建议你提前把你的CentOS的网络模式设置成【桥接模式】--->自行百度哈.....
$ cd /etc/yum.repos.d/
$ wget https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo  # 下载docker安装源
$ sed -i 's#download.docker.com#mirrors.ustc.edu.cn/docker-ce#g' docker-ce.repo  # 修改为国内的镜像下载源
$ yum -y install docker-ce
$ systemctl enable --now docker.service # 设为开机启动,并且现在启动这个服务,就是把enbale后的start结合在一起了
$ systemctl status docker.service # 确保处于开启态
# 查看系统中正在监听的端口 ,可以看到并没有nginx 的服务
$ ss -anptu   # 超好用 
 
# ---------------------------------------------------------------------------------------------------------
 
# 安装nginx服务(练习)
$ docker pull nginx:1.21 # 先拉取
$ docker container run -itd --name webNginx -p 8080:80 nginx:1.21
# container:容器的意思
# -itd : -i -interactive 即使没有连接,也要保持标准输入保持打开状态,一般与 -t 连用。
# 	    -t -tty 分配一个伪tty,一般与 -i 连用
# 	    -d –detach 在后台运行容器,并且打印容器id
# --name 容器的名字,自定义
# -p 端口映射,将容器的80端口映射到宿主机的8080端口。
# 后面的nginx:1.21 时具体版本,不指定的话,一般是最新版 latest

$ ip a # 获取本机(宿主机)ip地址,访问 宿主机IP:8080,出现nginx欢迎页
$ docker container ls # 查看所有容器 


#---------------------------------------------------------------------------------------------------------

# 配置镜像加速器(重要)

$ vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}
$ systemctl daemon-reload  # 重新载入系统和服务管理器配置
$ systemctl restart docker.service 

4.Docker基本操作指令

# 先熟悉这些命令,(也可以过个眼熟,等会用的时候,再查)
$ docker version # 查看docker版本信息
$ docker container ls # 查看docker的容器信息
$ docker images  # 查看docker的镜像信息
$ docker network ls # 查看docker里的网络信息
$ docker volume ls  # 查看数据卷,例如,我们有时候需要将Linux里的某个目录挂载到容器里。
$ docker search [镜像名称] # 搜索镜像 例如:docker search mysql
$ docker pull [镜像名:tag] #如果不指定版本(tag),默认下载最新版 docker pull mysql:5.7
$ docker rmi [镜像ID] # 删除一个镜像,docker rmi feb6csjwjf  -f 强制删除
$ docker rmi [镜像ID] [镜像ID] [镜像ID] # 删除多个镜像
$ docker run -d -it -p # 创建容器
$ docker ps  # 列出正在运行的容器 -a : 列出历史运行过的容器
$ docker start [容器ID] # 启动容器
$ docker restart [容器ID] # 重启容器
$ docker stop [容器ID] # 停止容器
$ docker kill [容器ID] # 强制停止当前容器
$ docker logs -tf --tail [容器ID] # 查看日志
$ docker top [容器ID] # 查看容器中进程的信息
$ docker exec -it [容器ID] /bin/bash # 进入当前正在运行的容器,后面的/bin/bash 是它用的是那种解释器
$ docker cp [容器ID]:[容器内路径] [目的主机路径] # 将容器内文件拷贝出来到主机上
$ docker cp [目的主机路径] [容器ID]:[容器内路径] # 将主机的文件拷贝到容器内
$ docker inspect nginx:1.21  # 查看镜像的详细信息
  • Docker官方仓库地址: Docker镜像地址
  • 进去后注册一个账号,然后在终端登录。
$ docker login  #  进行官方仓库登录,以后拉去较大的镜像不会报错
$ docker logout #  登出

5.Docker镜像管理

# 我们可以在终端上登陆hub.docker仓库,演示拉取tomcat镜像
$ docker login
$ docker search tomcat # 看看有什么镜像
$ docker pull tomcat:8.5 # 我拉取的是指定的版本号8.5
# 然后使用docker images 查看刚才拉取的镜像
5.1 导出/导入镜像
# 会有这样一种情况,我们需要将这台机器上的一个镜像,传输到另外一台机器上,我们看看如何操作
# 现在假设有两台已经安装好docker的CentOS,分别是docker-01 ,docker-02
# 假设docker-01 上有一个nginx镜像,现在的需求是把这个镜像导出来并导入到docker-02里。

# 1. 将docker-01里的nginx进行打包
$ docker image save nginx:1.21 > nginx121.tar # 先打成压缩包

# 2. 在docker-01 里运行这条命令,将压缩包传过去,然后你会在docker-02 里用ls命令看到这个压缩包
$ scp nginx121.tar root@192.168.84.133:/root/ 

# 3.在docker-02 里加载这个指定的镜像压缩包 -i 是指定压缩包
$ docker image load -i nginx121.tar

# 然后在docker-02里创建容器,可以发现,他不再去仓库里直接下载了,而是可以直接从本地拿到
docker container run -itd --name nginxwebserver -p 8081:80 nginx:1.21
5.2 删除镜像
$ docker ps -a # 查看正在运行和已经运行过的镜像,注意看STATUS的那一列,如果是UP,或者是Exited
# 如果是Exited,我们可以直接用以下命令删除(如果你直接docker rmi 去删除,会报错,提示你镜像在运行)
$ docker container rm [镜像名字]  

# 如果是Up,表明在运行,我们先停止,再删除。 
$ docker stop [镜像名字]
$ docker container rm [镜像名字]

# 然后最后一步再删除
$ docker rmi  [镜像ID/或者名字] # rmi 其实就是 image rm的简写  docker rmi nginx:12.1
# 大功告成!
5.3 上传/拉取镜像
# 首先,我们需要登陆hub.docker.com网站,然后创建一个属于自己的仓库。随便起一个名字,例如叫Test
# 我们假设要上传属于自己的nginx,例如版本是1.21,我们首先要更改它的tag标识,让他有一个自己独有的标识
# 其实我们直接上传官方的nginx镜像到自己的仓库里也可以,这里只是做一个示例,演示!

# nginx        1.21      0e901e68141f   21 months ago   142MB

# 将上面的nginx更改为zhengtf/nginx:1.21 ,这里的zhengtf 是你自己注册时候的用户名,作为一个标志,必须要写。
$ docker tag nginx:1.21 zhengtf/nginx:1.21  

# docker images 后就变成下面这样子(我的理解是,相当于复制了一个出来)
# nginx        		   1.21     0e901e68141f   21 months ago   142MB
# zhengtf/nginx        1.21      0e901e68141f   21 months ago   142MB

# 然后将zhengtf/nginx上传上去
$ docker push zhengtf/nginx:1.21  
# 然后稍等一会,就会在你的Test仓库里看见这个镜像

# 待到上传成功了,我们还可以从仓库里拉出来我们刚才上传的镜像,例如我在docker-02里演示。
# 假设,另外一台服务器要拉去你刚才的镜像,那它就可以这样。
$ docker pull zhengtf/nginx:1.21 # 等待拉取成功即可
$ docker images # 查看刚才拉取的镜像是否存在

6. Docker容器管理

6.1 容器的启停
$ docker container ls # 查看容器

$ docker container run -itd --name TestServer -p 8081:80 nginx:1.21 # 创建容器,这里的参数上面有提到过
# 你还可以使用curl去查看
$ curl http://localhost:8081 # 会出现nginx的欢迎页

$ docker restart TestServer # 重启容器
$ docker stop TestServer # 停止容器

# 然后去查看这个容器,他就没了 
$ docker container ls 

# 然后去查看这个停止中的容器
$ docker ps -a # 此时的Status是Exited

# 那如何启动一个【停止】的容器呢?
$ docker start TestServer
# 然后用docker ps -a 查看他的状态就是 Up

# 然后强制停止容器
$ docker kill TestServer

# 如何删掉一个已经停止的容器?
$ docker container rm TestServer

# 我们如何删除全部的容器
$ docker container rm -f `docker ps -a -q` # docker ps -a -q 输出的是每一个容器的ID
6.2 进入容器内部
# 设想,我们想要进去这个容器里面来查看或者修改里面的东西,我们该如何进去?拿nginx为例,我们要查看Nginx的配置文件。
# 首先,我们需要创建运行一个容器,这个容器是以nginx镜像为基础创建的。
$ docker container run -itd --name ServerNginx -p 8081:80 nginx:1.21 # 创建容器

# 其次,我们使用exec指令进入该容器
$ docker exec -it ServerNginx bash # 这个bash指明需要何种解释器。如果bash不支持,请使用sh

# 我们可以发现终端的命令提示符已经改变,变成容器的ID了,表明我们已经进入该容器内部

# 最后,我们可以查看一下nginx的配置文件
$ cat /etc/nginx/conf.d/default.conf

# 退出容器
$ exit
6.3 容器与宿主机之间传输文件
# 我们实际演示,我们要把 /etc/nginx/conf.d/default.conf  默认配置文件传到宿主机上进行修改,完了后给他传回去。
$ docker cp ServerNginx:/etc/nginx/conf.d/default.conf .   # 将配置文件拷贝到当前目录下

# 然后,我们就可以ls看到当前目录下有default.conf ,我们可以进行修改等等,然后传回去
$ docker cp default.conf ServerNginx:/etc/nginx/conf.d/default.conf  # 拷贝回去

# 然后重启容器,再去进入容器内部,查看修改是否生效即可
$ docker restart ServerNginx

7.Docker数据卷的管理

我们想要将目录挂载到nginx下,我们要如何做?

7.1 挂载时创建卷
# 首先,创建一个目录用来测试
$ mkdir /opt/webserver
$ docker run -itd --name ServerNginx -p 8081:80 -v /opt/webserver:/usr/share/nginx/html nginx:1.21
# 如上,就是利用-v参数,来挂载这个目录到容器里的nginx下的目录 -v volume

# 然后我们可以利用curl来看看(肯定是403状态页面)
$ curl -I http://localhost:8081  # -I 参数: 仅展示响应的响应行和响应头,不展示响应体,也就是不会展示Html代码 
$ curl http://localhost:8081 # 出现403界面

# 我们做一个测试,我们向/opt/webserver下写一个index.html文件,里面写一句hello world,然后再去利用curl查看该网站的欢迎页。
$ echo "Hello World" > /opt/webserver/index.html
$ curl http://localhost:8081
# 可以看到,打印出来的正是我们刚才输入的Hello World。



# 那么请问,这种方式和拷贝有啥区别,有啥用啊??????????????
# 请你想想,如果我们在生产环境里,使用拷贝的方式来更新页面的数据的话,那么就极大的增加了数据的风险性,而且非常不方便,这种拷贝# 的方式,也仅仅在我们测试环境,灰度环境里用用即可。
# 而这种数据卷的挂载,说白了就是数据卷的映射,我们可以在不进入容器内部的情况下,只修改外部,也就是/opt/webserver的内容,
# 即可实现生成环境中页面数据的更新。相当于这个目录是和nginx映射的目录是共享的。这个多方便,极大的保证了数据的安全性。
7.2 提前创建数据卷
# 在创建容器之前先创建数据卷,然后再挂载上去
$ docker volume create --name TestVolume --opt type=tmpfs --opt device=tmpfs --opt o=size=100m
# 解释一下,创建一个数据卷,名为TestVolume ,共有三个选项,一个是类型,一个是设备,一个大小100M
$ docker volume ls # 查看数据卷
$ docker volume inspect TestVolume # 查看数据卷详细信息
# 可以看到Mountpoint 挂载点
------------------------------------------------------------------------------------------
[
   {
       "CreatedAt": "2024-02-29T20:20:18+08:00",
       "Driver": "local",
       "Labels": null,
       "Mountpoint": "/var/lib/docker/volumes/TestVolume/_data",
       "Name": "TestVolume",
       "Options": {
           "device": "tmpfs",
           "o": "size=100m",
           "type": "tmpfs"
       },
       "Scope": "local"
   }
]
----------------------------------------------------------------------------------------------
# 这次我们再创建容器的时候,可以直接写TestVolume的数据卷的名称,而不是写宿主机的目录。
# woc,其实就相当于搁着套娃呢,简单理解,就是宿主机的某个目录套了一层TestVolume的皮,然后用这层皮去和容器里的对接
# 有好处,当以后你不想要这个容器的时候,但是还想保存共享的数据,那么此时删掉容器,并不会删除掉共享数据卷的内容,可以继续使用
$ docker run -itd --name ServerNginx02 -p 8082:80 -v TestVolume:/usr/share/nginx/html nginx:1.21

# 然后自己做个测试,像上面一样,往这个目录 /var/lib/docker/volumes/TestVolume/_data/index.html 写一段话,然后看看nginx # 的首页改变了没

8. Dockerfile自动构建docker镜像

8.1 Dockerfile指令集

dockerfile就相当于Linux里shell脚本一样,用来自定义批量执行一些命令啊

$ FROM  # FROM 指定基础的镜像,就是以谁为基础来构建的,例如以nginx为基础构建

$ MAINTAINER # 指定维护者信息(可以不写)频率低~~

$ RUN # 运行一些指令,例如shell指令,例如 ps -ef

$ ADD / COPY # 都是将宿主机中的文件,拷贝到容器里,ADD可以自动解压压缩包,COPY却不会

$ WORKDIR # 工作目录,类似cd 

$ VOLUME # 设置相应的卷,使用频率低。

$ EXPOSE # 指定对外的端口

$ CMD  # 指定容器启动后要干的事,它可以有多个,但只有最后一条生效。
8.2 单阶段构建镜像
# 我们利用dockerfile来完成这样一个任务,由于现在的环境下,比较倡导前后端分离的方案
# 那我们就把单阶段分为两部分来讲,先来构建前端的这部分,再去构建后端的这一部分
# 前端采用Vue,后端采用Python
#------------------------------------------------------------------------------------------------------------
# 我们先不用dockerfile,来看是如何构造的,之后再看dockerfile构造,不想动手的同学,直接看看这部分就行。
# 构建前端...............................................
# Vue的运行环境就是Javascript,我们先去node.js来解析Vue
$ docker pull node:16.15.0
# 提示:如果出现这种错误:failed to register layer: write /usr/lib/x86_64-linux-gnu/libicudata.a: no space left on device

# 说明容器存储空间满了,使用 docker system prune -a 命令释放空间,永久删除的,请谨慎使用
#------------------------------------拓展-----------------------------------------------------
# docker container prune  # 永久删除已停止的容器
# docker system prune # 永久清理未使用的镜像和容器
# $ docker system prune -a --volumes # 永久清除卷和镜像、容器。
# 查看docker的存储空间信息结合了awk,
# $ docker system df | awk '/^TOTAL/ { total=$4 } /^Images/ { images=$4 } /^Containers/ { containers=$4 } /^Local Volumes/ { volumes=$4 } END { printf("总空间: %s\n镜像: %s\n容器: %s\n数据卷: %s\n", total, images, containers, volumes) }'
#------------------------------------拓展-----------------------------------------------------

# 然后创建这个容器
$ docker run -itd --name webserver-Vue -p 8080:8080 node:16.15.0

# 接下来我们需要做一件事情(重要),我们的容器默认的网络模式是桥接,它在查看ifconfig里我们看到自动生成一个dokcer0的网桥,
# 自动给创建的容器分配IP地址,但我试过了,如果宿主机不开启路由转发功能,那么进入容器后,容器并不能访问外部网络。
$ vim /etc/sysctl.conf  # 修改或加入 net.ipv4.ip_forward=1 这一行即可 ,这样就开启了路由转发功能

# 【注意】: 也可以自定义docker的网络模式

$ docker exec -it webserver-Vue bash # 进入容器,切记千万不能加d,不然就跑后台运行去了
$ git clone https://gitee.com/mirschao/webserver-vue.git  # 克隆这个,用于演示
$ cd webserver-vue/
$ npm install # 安装依赖
$ npm run serve # 启动项目
# 然后会出现一个http地址,去浏览器访问即可,千万记得哈,那个localhost要改的,改成你的宿主机的Ip地址才可以,切记!
#---------至此不使用dockerfile构建的部分结束-------------------------------------------------------------------------



#使用dockerfile 来操作
#我们可以一个命令就完成上述安装到启动的一系列步骤,一次操作,到处运行,就类似脚本
为了编译快一点,我先把之前的容器删掉
$ docker rm -f `docker ps -a -q`
$ docker ps -a # 没容器了

# 创建一个新目录存放这个容器
$ mkdir -p /opt/docker-images/webserver-vue
$ cd /opt/docker-images/webserver-vue
$ vim Dockerfile # 不论在那个容器下创建的名字都叫Dockerfile,一个字母都不能差,大小写也不能差。
---------------------Dockerfile内容------------------------------------------------------------------
FROM node:16.15.0
RUN git clone
WORKDIR webserver-vue
RUN npm install
EXPOSE 8080
CMD ["npm","run","serve"]
----------------------------------------------------------------------------------------

# 触发Dockerfile构建(前提:你必须在你创建的这个webserver-vue目录下)
$ docker build -t webserver-vue:v1.0 .  # 开始构建, . 是在当前目录下找Dockerfile来构建
$ docker run -itd --name webserver-vue-project -p 8090:8080 webserver-vue:v1.0  # 创建容器,运行镜像
# 然后去访问 宿主机IP:8090

# 构建后端...............................................
# -----------------我还是先不利用dockerfile,走一遍普通流程----------------------------
#用python:alpine3.15,体积小
$ docker pull python:alpine3.15
$ docker run -itd --name webserver-python -p 8000:8000 python:alpine3.15
$ docker exec -it webserver-python sh # bash不行,得用sh
# 进去后发现,git clone 不了东西,所以我们需要通过docker cp 来拷贝进去
$ exit # 退出容器
$ cd /opt
$ git clone https://gitee.com/mirschao/webserver-backend.git
$ docker cp webserver-backend webserver-python:/ # 拷贝到容器的根目录下
$ docker exec -it webserver-python sh # 进去后 ls 就可以看到拷贝的文件
$ ls -l
# 安装依赖包
$ pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple -r requirements.txt  # -i指定安装源,-r 指定根据哪个文件安装依赖
# 运行项目
$ python manage.py runserver 0.0.0.0:8000 
# 然后访问 宿主机IP:8000 网页


--------------------------------------------------------------------------------------------------------

# 使用dockerfile来构建,跟上面差不多,但是我们刚才拉取的那个里面就有Dockerfile文件,这是为啥,这是因为
# 在实际生产环境中,我们一般都是把Dockerfile构建文件直接放在项目里的,这样就可以复用。
# 所以我们直接使用项目的Dockerfile构建
$ cd /opt/webserver-backend
$ cat Dockerfile # 查看dockerfile文件,内容如下
--------------------------------------------------
FROM python:alpine3.15
WORKDIR webserverbackend         # 这是工作目录
COPY . .						# 这是复制当前目录下的所有文件到工作目录
RUN pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple -r requirements.txt
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
--------------------------------------------------
$ docker build -t webserver-python:v1.0 . # 构建镜像
$ docker run -itd --name test-webserver -p 8081:8000 webserver-python:v1.0 # 创建容器
# 然后访问网页即可
8.3 多阶段构建镜像
# 工作中我们根据语言的特性,例如vue,他需要打包构建,构建出来的就是一个dist目录,所以我们可以采用这种多阶段构建的方式,Java也可以采用,但是Python是一门解释性语言,只需要安装依赖即可运行,不需要多阶段构建。
# 也就是说,例如Vue,如果利用他的基地镜像node.js的话,那构建出来的镜像会非常大,上线也就很缓慢。所以我们一般是采用多阶段构建,先将vue利用node.js打包成dist目录,再用nginx反向代理dist目录,提供给外部访问,nginx的作为基础构建镜像是非常小的。

# 下载Nginx镜像(选择合适的版本)
$ docker pull nginx:1.21

# 先把写好的项目克隆到本地(这里作为演示,就拉取了gitee上的代码)
$ git clone https://gitee.com/mirschao/webserver-vue.git
$ cd webserver-vue
$ vim Dockerfile # 将下面的Dockerfile配置复制进去
-----------------------------------------------------
FROM node:16.15.0   # 先基于node 的环境来打包构建vue应用
COPY ./ /app
WORKDIR /app
RUN npm install && npm run build   # npm run build会产生一个dist目录,这个目录就是我们需要的

FROM nginx:1.21  # 然后在基于nginx,将dist目录放入nginx目录下,来构建自己的镜像。这样构建出来的就很小。
RUN mkdir /app
COPY --from=0 /app/dist /app   # --from=0 意思是基于上面(node)构建的来进行拷贝,计数从0开始
COPY nginx.conf /etc/nginx/nginx.conf # 将当前目录下的nginx.conf配置文件进行复制
-------------------------------------------------

$ vim nginx.conf    # 再当前目录下创建一个nginx.conf 
-------------------- nginx.conf --------------------------------------------------------------
user	nginx;
worker_processes 1;
error_log	/var/log/nginx/error.log warn;
pid		/var/run/nginx.pid;

events {
	worker_connections 1024;
}
http {
	include		  /etc/nginx/mime.types;
	default_type   application/octet-stream;
	log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
				     '$status $body_bytes_sent "$http_referer" '
				     '"$http_user_agent" "$http_x_forwarded_for" ';
access_1og		/var/log/nginx/access.log  main;
sendfile 		on;
keepalive_timeout 65;
server {
	listen 	80;
	server_name	 localhost;
	location / {
		root 	/app;
         index index.html;
         try_files $uri $uri/ /index.html;
	}
	error_page   500 502 503 504 /50x.html;
	location = /50x.html {
		root	/usr/share/nginx/html;
	}
  }
}
----------------------------------------------------------------------------------

# 构建镜像
$ docker build -t vue-project:v1.0 .
$ docker images # 查看构建好的镜像
$ docker run -itd --name test-vue-project -p 80:80 vue-project:v1.0
# 然后 宿主机IP访问,   80不用写,浏览器默认就是80
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值