docker 第二次学习笔记

一、dockers简介

docker官网:https://www.docker.com

1.1 docker定义

docker是一种容器化技术,用来更好的构建和发布应用。

二、docker安装

2.1 方法1 centos7.x系统的安装

官网安装步骤:https://docs.docker.com/engine/install/centos/

2.2 方法2 bash安装(适用于所有平台Linux)

(1) 下载并执行安装脚本

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

(2) 启动docker

sudo systemctl enable docker #开机自启动
sudo systemctl start docker

步骤(3),(4)可不执行。

(3) 创建docker用户组

sudo groupadd docker

(4) 将当前用户加入docker组

sudo usermod -aG docker $USER

(5) 查看docker版本

docker version
Client: Docker Engine - Community
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.16.12
 Git commit:        e91ed57
 Built:             Mon Dec 13 11:45:41 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.12
  Git commit:       459d0df
  Built:            Mon Dec 13 11:44:05 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.12
  GitCommit:        7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

三、docker核心概念

3.1 镜像 image

定义:一个镜像就代表一个软件
特点:镜像是只读的,不能进行写操作

3.2 容器 container

定义:一个镜像运行一次就会生成一个容器,容器就是一个运行的软件服务。
特点:可读可写

3.3 远程仓库 respostory

定义:仓库存储所有软件的镜像。

3.4 本地仓库

定义:存储使用docker过程中的镜像

四、docker架构

在这里插入图片描述

五、镜像的基本操作

在这里插入图片描述

5.1 docker辅助命令

(1) 查看docker版本信息

docker version

(2) 查看docker引擎详细信息

docker info

(3) 查看docker帮助信息

docker --help

5.2 image相关命令

(1) 查看所有镜像

docker images

(2) 下载镜像

docker pull redis

(3) 搜索镜像

只能看是否有redis镜像,不能列出版本

docker search redis

(4) 删除镜像

docker image rm 镜像名
docker image rm 镜像ID

强制删除镜像

docker image rm -f 镜像

(5) 只查看与tomcat相关镜像

docker images tomcat

(6) 只查看镜像ID

docker images -q
# docker images -q
2b213ae9dde9
f513b3f80437
6974a500c5d2
ed4f92437413
048c3fba5aec
851d23a02794
302d958928e7
13b66b487594
1b3de68a7ff8

(7) 只删除tomcat相关镜像

docker image rm -f $(docker images tomcat -q)

删除所有镜像

docker image rm -f $(docker images -q)

六、容器的基本操作

6.1 查看容器中正在运行的容器

docker ps

查看所有容器,包括停止的容器。

docker ps -a

6.2 运行容器

docker run 镜像名

6.3 运行容器,添加宿主机与容器的映射

-p 参数可以写多个

docker run -p 8080:8080 tomcat

6.4 后台启动容器

docker run -p 8080:8080 -d tomcat

返回容器ID

6.5 启动容器时,指定容器名字

docker run -p 8082:8080 -d --name tomacat01 tomcat:8.0

6.6 停止 重启 暂停 恢复容器

docker stop 容器ID
docker start 容器ID
docker restart 容器ID
docker pause 容器ID #暂停容器
docker unpause 容器ID #恢复容器

容器暂停时,会有pause的标识

# docker ps
CONTAINER ID   IMAGE        COMMAND     CREATED        STATUS       PORTS                                               NAMES
d48d3346736b   tomcat:jdk   "/run.sh"   5 hours ago    Up 5 hours   22/tcp, 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp   serene_archimedes
e480832e69e6   tomcat:jdk   "/run.sh"   20 hours ago   Up 4 hours   22/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   condescending_beaver

6.7 杀死容器

docker kill 容器ID 

6.8 删除容器

docker rm 容器ID    #只能删除已经停止的容器,不能删除正在运行的容器
docker rm -f 容器ID #强制删除容器

强制删除所有容器

