本实践的最终目的是搭建一个支持多个 Laravel 项目的 Laradock 服务。

一、安装

最终目录布局:

+ laradock
+ project-1
+ project-2

Laradock 目录将和项目目录存放在同一目录下。

在项目目录下获取 Laradock:

$ git clone https://github.com/Laradock/laradock.git

二、配置

首先创建环境配置文件:

$ cd /path/to/laradock
$ # 从系统给的配置文件样例复制一份出来
$ cp env-example .env

2.1 重构服务

需要注意的一点是,如果已经使用 docker-compose up 命令启动了 Laradock 服务,在修改 Laradock 的 .env 文件后,或者修改各服务的 Dockerfile 文件之后,都需要重构相关服务的镜像,并且重构对应的容器。

workspace 为例,重构镜像的命令为:

$ docker-compose build workspace

在上面的命令中的 workspace 指的是服务名,而不是容器的名称,所以只要输入 workspace 即可。该命令与正在运行的容器没有关系也互不影响。

重构容器,该命令不会影响到挂载过的卷上的内容:

$ docker-compose up -d workspace

2.2 通用配置

  1. 修改默认时区为中国时区

    .env 文件中找到 WORKSPACE_TIMEZONE=UTC 参数,将其值改为 Asia/Shanghai。所有可选值参考 TZ database

    在使用 docker-compose exec workspace bash 命令进入 workspece 容器后,可以使用 date 命令查看当前时区。

    同时,也要修改 Laravel 项目的配置文件:依次打开:config -> app.php,将默认的 'timezone' => 'UTC', 改为 'timezone' => 'Asia/Shanghai'

  2. 中国区镜像

    .env 文件中找到 CHANGE_SOURCE=false 参数,将其值改为 true,但实际受其影响的源并不全面。

2.3 PHP

# Select a PHP version of the Workspace and PHP-FPM containers (Does not apply to HHVM). Accepted values: 7.3 - 7.2 - 7.1 - 7.0 - 5.6
PHP_VERSION=7.1

可选版本已在注释中写明。

2.4 Mysql

首先在 Laravel 项目的 .env 文件中,要将 DB_HOST 参数的值设置为 mysql,而不是 127.0.0.1,否则无法连接服务器。原因是,项目是在 Laradock 环境中的 workspace 容器中运行,通过 127.0.0.1 访问的只能是 workspace 容器中的内容。而要在 workspace 容器中访问 mysql 容器,则需要通过服务名访问。

然后编辑 Laradock 的 .env 文件如下

### MYSQL #################################################

MYSQL_VERSION=5.6
MYSQL_DATABASE=homestead
MYSQL_USER=homestead
MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d

按照上面的配置进行修改,也就是:

  • 指定版本号。
  • 修改默认创建数据库名为 Laravel 默认数据库名。
  • 修改默认创建用户名为 Laravel 默认用户名。

如果多个项目共用一个 Laradock 服务,那么就需要初始化多个数据库。途径就是在 MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d 参数指定的目录中操作:

$ cd ./mysql/docker-entrypoint-initdb.d
$ cp createdb.sql.example createdb.sql

然后修改新创建的 createdb.sql 文件,文件中已经给出了创建数据库以及添加用户权限的例句,模仿即可。比如要创建一个名为 foo 和一个名为 bar 的数据库,用户名就是上面配置的 homestead,并使用 utf8mb4 字符集:

# 创建名为 foo 的数据库并指定字符集为 utf84
CREATE DATABASE IF NOT EXISTS `foo` COLLATE 'utf8mb4_general_ci' ;
# 设定用户 homestead 拥有对数据库 foo 的所有操作权限
GRANT ALL ON `foo`.* TO 'homestead'@'%' ;

CREATE DATABASE IF NOT EXISTS `bar` COLLATE 'utf8mb4_general_ci' ;
GRANT ALL ON `bar`.* TO 'homestead'@'%' ;

# 下面这个命令是使修改的用户权限生效
FLUSH PRIVILEGES ;

