欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

宁皓网 Docker 容器化应用 有大用

把一般的 PHP 应用放到容器里。使用 Docker 在本地创建一个 PHP 应用的运行环境。

代码库:https://github.com/ninghao/nest

封面摄影:Carsten Meyerdierks

来自  https://ninghao.net/course/3840#info


介绍

1)容器化 PHP 应用

一个一般的 PHP 应用需要几个服务 .. 比如 web 服务,数据库服务,还有解释 php 的服务,我们可以把这些服务单独放在各自的容器里面,使用 docker compose ,让这些服务可以配合到一块儿,提供一个完整的可以运行 php 应用的服务。

web 服务我们可以使用 nginx,数据库服务可以使用 mariadb ,它可以兼容 mysql , php 我们使用比较新的 php 7 ,再加上 php-fpm ... 它可以为 nginx 提供解释 php 的服务 ..

web 服务跟数据库服务可以共享一个数据卷,我们的应用的代码可以放在这个数据卷的上面 .. 然后再为数据库服务添加一个数据卷,可以保存数据库服务里的数据 .. 这样即使删除了数据服务的容器,它里面的数据也会保留下来 ..

先启用一下 docker ...

 然后打开终端 ... 进入到我的桌面上 .. 创建一个目录 .. 名字可以是 nest ... 它是我为这个运行环境起的一个名字 ...

进入到这个目录的下面 .. 然后用编辑器打开它 ... 在项目的根目录下创建一个 docker-compose.yml 这个文件 .. 在它里面,我们可以去定义需要的服务 .. 数据卷,还有网络 ...

docker-composer.yml文件内容

version: '2'

来自  https://ninghao.net/video/3842#info


定义服务

2)db - 定义数据库服务

在这个 docker compose 文件里面,添加一个 services .. 在它的下面可以去定义需要的服务 .. 我们先去定义一个数据库服务 ... 名字可以是 db ...

然后用一个 image 指定一下要使用的镜像 ... 用一下官方提供的 mariadb 这个镜像 .. 再指定一个具体的版本 .. 这样我们可以更好的控制自己的服务 ...

镜像可用的版本,你可以在镜像的介绍页面上找到 ... 这个镜像提供了一些环境变量,可以让我们去配置一下使用它创建的容器的一些行为 ..

具体可以使用哪些环境变量,你也可以在镜像的介绍页面上找到 .. 配置这些环境变量,先在服务里添加一个 environment ...

在它的下面,再去配置一下环境变量 .. MYSQL_ROOT_PASSWORD .. 它是数据库 root 用户的密码 .. 我们先把它设置成 root ...

MYSQL_DATABASE ... 这里可以指定一下要创建的数据库的名字 .. 比如我们要为应用创建一个名字是 app 的数据库 ..

再用一个 MYSQL_USER .. 可以指定一下数据库的用户的名字 .. 这里我们也把它设置成 app .. 然后是 MYSQL_PASSWORD .. 设置成 123123 ...

下面再去给数据库添加一个数据卷 ... 先去定义一个数据卷 ... 使用一个 volumes .. 名字是 db .. 使用的 driver 是 local ... 一个本地的数据卷 ..

再把这个 db 数据卷交给 db 这个服务 .. 在它的下面再用一个 volumes ... 添加一个 db ... 把它挂载到容器的 /var/lib/mysql 这个位置上 .. 它是数据库管理系统默认存储数据的地方 ...

这样我们就定义好了应用需要的数据库服务了 ...

docker-composer.yml文件修改后的内容

version: ' 2 '

    services:

        db:

                image: mariadb: 10.1

                environment :

                        MYSQL_ ROOT_ PASSWORD: " root"

                        MYSQL_ DATABASE: "app"

                        MYSQL_ USER: "app"

                        MYSQL_ PASSWORD:' "123123"

                volumes :

                        - db: /var/lib/mysqU

volumes  :

        db:

                driver: local

来自  https://ninghao.net/video/3844#info



3)db - 测试数据库服务

进入到项目所在的目录,然后去启动一下服务 .. 

docker-compose up -d 

... -d 可以让服务在后台运行 ... 启动以后,我们再进入到之前定义的数据服务这个容器里面 .. 

docker-compose exec db bash

 ..

