Summary of Docker Getting Started Notes

1. Docker overview

Why does docker appear

A product will have three environments: development, testing, and online, so it is very troublesome to configure different application environments and configurations, so there will be situations where this project can run on my computer but not on other computers, or the version The update caused the service to be unavailable, and ducker can solve this problem. Duker can release the project jar package with the java operating environment jdk, mysql, redis, es...) , simply put, the project can be released with the environment.

  • Tradition: develop the jar, and do the operation and maintenance!
  • Now: Development, packaging and deployment are online, and a set of processes is completed!
  • java – apk -- release (app store) ---- Zhang San uses apk -- install it and use it!
  • java .-- jar (environment)----package the project and bring the environment (mirror)---- (Docker warehouse: store)----download the image we released-just run it directly!

Docker proposes a solution to the above problems, which is a containerized technology !

2. What Docker can do

First, you need to make a comparison with the virtual machine.

virtual machine technology

Please add a picture descriptionDisadvantages of virtual machine technology:

  • Very resource intensive
  • Many redundant steps
  • Very slow to start!

container technology

Please add a picture descriptionCompare the difference between Docker and virtual machine technology:

  • A traditional virtual machine virtualizes a piece of hardware, runs a complete operating system, and then installs and runs software on this system
  • The application in the container runs directly on the content of the host machine. The container does not have its own kernel, nor does it virtualize our hardware, so it is portable
  • Each container is isolated from each other, and each container has its own file system, which does not affect each other.

3. Docker installation

The basic composition of Docker

Please add a picture description

  • Image ( image ):
    The docker image is like a template through which container services can be created, tomcat image ===>run ==> tomcat01 container (providing server), multiple containers can be created through this image (final service run or project run is in the container).
  • Container ( container ):
    Docker uses container technology to run one or a group of applications independently, created through mirroring. Start, stop, delete, basic commands! At present, this container can be understood as a simple linux system
  • Warehouse (repository):
    The warehouse is the place where the image is stored! The warehouse is divided into public warehouses and private warehouses!
    Docker Hub (default is foreign)
    Alibaba Cloud... all have container servers (configure mirror acceleration!)

install docker

First use Xshell to connect to your own remote server, and enter the following commands. (This is the installation of CentOS8)

1. 下载docker-ce的repo
curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
2. 安装依赖
yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm
3. 安装docker-ce
dnf -y  install docker-ce  docker-ce-cli --nobest
4.启动 docker
systemctl start docker
5.查看 docker 版本信息
docker -v
6.设置开机自动启动
systemctl enable --now docker


CentOS8 takes a long time to install Docker and needs to wait for a while!

4. Test the Docker command

Download the hello-world image

docker run hello-world

Please add a picture description

View the docker image on this machine

docker images

Please add a picture description

What does docker do after running?

Please add a picture description

Docker will first look for the image on the local machine, and then determine whether the machine has an image. If there is such an image, it will use this image to run. If not, it will go to docker-hub to download (if Alibaba Cloud’s image acceleration is configured, go back to Alibaba Cloud download), if it cannot be found on the docker-hub warehouse, it will return an error that the image cannot be found, and if it can be found, it will download the image to the local and run it.

5. Common commands of Docker

help command

docker version      		 #显示docker的版本信息
docker info         		 #显示docker的系统信息.,包括镜像和容器的数量
docker 命令 --help    		 #万能命令(查看docker的所有命令)

mirror command

  • docker images
    View all images on this machine