docker rm -f $(docker ps -aq)

6.9 查看容器日志

docker logs 容器ID
docker logs --tail 10 容器ID #显示后10行日志

高频使用

docker logs -f 容器ID #显示实时的日志

6.10 进入容器内部

docker exec -it 容器ID bash

6.11 容器与宿主机之间文件拷贝

从容器拷贝文件到宿主机

docker cp 容器ID:容器中文件或目录 宿主机目录
docker cp tomcat01:/tomcat/RUUING.txt /root

从宿主机拷贝文件到容器内

docker cp 宿主机目录 容器ID:容器中文件或目录
docker cp /root/readme.txt tomcat01:/tomcat/

6.12 查看容器内部运行进程

docker top 容器ID

6.13 查看容器内细节指令

docker inspect 容器ID

6.14 使用绝对路径设置数据卷

作用:用来实现宿主机,与容器中数据同步
注意:数据卷使用必须在容器首次启动时设置
使用:

docker run -v 宿主机路径:容器路径:ro
docker run -d -p 8080:8080 --name tomcat02 -v /apps/:/tomcat/apps/:ro tomcat:jdk

ro:read only 如果在设置数据卷时指定ro,代表容器内路径是只读的
注意:该方式会将容器路径的原始内容全部清空,始终以宿主机路径为主<\font>

6.15 使用别名方式设置数据卷

docker run -d -p 8080:8080 --name tomcat03 -v aaaa:/tomcat/apps/:ro tomcat:jdk

6.16 将修改后容器打包成新的镜像

docker commit -m "描述信息" -a "作者信息" 容器ID 新镜像名:版本
docker commit -m "deploy project" -a "zhou" dfaae0abef47 tomcat-test:zhou

6.17 镜像的备份和恢复

(1) 打包镜像

不指明路径,就保存在当前路径

docker save 镜像名:tag -o 名称.tar

(2) 恢复镜像

docker load -i 镜像.tar

七、 运行mysql

dockerhub官网:https://hub.docker.com

7.1 下载mysql

docker pull mysql:5.6

7.2 运行mysql

  • 开启端口映射 -p
  • 指定root用户密码 -e
  • 后台运行 -d
  • 指定容器名称 --name
  • 总是运行 --restart=always。docker引擎重启时,mysql容器会自动重启
  • 数据卷挂载 -v
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root --name mysql01 --restart=always -v /root/data:/var/lib/mysql mysql:5.6

7.3 Docker运行Mysql容器数据备份

问题:数据卷备份mysql容器数据时,备份的是数据库底层的文件系统。不利于数据的迁移

7.4 在mysql容器中导出sql文件

(1)备份全部数据

docker exec mysql容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/databases.sql

(2)备份指定数据库

docker exec mysql容器id sh -c 'exec mysqldump --databases 库名 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/databases.sql

(3)备份表结构,不要数据

docker exec mysql容器id sh -c 'exec mysqldump --no-data --databases 库名 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/databases.sql

八、 docker运行redis

8.1 下载redis镜像

 docker pull redis:5.0.12

8.2 运行redis

docker run -d -p 6379:6379 redis:5.0.12

8.3 redis支持内存数据持久化

  • rdb持久化:redis服务器将某一时刻数据以快照文件形式写入到磁盘
  • aof持久化:redis服务器将所有redis客户端写操作以命令方式记录到日志文件中。aof更加安全

8.4 docker启动redis,持久化,数据卷,

docker run -d -p 6379:6379 --name redis01 --restart=always -v /root/redisdata:/data/ redis:5.0.12 redis-server --appendonly yes
  • 开启持久化后,持久化文件生成在容器中/data/目录

8.5 获取配置文件启动redis

(1)上传配置文件到宿主机目录

/root/redisconf/redis.conf

(2)数据卷挂载启动

docker run -d -p 6379:6379 --name redis02 --restart=always -v /data/redisocnf:/data/ redis:5.0.12 redis-server /data/redis.conf