进来以后再登录到数据库 ... 使用 root 这个用户登录 .. 它的密码就是我们在 MYSQL_ROOT_PASSWORD 这个环境变量里设置的那个 ...

查看一下数据库 ... show databases; 这里会出现我们创建的 app 这个数据库 ... 数据库的名字,用户名,还有密码,都是我们在定义 db 这个服务的时候,在它的环境变量里设置的 ...

mysql -u root -p

我们可以再去创建一个数据库 .. 比如创建一个叫 test 的数据库 ... 再退出来

exit

 ... 然后可以把项目里面定义的服务容器都删除掉 .. 

docker-compose down 

...

重新再启动一下 .... 

docker-compose up

进入到 db 这个容器里面 ... 

docker-compose exec db bash

登录到数据库 ... 

mysql -u root -p

再查看一下所有的数据库 ... 在这里会有一个之前我们创建的 test 数据库 ...

也就是即使我们删除掉了这个数据服务容器,它里面的数据也会被保留下来 .. 因为我们给它挂载了一个数据卷 ...

来自 https://ninghao.net/video/3845#info


4)php - 定义 php 服务

我们再去定义一个解释 php 脚本用的服务 ... 在 services 的下面,再添加一个新的服务 .. 名字可以是 php ... 这个服务使用的镜像是 php:7.0-fpm ...

php 是官方提供的镜像,里面有很多可以使用的版本,因为我们的 web 服务要用到 php-fpm,所以这里我们的 php 服务要使用它的 fpm 版本的 ...

再给它添加一个数据卷 .. 用一个 volumes .. 这个数据卷在主机上的位置是当前目录下的 app 这个目录 ... 把它挂载到容器里的 /mnt/app 这个位置上 ...

再去创建一个 app 目录 ... 在它的下面,可以再添加一个 php 文件,名字是 phpinfo.php .. 文件里面使用一个 phpinfo() 函数 ..

phpinfo.php文件的内容

<?php

phpinfo();

?>

 保存一下 ...

这个 php 服务可以先这样,后面我们会再去配置一下它,比如给它安装一些扩展,自定义一些配置等等 ...

docker-composer.yml文件修改后的内容

version: ' 2 '

    services:

        php:

                image: php:7.0-fpm 

                volumes:

                        - ./app: /mnt/app

        db:

                image: mariadb: 10.1

                environment :

                        MYSQL_ ROOT_ PASSWORD: " root"

                        MYSQL_ DATABASE: "app"

                        MYSQL_ USER: "app"

                        MYSQL_ PASSWORD:' "123123"

                volumes :

                        - db: /var/lib/mysqU

volumes  :

        db:

                driver: local

来自 https://ninghao.net/video/3846#info


5)web - 定义 nginx 服务

下面我们再用 nginx 这个镜像去给应用定义一个 web 服务 ... 这个服务的名字可以是 web .. 使用的镜像是 nginx .. 再设置一个具体的版本 ...

发布的端口可以放在 ports 的下面 ... 让主机上的 8080 端口,对应这个 web 服务的 80 这个端口 ... 这个 web 服务需要使用 php 提供的脚本解释服务 ..

所以我们要让它依赖 php 这个服务 .. 使用一个 depends_on .. 依赖的是 php 这个服务 ... 这样会先去启动 php 这个服务 .. 然后再启动这个 web 服务 ..

这个 web 服务跟 php 服务要共享一个数据卷,它里面存储的就是我们的应用的代码 ... 可以使用一个 volumes_from ... 让它去继承一下 php 服务上的数据卷 ...

下面我们需要再去添加一个 nginx 的配置文件,可以把它放在 images/nginx/config 这个目录的下面,名字是 default.conf ..

 images/nginx/config/default.conf文件内容如下

server {

        listen 80 ;

        server_name localhost;

        root /mnt/app; 

        index index.php index,html index.htm;

        location / {

                        index  index.php index.html index.htm;

        try_ files $uri $uri/ /index.php?$query_ string;

        }

        location ~ \.php$ { 

                fastcgi_pass php: 9000;

                fastcgi_index index.php;

                fastcgi_param SCRIPT FILENAME $document_ root$fastcgi script_ name ;

                include fastcgi_params;

        }

}