[root@VM-4-7-centos ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB
#解释
REPOSITORY      镜像的仓库源
TAG				镜像的标签
IMAGE ID		镜像的id
CREATED		    镜像的创建时间
SIZE  		    镜像的大小
#可选项
docker images -a       #列出所有镜像
docker images -q       #只显示镜像的id
  • docker search image name
    Search image, for example: docker search mysql (search mysql image) or
    filter images by the number of favorites: docker search mysql --filter=STARS=3000 (search mysql image and the number of favorites is greater than 3000)

  • docker pull image name: xx.xx
    download image, xx.xx is the version information, if not written, it will be the latest version by default (you can go to the official see the specific version)
    Example: docker pull mysql:5.7 -----> (download 5.7 version of mysql)

  • docker rmi -f mirror id
    to forcefully delete the mirror (-f means mandatory), for example: docker rmi -f mirror id----->(delete by mirror id)

  • docker rmi -f $(docker images -aq)
    delete all images

container command

You can create a container only with a mirror, so you can download a centos mirror from linux to test and learn.

  • docker pull centos
    pulls the image of centos. (The container created by mirroring is actually a small server, so it also has its own port number inside)
  • docker run optional parameter image
    creates a new container and starts it
#参数说明
--name="Name"  		#给容器命名(比如java每个对象都有自己的名称)
-d                	#以后台方式运行(不挂断)
-it               	#使用交互方式运行,进入容器查看内容
-p                  #指定容器的端口(这个是小写的p)   -p 8080:8080 (-p 主机端口:容器端口)
-P					#随机映射端口(不用写具体端口映射)
#测试,启动并进入容器
[root@VM-4-7-centos ~]# docker run -it centos /bin/bash     
[root@09408741e760 /]# ls            #查看容器内的cenntos,基础版本很多命令都是不完善的
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@09408741e760 /]# exit          #停止运行并退出容器
exit
[root@VM-4-7-centos ~]# 
  • docker ps
    lists currently running containers
  • docker ps -a
    lists currently running containers + historically run containers
  • docker ps -aq
    lists the ids of currently running containers + historically run containers
  • docker ps -a -n=1
    displays the recently created container, n=1 means only one display, variable parameters
  • Ctrl+P+Q
    exits the container, but does not stop the container from running
  • docker rm container id
    deletes the container according to the container id, and the running container cannot be deleted unless -f is added after rm to force the deletion
  • docker rm -f $(docker ps -aq)
    recursively delete all containers by passing parameters

Actions to start and stop containers

docker start 容器id      #启动容器
docker restart 容器id    #重启容器
docker stop 容器id       #停止当前正在运行的容器
docker kill 容器id       #强制停止当前容器

Other commonly used commands

  • docker run -d centos
    background start container