九、运行nginx

9.1 下载nginx镜像

docker pull nginx:1.19.10

9.2 启动nginx,映射端口

docker run -d -p 80:80 --restart=always --name nginx01 nginx:1.19.10

9.3 加载指定配置文件,启动nginx

docker run -d -p 80:80 --restart=always --name nginx02 -v /root/nginxconfig/nginx.conf:/etc/nginx/nginx.conf nginx:1.19.10

9.4 nginx作为服务器,将nginx家目录挂载到宿主机

docker run -d -p 80:80 --restart=always --name nginx02 -v /root/html:/usr/share/nginx/html nginx:1.19.10

十、docker运行ElasticSearch

10.1 下载ElasticSearch

docker pull elasticsearch:6.8.10

10.2 运行es

docker run -d -p 9200:9200 -p 9300:9300 --restart=always --name es -v esdata:/usr/share/elasticsearch/data elasticsearch:6.8.10

注意:es默认使用集群方式启动,使用集群启动时会出现如下错误:
max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

解决方案如下

  • vim /etc/sysctl.conf 加入如下配置
vm.max_map_count=262144
  • sysctl -p 使配置生效

10.3 指定配置文件运行es

docker run -d -p 9200:9200 -p 9300:9300 --restart=always --name es -v esdata:/usr/share/elasticsearch/data -v /root/esconfig/elasticsearch.yml /usr/share/elasticsearch/config/elasticsearch.yml elasticsearch:6.8.10

十一、容器网络

容器之间通过网络进行相互通信

10.1 官方说明

  • docker启动后,会自动创建一个docker0虚拟网桥,可以理解为一个软件交换机

在这里插入图片描述

10.2 网络总结

  • docker在创建容器时将所有容器都连接到docker0网桥上,容器之间通过容器内ip可以实现通信
  • docker在创建容器时将所有容器都连接到docker0网桥上,容器之间通过容器名可以实现通信。注意:使用容器名通信不能使用docker0网桥,必须自定义网桥。

10.3 自定义网桥,实现网桥中一组容器的通信

10.3.1 docker中桥的类型

docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f4592993ec2f   bridge    bridge    local
7abdac590e2b   host      host      local
e7525fc2fc6a   mynet     bridge    local
f0c3788f5cda   none      null      local
7cd2081215f8   redis     bridge    local

10.3.2 创建自定义网桥

docker network create -d bridge 网络名称
docker network create clazz-web

10.3.3 查看创建的网桥

docker network ls

10.3.4 查看某个网络的细节

docker network inspect 网络名称

10.3.5 删除某个网络

docker network rm 网络名称

删除未用到的网络

docker network prune

10.3.6 运行多个容器在指定的网络中

启动容器时,明确指定使用哪个网络

docker run -d --network 网络名称 ...
docker run -d -p 8080:8080 --name tomcat01 --network clazz-web tomcat:jdk

启动容器后,再加入网络

docker network connect 网络名 容器id

示例:
默认bridge网络启动tomcat03容器

docker run -d -p 8082:8080 --name tomcat03 tomcat:jdk

将tomcat03容器加入到clazz-web网络

docker network connect clazz-web tomcat03

查看clazz-web细节

docker network inspect clazz-web

注意:自定网络既可以使用Ip地址通信,也可以使用容器名称通信

十一、高级数据卷

11.1 定义

用来实现宿主机和容器之间文件目录映射、同步

11.2 数据卷使用,-v 宿主机路径:容器内路径

注意:必须在容器首次启动时指定

11.2.1 使用绝对路径映射数据卷

docker run -v /root/datas:/usr/local/tomcat/webapps ... tomcat:8.0

11.2.2 使用绝别名映射数据卷