一会儿我们要把这个配置文件放到 web 服务的容器里面 ... 在这个 nginx 配置文件里, 我们可以定义一下监听的端口号 .. 主机名 .. 根目录这些东西 ...

这里我们定义了一个可以处理 php 脚本的区块 ... 这个 php 是我们定义的 php 服务的名字 ... 也就是如果 web 服务收到对 php 的请求以后,它会把请求交给我们的 php 这个服务去处理 ...

再回到 compose 的配置文件 .. 给这个 web 服务添加一个数据卷 .. 它在主机上的位置就是 ./images/nginx/config .. 把它挂载到容器里的 /etc/nginx/conf.d 这个位置上 .. 它是 nginx 服务的配置文件所在的地方 ..

docker-composer.yml文件修改后的内容

version: ' 2 '

    services:

         web:

                    image: nginx:1. 11.1 

                    ports :

                            - " 8080:80"

                    depends_ on:

                            - php

                    volumes_from :

                            - php

                    volumes:

                            - ./ images/nginx/config:/etc/nginx/conf.d

        php:

                image: php:7.0-fpm 

                volumes:

                        - ./app: /mnt/app

        db:

                image: mariadb: 10.1

                environment :

                        MYSQL_ ROOT_ PASSWORD: " root"

                        MYSQL_ DATABASE: "app"

                        MYSQL_ USER: "app"

                        MYSQL_ PASSWORD:' "123123"

                volumes :

                        - db: /var/lib/mysqU

volumes  :

        db:

                driver: local

保存一下 ...

回到终端 ... 再去启动一下所有的服务 ..

 docker-compose up -d 

...

打开浏览器 ... 访问一下 localhost:8080 .. 后面加上一个 phpinfo.php ... 这里你会看到 php 的相关信息 ... 这个 phpinfo.php 是我们项目下面的 app 这个目录下面的文件 ...


来自  https://ninghao.net/video/3847#info



Build

6)创建自己的服务

现在我们在 compose 文件里定义的服务用的都是现成的镜像,有时候我们需要定制一下这些镜像,比如去添加自己的配置,去安装新的模块等等 ...

比如我想修改 php 服务里的一些配置,现在你可以看到它的 upload_max_filesize 的值是 2M ... 我们先去创建一个 Dockerfile ,放在 images/php 这个目录的下面 ...


先用一个 FROM 指定一下基于哪个镜像去创建自己的镜像 .. 这里就是 php:7.0-fpm ... 再用一个 MAINTAINER 设置一下维护这个镜像的作者 ...

然后用一个 COPY .. 它可以把主机上的文件复制到镜像里面 ... 复制的是相对于这个 Dockerfile 文件下面的 config 这个目录里的 php.ini 这个文件 ... 把它复制到镜像里的 /usr/local/etc/php/conf.d/ 这个目录的下面 .. 这个目录是存储 php 配置的地方 ...

 images/php/Dockerfile 的内容

FROM php:7.0-fpm

MAINTAINER wanghao<wanghao@ninghao. net>

COPY ./config/php.ini /usr/local/etc/php/conf.d/


保存一下 ... 再去创建这个配置文件 .. 放在 images/php/config 下面,名字是 php.ini ... 在这个配置文件里,可以添加一些 php 相关的配置 .. 比如用一个 memory_limit .. 设置一下内存的限制 .. 再用一个 post_max_size .. 设置一下提交的大小 ... 然后再用一个 upload_max_filesize ... 设置一下可以上传文件的大小 .. 你可以把想要的 php 配置放在这个文件里面 ... 先保存一下 ...

 images/php/config/php.ini的内容如下

memory_limit = 256M

post_max_size = 100M

upload_max_filesize = 100M


再打开 compose 文件 .. 找到 php 这个服务 .. 去掉这个 image .. 换成 build ... 因为我们先要创建自己的镜像,然后再基于这个自定义的镜像创建一个容器服务 ...

用一个 context .. 设置一下 Dockerfile 所在的目录 ... 再用一个 dockerfile .. 设置一下 Dockerfile 文件的名字 ....


docker-composer.yml文件修改后的内容