注意: 这里的数据库操作会在启动 mysql 容器时运行,但是 $DATA_PATH_HOST/mysql 目录必须不存在,也就默认配置 ~/.laradock/data/mysql 目录必须不存在。

所以如果已经启动过 Laradock,又想导入数据库,就要走下面的流程:

导出现有数据库 -> 删除 ~/.laradock/data/mysql 目录 -> 将导出的数据库文件放在 MYSQL_ENTRYPOINT_INITDB 参数指定的目录中 -> 重启 mysql 容器

2.5 Nginx

默认的 Nginx 配置是服务于单个项目,所以需要修改。修改依据就是文章最开始的目录结构。

依次打开目录: laradock -> nginx -> sites,在其中可以看到默认的站点配置文件 default.conf,该文件是以单个项目为前提创建的,所以在其中可以看到下面的两个指令配置:

server_name localhost;
root /var/www/public;

而要想让 Laradock 服务多个项目,就需要更改配置文件。还是以服务 project-1project-2 两个项目为例:

$ # 屏蔽默认配置文件 default.conf
$ mv default.conf default.conf.backup
$ # 为每个项目创建单独的配置文件
$ cp laravel.conf.example project-1.conf
$ cp laravel.conf.example project-2.conf

然后分别打开 project-1.confproject-2.conf 文件,修改下面四个指令:

server_name project-1.test;
root /var/www/project-1/public;
# ...
error_log /var/log/nginx/project_1_error.log;
access_log /var/log/nginx/project_1_access.log;
  • server_name : 由于此时要服务于两个项目,就不能使用 localhost 作为域名来访问了,必须区分开来,用各自的项目名称作为域名加以区别。
  • root: 该指令指定各项目的访问路径。
  • error_log & access_log:指定各自错误日志和访问日志的文件路径。

最后,将域名追加到本地的 hosts 文件中:

127.0.0.1  project-1.test
127.0.0.1  project-2.test

2.6 Redis

.env 文件中关于 Redis 的只有对端口号的设置。在 laradock/redis 目录下有 Redis 的配置文件 redis.conf。对于 redis.conf 文件只需要修改一个参数 maxmemory-policy (最大内存策略),也就是当内存不够用的情况下如何删除现有 key,推荐设置为 volatile-lru,也就是当内存不足时,在设置了过期时间的 key 中,删除最近最少使用的 key

maxmemory-policy volatile-lru

Redis 容器默认挂载本地的 ~/.laradock/data/redis 目录。

可见 Redis 服务一般无需特别配置。

启动 Redis 服务后可以直接使用下面的命令登录 Redis 客户端:

$ docker-compose exec redis redis-cli

在 Laravel 使用 Redis 之前需要先安装扩展:

$ composer require predis/predis

或者安装性能更好一些的 PHP 扩展 PHPRedis

同时需要在 Laravel 的 .env 文件中设置 REDIS_HOST=redis ,而不是 127.0.0.1,原因同上面的 Mysql 相同。

为 Session 设置 Redis 驱动:

先在 config/database.php 文件中为 Session 设置专门的 Redis 数据库:

'redis' => [
       // ...
       'session' => [
           'host' => env('REDIS_HOST', 'redis'),
           'password' => env('REDIS_PASSWORD', null),
           'port' => env('REDIS_PORT', 6379),
           // 这里的 database 设置为一个不同其它的整数,默认不能超过 15
           'database' => 2,
       ]
   ],

然后在 config/session.php 文件中将 Session 驱动设置为 Redis,也就是在 .env 文件中将 SESSION_DRIVER 设置为 reids。并将连接设置为前面设置好的 session

'driver' => env('SESSION_DRIVER', 'file'),
'connection' => env('SESSION_CONNECTION', 'session'),

2.7 Elasticsearch

由于要使用的 THULAC 中文分词插件匹配的是 Elasticsearch 6.4.1,所以需要修改默认的版本,否则会出现异常退出的情况:打开 laradock -> elasticsearch -> Dockerfile,将第一行 FROM 指令尾部的版本改为 6.4.1