docker run -v bb:/usr/local/tomcat/webapps ... tomcat:8.0
注意:
  • bb代表数据卷的别名
  • bb数据卷可以存在,也可以不存在。不存在时,docker 首次用到会创建
  • 第一次使用别名时,容器中的原始数据将保存下来
  • 使用绝对路径是,不会保留容器中的原始数据

11.3 别名是什么

别名代表docker自身维护的数据卷

11.3.1 查看docker维护的所有数据卷

docker volume ls
DRIVER    VOLUME NAME
local     37e9c89ccd44ee1bef763f50a73eeb9eb93190acdf8237b76d10ba5c622b569c
local     069dfdd4e553e7d23e18010b3584adb8775d9c52df8137447d3850a6d1651877
local     71e11f380c16c2f91b81f3a71e92f276ae0c5f7b80e870c1d0f1bb3a67781920
local     258b1f13fea3f4cca5e9575c06279e0ada720c6c7b01b5441fa262ff12d684a7
local     270e7ef1b5a966052c05114499646e8ba826acb8f12126c733fd09aa48e6ff33
local     560e5b310d4f24a4b016cde8f75df1f064dff832e85650fdf7f80ed77be7f3e2
local     7295f5e370068082cef6804958d368094027a8926e82dde20af446aaf78a1e90
local     8628ef40223a441805aaa74af7f437e153fc7694bc6e182d33f33d144fc0fdaf
local     14148f7cc07992ac5f99440d3cdc8f70c41c914e925047bc6a641cd7cd3f88f6

11.3.2 查看某数据卷的详细信息

docker volume inspect juming
[
    {
        "CreatedAt": "2022-11-10T15:45:53+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/ems/_data",
        "Name": "ems",
        "Options": {},
        "Scope": "local"
    }
]

11.3.3 删除某数据卷

docker volume rm 数据卷
docker volume rm juming

11.3.4 创建数据卷别名

docker volume create 数据卷别名
docker volume create ems

十二、dockerfile

12.1 dockerfile是什么

Dockerfile是镜像的描述文件

12.2 dockerfile语法

12.2.1 FROM:当前镜像基于哪个镜像

使用dockerfile构建镜像

docker build -t mycentos:01 .

12.2.2 RUN:构建镜像时需要运行的指令

12.2.3 EXPOSE:当前容器对外暴露的端口号

12.2.4 WORKDIR:创建容器后,指定登入容器的工作目录

12.2.5 ADD:将宿主机中文件拷贝到容器,会自动解压tar包

12.2.6 COPY:将宿主机中文件拷贝到容器

12.2.7 ENV:构建镜像过程中设置环境变量

12.2.8 VOLUME:容器数据卷,用于数据保存和持久化工作,dockerfile中仅作声明

启动容器时,挂载数据卷

docker run -v datas:/apps/data mycentos:03

12.2.9 CMD命令

  • 容器运行时默认启动的脚本
  • dockerfile中可以有多个CMD指令,但只有最后一个生效。

使用语法

(1)直接命令方式

java -jar ems.jar

(2)json数组方式

["java","-jar","ems.jar"]

12.2.10 CMD与Entrypoint命令区别

CMD命令构建的容器:运行容器时再次运行命令,会直接覆盖掉dockerfile文件中的CMD指令

docker run 镜像:版本 命令

一个示例:

docker run centos:08 ls /

Entrypoint命令构建的容器,进行命令覆盖

docker run --entrypoint=覆盖指令 镜像:版本 传递的参数

一个示例:

docker run --entrypoint=ls centos:08  /

总结

  • entrypoint用来书写容器固定的指令
  • cmd用来给entrypoint传参
  • 必须使用json数组语法
    一个示例:
FROM centos:latest
EXPOSE 8081
ENV BASE_PATH=/apps/data
WORKDIR $BASE_PATH
ADD aa.txt .
#CMD ["ls","/apps/data"]
#ENTRYPOINT ["ls","/apps/data"]
ENTRYPOINT ["ls"]
CMD ["/apps/data"]