[root@VM-4-7-centos ~]# docker run -d centos
2d6d2d2b4a43853268d586aa26ba4961db73f2d6bf78d012a95ecb64b7b1375f
[root@VM-4-7-centos ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Here you will find a problem that the centos container is obviously started but it stops by itself (there is no running centos). This is because the docker container runs in the background, so there must be a foreground process. If docker finds that there is no application, it will Automatic stop.

  • docker log -tf tail [n] container id
    to view the log, [n] indicates how many to display
  • docker top container id
    View the process information inside the container, if you want to kill the process in the container, you can use this command to view the process
  • docker inspect container id
    to view container metadata (all data information)
  • docker top container id

more commonly used

  • docker exec -it container id /bin/bash
    to enter the currently running container (method 1) commonly used
  • docker attach container id
    into the currently running container (method 2)

The difference between these two methods:

docker exec		#进入容器后开启一个新的终端,可以在里面操作(常用)
docker attach	#进入容器正在执行的终端,不会启动新的进程!

copy

  • docker cp container id: the host path of the path destination in
    the container Copy from the container to the host
[root@VM-4-7-centos home]# docker exec -it cfca0b940c56 /bin/bash     			#进入容器目录
[root@cfca0b940c56 /]# cd /home													#进入容器home目录
[root@cfca0b940c56 home]# ls													#home目录下没有文件
[root@cfca0b940c56 home]# touch test.java      									#创建文件夹
[root@cfca0b940c56 home]# ls
test.java																		#有文件了
[root@cfca0b940c56 home]# exit
exit																			#退出并停止运行(但是数据是还在的)
[root@VM-4-7-centos home]# docker ps											#查看正在运行的容器
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
cfca0b940c56   centos    "/bin/bash"   53 minutes ago   Up 53 minutes             stoic_hawking
[root@VM-4-7-centos home]# docker cp cfca0b940c56:/home/test.java /home   	    #拷贝文件
[root@VM-4-7-centos home]# ls												    #主机查看文件
test.java

6. Deploy some application containers

Deploy Nginx

  • docker run -d --name nginx01 -p 9000:80 nginx
    -d: background running
    –name: name the container
    -p: host port: container internal port

It should be noted here that the server of this machine must open the port 9000, and the inside of the container is actually a small Linux system with port 80 by default, so -p 9000:80 means to connect port 80 of the container with the local Binding to port 9000 of the machine, we can access port 80 of the container by directly accessing port 9000 of the machine.

[root@VM-4-7-centos ~]# docker pull nginx          						#下载nginx镜像
[root@VM-4-7-centos ~]# docker images									#查看下载的镜像
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    55f4b40fe486   27 hours ago   142MB
[root@VM-4-7-centos ~]# docker run -d --name nginx01 -p 9000:80 nginx   #启动容器 
4762c5c6c302223ad678a472c313c5e03a153990273f6697f1b9dea3139cbad5		#出现这个表示运行成功
[root@VM-4-7-centos ~]# docker ps										#查看正在运行的容器
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
4762c5c6c302   nginx     "/docker-entrypoint.…"   6 seconds ago   Up 4 seconds   0.0.0.0:9000->80/tcp, :::9000->80/tcp   nginx01
[root@VM-4-7-centos ~]# curl localhost:9000								#访问本机9000的端口
[root@VM-4-7-centos ~]# docker exec -it nginx01 /bin/bash				#进入容器
root@4762c5c6c302:/# ls													#查看容器里的文件

At this time, you can also access this port through the public network ip.

Please add a picture description

Deploy Tomcat

  • docker run -it -p 9002:8080 tomcat
    downloads the tomcat image and starts it in interactive mode. (9002 is the local port)

Then restart a terminal

[root@VM-4-7-centos ~]# docker ps      								     #查看正在运行的容器
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                       NAMES
8fb51866aae0   tomcat    "catalina.sh run"        19 seconds ago   Up 18 seconds   0.0.0.0:9002->8080/tcp, :::9002->8080/tcp   gifted_agnesi
[root@VM-4-7-centos ~]# docker exec -it 8fb51866aae0 /bin/bash     		 #进入容器
root@8fb51866aae0:/usr/local/tomcat# cp -r webapps.dist/* webapps     #将webapps.dist下的所有文件拷贝到webapps下
#这是因为官方的镜像webapps下是没有东西的所以是打不开tomcat的首页的,所以我们需要将首页文件信息拷贝进去。

Access this port through the public network ip.

Please add a picture description

7. Commit image

You can make your own local container into a mirror, so that you can run the mirror version you want every time. The idea is similar to git.
Specific command:
docker commit -a="author name" -m="commit information" container id image name:formed version information
Example:

[root@VM-4-7-centos ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED             STATUS             PORTS                                       NAMES
8fb51866aae0   tomcat    "catalina.sh run"        About an hour ago   Up About an hour   0.0.0.0:9002->8080/tcp, :::9002->8080/tcp   gifted_agnesi
[root@VM-4-7-centos ~]# docker commit -a="cjy" -m="add webapps app" 8fb51866aae0 tomcat02:1.0
sha256:fb86e87fc9d06292819394594f375cdf801670e01406832ad9d47a9985f5caf0      #成功生成镜像
[root@VM-4-7-centos ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
tomcat02     1.0       fb86e87fc9d0   41 seconds ago   485MB             	   #多了的5M就是复制到webapps下的文件
tomcat       latest    4813a0e5f815   13 days ago      480MB

8. Container data volume

Every application must have data. If the data is stored in the container, then if the container is deleted, the data will be lost. Obviously this is unreasonable, so there is a container data volume , so that the container and the local There is a data sharing technology among them, which synchronizes the data generated in the docker container to the local! (The container directory is mounted to the local directory), which can also be understood as two-way binding , and data sharing between containers is also possible.

1. Use the data volume to mount (method 1)

1. Specify the local path to mount (essentially anonymous mount)
Example:

  • docker run -it -v /home/test:/home centos /bin/bash
    starts and mounts the files under the /home path in the container to the local /home/test path
    -v local path: container path

After mounting, you can use the command: docker inspect container id to check the specific situation. (don't look in the container, because there is no container in the container)

Please add a picture description

In this way, the files between the two paths will be synchronized, and another great advantage is that if we want to modify some files in the container, we only need to modify the container locally and it will be automatically synchronized ( Such as some configuration files in the container) .

2. Mount without specifying the
local path

Anonymous mount:
Example:
docker run -d -P --name nginx1 -v /ect/nginx nginx
docker run startup method port mapping --name container name -v path mirror name that the container needs to mount
-P random port
mapping- v path inside the container

[root@VM-4-7-centos ~]# docker run -d -P --name nginx1 -v /ect/nginx nginx			#启动并进行匿名挂载
29aaf183f267add3d789d7e9afc19453a05ae69a1529ce3e37515bcb8ed4990a
[root@VM-4-7-centos ~]# docker volume ls       										#查看所有数据卷的情况
DRIVER    VOLUME NAME
local     402a6f662feddc6be4442d4ea9dd2e75fdb5aad9dee37c2a7f4749b50776ca73     	    #后面这串就是具体的名称

Named mount:
Example:
docker run -d -P --name nginx2 -v my-nginx:/etc/nginx nginx
my-nginx is the mount name

[root@VM-4-7-centos ~]# docker run -d -P --name nginx2 -v my-nginx:/etc/nginx nginx
8a5dea0a9c65b20dc4352c7d71c753d2f5f7e0a9191ad50166cb687a36a13031
[root@VM-4-7-centos ~]# docker volume ls
DRIVER    VOLUME NAME
local     402a6f662feddc6be4442d4ea9dd2e75fdb5aad9dee37c2a7f4749b50776ca73
local     my-nginx              #可以看到挂载名的情况

It is convenient for us to find a volume through named mount, so in most cases, we still use named mount

expand

Configure permissions for the files in the mounted container
ro ---->readonly #Files in the container are read-only
rw ---->readwrite #Files in the container are readable and writable (default)

docker run -d -P --name nginx2 -v my-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx2 -v my-nginx:/etc/nginx:rw nginx

Once the container permissions are set, the container has restrictions on the content we mount!

2. Use the data volume to mount (method 2)

Build via Dockerfile

Dockerfile is a build file used to build a docker image. In fact, it is a command script!
Through this script, a mirror image can be generated. The mirror image is a layer-by-layer command, and each command is a layer! We can create Mount it when mirroring.
First experience of making a mirror image:

[root@VM-4-7-centos home]# mkdir docker-test-volume         		#创建docker-test-volume
[root@VM-4-7-centos home]# cd docker-test-volume					#进入文件夹
[root@VM-4-7-centos home]# vim dockerfile1							#编辑dockerfile1文件内容(制作脚本)
[root@VM-4-7-centos docker-test-volume]# cat dockerfile1 			#查看dockerfile1文件内容
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "----end----"
CMD /bin/bash
[root@VM-4-7-centos docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t cjycentos:1.0 .            #通过脚本制作镜像(最后面有个.)
[root@VM-4-7-centos docker-test-volume]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
cjycentos    1.0       8d8425552ab9   14 minutes ago   231MB

VOLUME ["volume01", "volume02"] This command is mounted anonymously.

Start the mirror written by yourself

[root@VM-4-7-centos docker-test-volume]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
cjycentos    1.0       8d8425552ab9   18 minutes ago   231MB
[root@VM-4-7-centos docker-test-volume]# docker run -it 8d8425552ab9 /bin/bash
[root@d1e86e1ca34c /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Jun 27 08:15 dev
drwxr-xr-x   1 root root 4096 Jun 27 08:15 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------   2 root root 4096 Sep 15  2021 lost+found
drwxr-xr-x   2 root root 4096 Nov  3  2020 media
drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
dr-xr-xr-x 115 root root    0 Jun 27 08:15 proc
dr-xr-x---   2 root root 4096 Sep 15  2021 root
drwxr-xr-x  11 root root 4096 Sep 15  2021 run
lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
dr-xr-xr-x  13 root root    0 Jun 27 08:15 sys
drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp
drwxr-xr-x  12 root root 4096 Sep 15  2021 usr
drwxr-xr-x  20 root root 4096 Sep 15  2021 var
drwxr-xr-x   2 root root 4096 Jun 27 08:15 volume01        #可以看到刚刚挂载的数据卷在这里
drwxr-xr-x   2 root root 4096 Jun 27 08:15 volume02		   #可以看到刚刚挂载的数据卷在这里

And these two data volumes will be mounted correspondingly under the /var/lib/docker/volumes/xxxxx(mount name)/_data path of the local machine . (You can use the docker inspect container id to view the corresponding mount path under Mounts)
Assuming that we did not mount the volume when we built the image, we need to manually mount -v volume name: path inside the container.

Nine.DockerFile

Introduction

dockerfile is a file used to build a docker image, and it is a command parameter script!
Build steps:

  1. Write a docker file
  2. docker build builds into a mirror image
  3. docker run run image
  4. docker push
    release image (DockerHub, Alibaba Cloud image warehouse)

build process

basic knowledge

  1. Each reserved keyword (instruction) must be an uppercase letter
  2. Execute sequentially from top to bottom
  3. #Represents comments
  4. Each command will create and submit a new image layer, and submit!!!

In the future, if you want to release the project, you need to make your own image and write the dockerfile.

Description of Common Commands

Order illustrate example
FROM Specify the base mirror image, everything starts to build from here FROM centos
MAINTAINER Who wrote the image, usually name + email (outdated) MAINTAINER [email protected]
LABEL It is the same as MAINTAINER, but you can set multiple LABEL maintainer=“[email protected]
RUN Commands that need to be run when the image is built RUN yum install -y wget
ADD Adding files will automatically decompress (mysql, redis, jdk...) ADD python.tar.gz /usr/local/
WORKDIR Set the working directory of the current mirror WORKDIR /usr/local/python/
VOLUME Mounted directory (data volume name) VOLUME [“volume01”,“volume02”]
EXPOSE Only expose the port of the container, you still need to continue to use -p for port mapping when using docker run EXPOSE 80
CMD Specify the command to run when the container starts, only the last one will take effect and can be replaced CMD /bin/bash
ENTRYPOINT Specify the command to run when the container starts, you can add the command ENTRYPOINT cd /opt ENTRYPOINT /bin/bash
ONBUILD When building an inherited DockerFile, the ONBUILD command will be run at this time
COPY Similar to ADD, copy our files to the mirror
ENV Set environment variables when building ENV JAVA_HOME /usr/local/jdk_1.8/

10. Make a Tomcat image

1. Create the tomcat folder first, and then operate in this folder.

[root@VM-4-7-centos home]# mkdir tomcat
[root@VM-4-7-centos home]# ls
tomcat
[root@VM-4-7-centos home]# cd tomcat

2. Then use the ftp tool to copy the compressed files of jdk and tomcat to this folder. Link to
Please add a picture descriptionthe compressed package of tomcat8 and jdk8
: https://pan.baidu.com/s/1IO-_RAlpLHFWA-D1UYuKsA?pwd=yxke
Extract code :yxke

[root@VM-4-7-centos tomcat]# ls
apache-tomcat-9.0.64.tar.gz  jdk-8-linux-x64.tar.gz

3. Write a Dockerfile (officially named Dockerfile , the build will automatically find this file, so there is no need to specify -f)

[root@VM-4-7-centos tomcat]# vim Dockerfile
[root@VM-4-7-centos tomcat]# cat Dockerfile
FROM centos
MAINTAINER cjy<13737xxxxx@qq.com>

ADD jdk-8-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.64.tar.gz /usr/local/


ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.64
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.64
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.64/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.64/bin/logs/catalina.out

4. Use the Dockerfile to build the image

[root@VM-4-7-centos tomcat]# docker build -t diytomcat:1.0 .

5. Start the generated image and build the Tomcat container.

The data volume is set here, and /home/tomcat/test of the host corresponds to /usr/local/apache-tomcat-9.0.64/webapps/test of the container. In this way, the repair of the test project only needs to be modified on the host machine, and there is no need to enter the container to modify it.

docker run -d -p 9003:8080 --name diytomcat -v /home/tomcat/test:/usr/local/apache-tomcat-9.0.64/webapps/test diytomcat:1.0

6. In the /home/tomcat/test directory, create a new index.html to test whether Tomcat can be used normally.
Because the volume mount is set, it can be operated directly on the host.

<!DOCTYPE html>
<html>
    <head>
         <meta charset="UTF-8"/>
        <title>这是个标题</title>
    </head>
    <body>
        <h1>这是一个一个简单的HTML</h1>
        <p>Hello World</p>
    </body>
</html>

7. Access test, browser access to check whether it can be accessed normally

Please add a picture description

11. Publish the image to DockerHub

Log in to your own dockerHub

[root@VM-4-7-centos tomcat]# docker login -u yxkcjy
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded

Then you need to regenerate a mirror before publishing, because when pushing, you need to add the username in front of the mirror name (yxkcjy is my username. If the username is not the current login user, the push request will be rejected), so you need to use the command docker tag Image name New image name Copy out an image and re-tag it.

[root@VM-4-7-centos tomcat]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
diytomcat    1.0       e8a23e9094d7   37 minutes ago   609MB
[root@VM-4-7-centos tomcat]# docker tag e8a23e9094d7 yxkcjy/diytomcat01:1.0
[root@VM-4-7-centos tomcat]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
diytomcat            1.0       e8a23e9094d7   38 minutes ago   609MB
yxkcjy/diytomcat01   1.0       e8a23e9094d7   38 minutes ago   609MB
[root@VM-4-7-centos tomcat]# docker push yxkcjy/diytomcat01:1.0					#发布镜像

Learning video address

Guess you like

Origin blog.csdn.net/cc1373709409/article/details/125421258