由于直接在容器中添加插件不方便,所以我选择将插件直接挂载到容器中:打开 laradock -> docker-compose.yml,找到 Elasticsearch 相关:

### ElasticSearch ########################################
    elasticsearch:
      build: ./elasticsearch
      volumes:
        - ${DATA_PATH_HOST}/elasticsearch/data:/usr/share/elasticsearch/data
        - ${DATA_PATH_HOST}/elasticsearch/plugins/thulac:/usr/share/elasticsearch/plugins/thulac
       # ...

也就是将本地的 ~/.laradock/data/elasticsearch/plugins/thulac 目录挂载到容器中的插件目录下。没有直接挂载到容器中的 plugins 目录的原因是,容器中的 plugins 目录内默认有 2 个插件,如果直接挂载到容器的 plugins 目录,会覆盖其中的默认插件。

对于中文分词插件,我选择的是 elasticsearch-thulac-plugin,它用的词法分析器是由清华大学研制的 THULAC

$ # 创建本地目录、下载、解压插件到该目录
$ cd ~/.laradock/data \
&& mkdir -p elasticsearch/plugins \
&& cd elasticsearch/plugins \
&& curl -LOk https://github.com/microbun/elasticsearch-thulac-plugin/releases/download/6.4.1-181027/elasticsearch-thulac-plugin-6.4.1-181027.zip \
&& unzip elasticsearch-thulac-plugin-6.4.1-181027.zip \
&& rm elasticsearch-thulac-plugin-6.4.1-181027.zip

值得一提的是,上面的 curl 命令必须使用 -L-k 选项,否则从 GitHub 上下载下来的 zip 文件不是正确的文件。原因看后面的参考文章。最后可以看到在 ~/.laradock/data/elasticsearch/plugins 目录下的插件 thulac 的目录文件。

接下来还要下载 THULAC 词法分析器用到的模型,在官网的获取链接部分,根据插件作者的推荐,找到 3.算法模型lite 版模型对应的下载链接,打开链接后需要登记一下信息,之后就会跳转到下载页面。

$ # 下载分词器模型,并将其拷贝到插件中
$ curl -O http://thulac.thunlp.org/source/Models_v1_v2.zip \
&& unzip Models_v1_v2.zip
&& cp -r models ~/.laradock/data/elasticsearch/plugins_extend/thulac/ \
&& rm -rf Models_v1_v2.zip models __MACOSX

可以注意到解压缩模型文件时会多出来一个 __MACOSX 目录,这个是 MacOS 系统在创建压缩文件时默认添加进去的,和 .DS_Store 性质差不多,删除即可。

初始化并进入容器:

$ # 如果已经初始化过,就要先重构一下
$ docker-compose build elasticsearch
$ # 初始化
$ docker-compose up -d elasticsearch
$ # 进入容器
$ docker-compose exec elasticsearch bash
[root@6792834994ca elasticsearch]# # 查看 elasticsearch 信息
[root@6792834994ca elasticsearch]# curl localhost:9200
[root@6792834994ca elasticsearch]# # 查看已安装的插件
[root@6792834994ca elasticsearch]# bin/elasticsearch-plugin list

2.8 Kibana

修改版本使其与 Elasticsearch 的版本一致,打开 laradock -> kibana -> Dockerfile,将第一行 FROM 指令尾部的版本改为 6.4.1

启动:

$ docker-compose up -d kibana

用浏览器访问 localhost:5601

三、操作

$ # 启动 Laradock 服务
$ docker-compose up -d nginx mysql redis

$ # 停止并删除所有 Laradock 容器,网络连接
$ docker-compose down

$ # 清理所有悬空镜像,以及没有被容器引用的镜像
$ docker image prune -af

四、参考文章

laradock多项目互相访问的问题

Guzzle/Curl connections between multiple projects

can’t download github project with curl command

(完)