一个jar包示例

dockerfile写法,构建ems:1.0镜像

ENTRYPOINT ["java","-jar"]
CMD ["ems.jar"]

命令行写法,运行挂载的jar包

docker run -v /root/apps:/apps ems:1.0 bb.jar

十三、docker-compose简介

13.1、现有docker进行项目部署存在的问题

  1. 一个完整的项目会使用到N个容器,N多个容器之间会形成依赖。所以容器编排显得很重要。
  2. 一个项目用到一组容器。日后会将该项目部署到多台服务器。需要区分清楚该项目用到哪些容器。

十四、docker compose 编排项目

14.1 什么是docker compose

Docker compose 负责实现对docker容器的快速编排。站在项目角度将一组相关容器整合在一起,将这组容器安照指定顺序启动。

  • compose的定位是对于多个容器的编排
  • 一个docker-compose中定义多个容器(服务)

14.2 compose中两个重要概念

  • project:由一组关联容器组成的业务单元,在docker-compose.yml文件中定义。
  • service:一个项目中的某一个容器,称之为服务

十五、docker-compose 案例一

15.1 查看docker-compose版本

docker-compose -v

15.2 书写docker-compose.yml文件

#代表docker-compose项目的版本号
version: "3.8"
services:
  tomcat:
   image: tomcat:8.0
   ports:             #宿主机与容器的端口映射
    - 8080:8080

15.3 启动

docker-compose up

15.4 docker-compose.yml文件写2个tomcat服务

version: "3.8"
services:
  tomcat:
   image: tomcat:8.0
   ports:
    - 8080:8080

  tomcat01:
   image: tomcat:8.0
   ports:
    - 8081:8080

15.5 停止

docker-compose down可以清除docker-compose up的缓存

docker-compose down

15.5 docker-compose.yml的配置示例

version: "3.8"
services:
  tomcat:
   container_name: tomcat01 #指定容器名字,推荐使用默认容器名
   image: tomcat:8.0
   ports:
    - 8080:8080

  tomcat01:
   image: tomcat:8.0
   ports:
    - 8081:8080

  redis:
   image: redis:5.0.12
   ports:
    - 6379:6379

  mysql:
   image: mysql:5.6
   ports:
    - 3306:3306
   environment: #指定环境变量,类似于docker run -e MYSQL_ROOT_PASSWORD=root
    - "MYSQL_ROOT_PASSWORD=root"
   volumes:  #docker-compose使用绝对路径必须先创建该路径
    # - /root/mysqldata1:/var/lib/mysql
    - mysqlData:/var/lib/mysql   #别名方式创建数据卷,也必须先声明

volumes:
 mysqlData: #声明别名数据卷

十六、docker-compose 模板命令

16.1 build指令

  • build指令与image不能同时使用
  • 通过docker-compose在启动容器之前,根据dockerfile构建镜像,根据构建的镜像启动容器

16.2 command指令

  • 覆盖容器启动后默认执行的指令

16.3 container_name指令

  • 指定容器名字,一般不建议指定容器名字

16.4 depends_on指令

  • 指定容器的依赖关系

16.5 environment指令

  • 容器启动时指定环境变量,相当于docker run -e指令

16.6 env_file指令

  • 容器启动时,指定环境变量的文件

16.7 expose指令

  • 构建镜像时,暴露容器的端口号

16.8 image指令

  • 指定容器启动时使用的镜像

16.9 networks指令

  • 指定容器启动时使用的网桥,相当于docker run --network

16.10 ports指令

  • 用来指定宿主机和容器的端口映射,相当于docker run -p

16.11 volume指令

  • 用来指定宿主机和容器的数据映射,相当于docker run -v

16.12 restart指令

  • 指定容器总是运行,相当于docker run --restart=always

16.13 一个docker-compose.yml示例

version: "3.8"

service:

  tomcat:
    image: tomcat:8.0
    ports:
      - "8080:8080"
    networks:
      - dangdang

  apps:
    #build: ./  #指定dockerfile的上下文目录,一切都是默认值
    build:
      context: ./ #指定dockerfile的上下文目录
      dockerfile: Dockerfile #指定dockerfile的文件名
    ports:
      - "8081:8081"
    command: ["test.jar"] #覆盖容器启动后默认执行的指令
    depends_on:
      - tomcat #书写依赖的服务名
    networks:
      - dangdang

  mysql
    image: mysql:5.6
    ports:
      - "3306:3306"
    #environment:
      #- "MYSQL_ROOT_PASSWORD=root"
    env_file:
      - .env
    volumes:  #映射数据卷
      - mysqlData:/var/lib/mysql
    networks:  #指定网桥
      - dangdang
    restart: always #容器总是运行


networks:  #声明网桥。在启动的时候就会创建网桥
  dangdang:

volumes:  #声明别名数据卷
  mysqlData:

十七、docker-compose 命令

17.1 docker-compose up

启动整个项目的容器

docker-compose up

启动项目中的tomcat服务

docker-compose up tomcat

17.2 docker-compose down

  • 移除容器,网络,并不移除数据卷

停止整个项目

docker-compose down

停止项目中的tomcat服务

docker-compose down tomcat

17.3 docker-compose exec

  • 进入容器内部
docker-compose exec tomcat bash

17.4 docker-compose ps

  • 列出运行中容器

17.5 docker-compose restart

重启整个项目中的容器

docker-compose restart

重启项目中的tomcat容器,20秒后重启容器

docker-compose restart -t 20 tomcat

17.6 docker-compose rm

删除整个项目或者指定的服务

docker-compose rm 服务id
  • -f ,强制删除容器
  • -v,删除容器挂载的数据卷

17.7 docker-compose top

查看指定服务中的进程

docker-compose top tomcat

17.8 docker-compose pause

暂定某个指定的服务

docker-compose pause tomcat

暂定所有服务

docker-compose pause

恢复所有服务

docker-compose unpause

17.9 docker-compose logs

查看整个项目的日志

docker-compose logs

查看指定服务的日志

docker-compose logs tomcat

实时查看服务运行日志

docker-compose logs -f tomcat

十八、portainer可视化工具

18.1 启动portainer

docker pull portainer/portainer
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当谈到Docker学习笔记时,我可以为你提供一些基本的指导和主题,以帮助你开始学习Docker。以下是一些可能涵盖的主题: 1. Docker简介:了解Docker的基本概念、优势以及它如何与虚拟化技术不同。 2. Docker安装:学习如何在不同的操作系统上安装Docker,并熟悉Docker引擎的组成部分。 3. Docker镜像:了解Docker镜像的概念,以及如何通过构建、拉取和推送镜像来管理和共享容器环境。 4. Docker容器:学习如何创建、启动、停止和删除容器,并了解容器和主机之间的交互方式。 5. Docker网络:探索Docker网络模式,包括桥接网络、主机网络和覆盖网络,并理解容器之间以及容器与主机之间的通信方式。 6. Docker存储:了解Docker存储技术,包括数据卷和绑定挂载,并学习如何在容器中持久化数据。 7. Docker Compose:介绍Docker Compose工具,它可以用于定义和运行多个容器的应用程序。 8. Docker Swarm:探索Docker Swarm,它是Docker官方的容器编排和集群管理工具,于在多个主机上部署和管理容器应用。 9. Docker和持续集成/持续部署(CI/CD):了解如何将Docker与CI/CD工具(如Jenkins、GitLab CI等)集成,以简化应用程序的构建和部署过程。 这只是一些可能的主题,你可以根据自己的需求和兴趣来选择学习内容。希望这些指导可以帮助你开始学习Docker!如果你有任何特定的问题,我很乐意回答。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值