version: ' 2 '

    services:

         web:

                    image: nginx:1. 11.1 

                    ports :

                            - " 8080: 80"

                    depends_ on:

                            - php

                    volumes_from :

                            - php

                    volumes:

                            - ./ images/nginx/config:/etc/nginx/conf.d

        php:

                build: 

                     context: ./images/php

                     dockerfile: Dockerfile

                     volumes:

                        - ./app: /mnt/app

        db:

                image: mariadb: 10.1

                environment :

                        MYSQL_ ROOT_ PASSWORD: " root"

                        MYSQL_ DATABASE: "app"

                        MYSQL_ USER: "app"

                        MYSQL_ PASSWORD:' "123123"

                volumes :

                        - db: /var/lib/mysqU

volumes  :

        db:

                driver: local

保存 ... 回到终端 .. 执行一下 

docker-compose build

 ... 这个命令可以去创建服务需要的镜像 ...

完成以后再执行一下 

docker-compose up -d

 ... 它可以重新创建需要的服务 ...

再回到浏览器 .. 刷新一下 ... 找到 upload_max_filesize .. 你会看到,现在它的值就变成了 100M ... 也就是 php 这个服务已经使用了我们自己的配置 ...

来自  https://ninghao.net/video/3849#info


7)安装 php 模块

要运行真正的应用,我们可能需要再为 php 服务安装一些扩展 ... 在这个 php 服务的 Dockerfile 里面,添加一个 RUN ,去执行一些命令 ...

这个 php:7.0-fpm 用的是 debian ,所以安装包可以使用 apt-get .. 先执行一下 apt-get update ... 两个 && 与符合可以继续执行其它的命令 .. 再用一下 apt-get install -y ,去安装需要的包,我们在安装 php 扩展之前要先安装这些扩展依赖的其它的一些包 ..

比如我要安装一个处理图像用的 gd 扩展 .. 它需要 libpng12-dev .. 还有 libjpeg-dev 这两个包 .. 后面加上一个反斜线,然后可以另起一行,继续添加其它的要执行的命令 ..

使用两个 & 符号连接一下 ... 可以使用 rm 删除掉 /var/lib/apt/lists 下面的所有的东西 ...

php 镜像里面提供了几个小工具,比如配置扩展可以使用 docker-php-ext-configure ... 配置一下 gd 扩展 .. 加上一个 --with-png-dir 选项 .. 启用 gd 扩展的处理 png 图像的功能 .. 再用一个 --with-jpeg-dir ... 启用一下处理 jpeg 图像的功能 ...

另起一行 .. 再执行一下 docker-php-ext-install ... 去安装需要的 php 扩展 .. 这里我们安装一下 gd 这个扩展 .. 还有 pdo_mysql .. 它提供了一个操作 mysql 数据库的功能 ... 再添加一个 zip 扩展 .. 还有一个 opcache ...

这个扩展我们可以单独去配置一下它 ... 在 images/php/config 目录下面创建一个文件 .. 名字是 opcache-recommended.ini ...


里面添加一些配置选项 ... 

images/php/config/opcache-recommended.ini 的内容如下

opcache.memory_consumption=128

opcache.interned_strings_buffer=8

opcache.max_accelerate_files=4000

opcache.reva_idate_freq=60

opcache.fast_shutdown=1

opcache.enable_cli=1


这些选项是我从 docker 官方的库里偷过来的 .. 想了解它们是什么意思可以去搜索一下 ...

下面再用一下 COPY ... 把这个配置文件,复制到镜像的 php 配置文件所在的目录里面 ...

 images/php/Dockerfile 的修改后的内容

FROM php:7.0-fpm

MAINTAINER wanghao<wanghao@n nghao.net>


RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev \

&& rm -rf /var/lib/apt/lists/* \ 

&& docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \

&& docker-php-ext-install gd pdo_mysql zip opcache


COPY ./config/php.ini /usr/local/etc/php/conf.d/ 

COPY ./config/opcache-recommended.ini /usr/local/etc/php/conf.d/ 

保存 ...

回到终端 ... 执行一下 

docker-compose build 

... docker 会按照我们在 Dockerfile 里面的配置重新生成镜像 ...

需要等一会儿 .. 因为要下载挺多东西 ...

完成以后 .. 再执行一下 

docker-compose up -d 

 ....

回到浏览器 .... 刷新一下 ... 我们可以在这个 php 信息的页面上,搜索一下刚才安装的扩展的名字 ... 比如 gd ...

你可以找到一个区域,上面有 gd 扩展的相关信息 ... 我们还安装了 opcache .... 在这里也可以找到 ... 你可以参考它下面的这些配置 ...

里面有些选项对应的值就是我们自己定义的 ....

来自  https://ninghao.net/video/3850#info


工具容器

8)创建工具包容器

在开发应用的时候会用到一些工具,比如 php 的包管理工具 composer, 管理 node 包的 npm , 管理 drupal 项目的 drush 等等 ...

这些东西我们可以单独放在一个容器里面,要使用它们的时候,我们可以进入到带这些工具的容器里面,然后去执行一些任务。

打开 docker-compose.yml .. 这里再添加一个新的服务 .. 名字可以是 console .. 表示控制台,或者操作台 ... 这个服务我们要去自己 build 一个镜像 ... 然后在上面去安装需要的工具 ...

这里用一个 build .. 位置是 images/console ... 创建镜像用的文件的名字是 Dockerfile ..

给它再挂载一个数据卷 .. 这个数据卷是从 php 这个服务那里来的 ...

再添加一个 tty ... 把它设置成 true ...

docker-composer.yml文件修改后的内容

version: ' 2 '

    services:

        console :

                build:

                               context: . / images/console 

                               dockerfile: Dockerfile

                voLumes_from:

                             - php

                tty: true

         web:

                    image: nginx:1. 11.1 

                    ports :

                            - "8080: 80"

                    depends_ on:

                            - php

                    volumes_from :

                            - php

                    volumes:

                            - ./ images/nginx/config:/etc/nginx/conf.d

        php:

                build: 

                     context: ./images/php

                     dockerfile: Dockerfile

                     volumes:

                        - ./app: /mnt/app

        db:

                image: mariadb: 10.1

                environment :

                        MYSQL_ ROOT_ PASSWORD: " root"

                        MYSQL_ DATABASE: "app"

                        MYSQL_ USER: "app"

                        MYSQL_ PASSWORD:' "123123"

                volumes :

                        - db: /var/lib/mysqU

volumes  :

        db:

                driver: local



然后我们可以再去创建这个服务需要用的 Dockerfile 放在 images/console 目录的下面 ...

先去设置一下要基于哪个镜像去创建我们自己的镜像 .. 这里可以先用一下 php 7.0 ... 然后再设置一下维护这个镜像的作者 ... 使用一个 MAINTAINER ... 添加一个用户名,还有对应的邮箱的地址 ...

 images/console/Dockerfile 文件内容如下

FROM php:7.0

MAINTAINER wanghao <wanghao@ninghao. net>



下面我们再去设置具体要怎么样创建这个工具包镜像 ...

来自  https://ninghao.net/video/3852#info


9)安装配置 git,composer

先去安装一些工具 ... RUN ,执行一下 apt-get udpate .. 再安装一下 git curl ..

然后再删除掉 /var/lib/apt/lists 下面的东西 ... 再用 pecl 去安装一下 zip 这个扩展 ... composer 会用到它解压 ... 再执行一下 docker-php-ext-enable ,启用一下 zip 这个扩展 .. 这个脚本是 php 这个镜像里面提供的 ...

zip 还依赖一个包 .. 把它也放在上面 ... 名字是 libfreetype6-dev ...

再去配置一下 git ... 执行 git config .. 设置一下 user name .. 用户名 .. 再设置一下用户的邮件地址 ...

下面我们再去安装一下 composer ... 在 composer 的官方网站你可以找到安装它使用的命令 ... 我们可以先去执行一下它们 ...

主要的作用就是去下载一个安装脚本,检查一下我们的环境,符合以后,它会给我们把 composer 下载下来 .. 然后会把那个安装脚本删除掉 ...

下载下来的文件是 composer.phar ... 想在任何地方可以使用它,我们要把它放在系统的环境变量的某个目录的下面 .. 可以把它转移到 /usr/local/bin 下面 .. 重命名成 composer ...

然后我们得把用户主目录下的 .composer vendor bin 这个目录下的东西作为可以执行的命令 ... 它里面就是用 composer 安装的一些东西 ... 我们可以去配置一下用户主目录下的 .bashrc 这个文件 ...

这行命令就是去把这个代码,放到 ~/.bashrc 这个文件里面 ... 它作用就是告诉系统,用户主目录下的 .composer/vendor/bin 里的东西可以直接执行 ...

再让这个配置可以立即生效 ...

最后我们可以再配置一下,让 composer 使用在中国的镜像 ... 这个镜像服务是 phpcomposer.com 提供的 ... 这样在国内使用 composer 安装东西(比如安装laravel)的时候会快很多 ...

 images/console/Dockerfile 文件修改后的内容如下

FROM php:7.0

MAINTAINER wanghao <wanghao@ninghao.net>


RUN apt-get update && apt-get install -y git curl libfreetype6-dev \

&& rm -rf /var/ lib/apt/lists/* \

&& pecl install zip \

&& docker-php-ext-enable zip


RUN git config --global user.name "wanghao8080" \

&& git config --global user.email "117663444@qq.com"


RUN php -r "copy('https://getcomposer.org/ installer','composer-setup.php')

&& php -r "if (hash_ file('SHA384','composer-setup.php') ==='

bf16ac69bd8b807bc6e4499b28968ee87456

e29a3894767b60c2d4dafa3d10d045ffef2aeb2e78827fa5f024fbe93ca2

'

&& php composer-setup.php \

&& php -r "unlink('composer-setup.php');" \

&& mv composer.phar /usr/ local/bin/ composer \

& echo

'export PATH="$PATH: $HOME/.composer/vendor/bin"'>> ~/.bashrc \

&&.~/.bashrc \

&& composer config -g repo.packagist composer https://packagist.phpcomposer.com


保存 ... 打开终端 ... 确定是在项目的根目录的下面 ... 再去 build 一下 console 这个镜像 .. 执行

 docker-compose build console

...

提示不能连接到 Docker ... 因为我现在没有启动它 ... 打开 Docker ... 等它启动以后 .. 再执行一下这个编译的命令 ...

这里又遇见个问题 ... 我觉得应该是个网络问题 .. . 就是在下载 composer 的时候出错了 ... 可以想想办法解决一下连接国外服务器( https://getcomposer.org/ installer )的问题 ...

然后再试一下 ...

 docker-compose build console

这回 docker 会按照我们在 console 的 Dockerfile 里面的配置,去生成一个新的镜像 ... 这个镜像里面,会安装并且配置好我们需要使用的工具 ...

来自 https://ninghao.net/video/3853#info


运行

10)安装运行 Laravel 项目

先启动一下项目里定义的所有的服务 ... 

docker-compose up -d

 ... 然后进入到 console 这个容器里面 ... 

docker-compose exec console bash


进来以后,进入到 /mnt/app 这个目录的下面 

cd /mnt/app

..

这里是我们给这个容器挂载的数据卷 ... 另外 web 还有 php 服务也使用了这个数据卷 .. 下面我们再用 composer 去创建一个项目 

 composer create-project --prefer-dist laravel/laravel laravel

.. 

项目使用的是 laravel/laravel .. 把它放在 laravel 这个目录的下面 ...

这样 composer 会去下载 Laravel .. 还有它依赖的一些其它的东西 ...

完成以后在这个 app 目录的下面,会出现一个 laravel 目录,它里面的东西就是 laravel 项目的代码 .. 回到编辑器 ... 找到 app 下面的 laravel 这个目录 ...

打开根目录下的 .env 这个文件 .. 修改一下相关的配置 ... APP_URL .. 这里设置成 localhost:8080 ..

DB_HOST,数据库的主机 .. 这里要设置成 db .. 这个 db 是我们在项目里定义的那个数据库服务的名字 ...

DB_DATABASE .. 数据库的名字是 app ... 用户也是 app ... 密码是 123123 ...

.env 大约修改的地方

image.png

保存一下 ...

然后我们得修改一下 NGINX 的配置 ... 打开 config 下面的 default.conf ... 这个项目的 root ... 现在应该是 /mnt/app/laravel 下面的 public 这个目录 ...

 default.conf 大约修改的地方

image.png

保存 ..

再重新启动一下 web 这个服务 ...

docker-compose restart web 

 这样新的配置就可以生效了 ...

打开浏览器 ... 访问一下 localhost:8080 ... 这里会显示出 Laravel 的欢迎界面 ....

来自  https://ninghao.net/video/3855#info


普通分类: