我就是頭髮掉光,累死,死在ICU,也不會使用 Docker
。
唉呀媽呀,真香。。。
Hyperf In Docker
作為 Hyperf
框架作者之一,強烈安利大家使用 Docker
,現在 Docker叢集
技術已經十分成熟,K8s
強勢領跑,深受一線企業的厚愛,而Swarm
使用簡單,絕對是中小型企業的首選。
但今天,並不是講 Hyperf
在 Docker
中的應用,而是 前端
如何在 Docker
中進行打包,並與 Hyperf
進行通訊。
打包
我們下面以 VUE
為例。這裡提供一個倉庫 vue-docker-demo,供大家測試。
首先我們使用 vue
腳手架初始化一個專案。
vue create vue-docker-demo
接下來我們初始化 Hyperf 專案,這裡為了方便講解,後端專案也一同上傳到這一個倉庫中。
cd vue-docker-demo
composer create hyperf/biz-skeleton hyperf
修改 Hyperf 專案,方便測試
新建 UserController
控制器
<?php
declare(strict_types=1);
namespace App\Controller;
class UserController extends Controller
{
public function info(int $id)
{
return $this->response->success([
'id' => $id,
'name' => 'Hyperf',
]);
}
public function update(int $id)
{
$name = $this->request->input('name');
return $this->response->success([
'id' => $id,
'name' => $name,
]);
}
}
新增路由
<?php
Router::get('/user/{id:\d+}', 'App\Controller\UserController@info');
Router::post('/user/{id:\d+}', 'App\Controller\UserController@update');
新增單元測試
<?php
declare(strict_types=1);
namespace HyperfTest\Cases;
use HyperfTest\HttpTestCase;
/**
* @internal
* @coversNothing
*/
class UserTest extends HttpTestCase
{
public function testUserInfo()
{
$res = $this->get('/user/1');
$this->assertSame(0, $res['code']);
$this->assertSame(['id' => 1, 'name' => 'Hyperf'], $res['data']);
}
public function testUserUpdate()
{
$res = $this->json('/user/1', [
'name' => 'limx',
]);
$this->assertSame(0, $res['code']);
$this->assertSame(['id' => 1, 'name' => 'limx'], $res['data']);
}
}
跑一下介面測試
$ composer test
> co-phpunit -c phpunit.xml --colors=always
Detected an available cache, skip the app scan process.
Detected an available cache, skip the vendor scan process.
[DEBUG] Event Hyperf\Framework\Event\BootApplication handled by Hyperf\Di\Listener\BootApplicationListener listener.
[DEBUG] Event Hyperf\Framework\Event\BootApplication handled by Hyperf\Config\Listener\RegisterPropertyHandlerListener listener.
[DEBUG] Event Hyperf\Framework\Event\BootApplication handled by Hyperf\Paginator\Listener\PageResolverListener listener.
PHPUnit 7.5.16 by Sebastian Bergmann and contributors.
... 3 / 3 (100%)
Time: 309 ms, Memory: 16.00 MB
OK (3 tests, 14 assertions)
改造 VUE 專案
我前端水平有限,所以就寫點簡單的測試,主要是為了試驗
Dockerfile
。
使用 NPM
安裝 axios
npm i axios -S
新增 request.js
import axios from 'axios'
export default {
async request(method, url, params) {
const BASE_URI = '/api';
return axios({
method: method,
url: `${BASE_URI}${url}`,
data: params,
});
}
}
修改 HelloWorld.vue
,以下只展示修改後的部分
<script>
import request from "../api/request";
export default {
name: 'HelloWorld',
messaage: '',
props: {
msg: String
},
async mounted() {
var data = await request.request('GET', '/user/1');
// eslint-disable-next-line no-console
console.log(data);
var res = await request.request('POST', '/user/1', { name: "limx" });
// eslint-disable-next-line no-console
console.log(res);
}
}
</script>
新增 Dockerfile 和 app.conf
首先,當 nginx
拿到 /api
字首後,轉發到對應的後端服務,所以這裡需要提供一份 app.conf
配置
server {
listen 80;
root /usr/src/app/dist;
index index.html;
client_max_body_size 8M;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /api/ {
proxy_pass http://biz-skeleton:9501/;
}
}
接下來是我們的 Dockerfile
,邏輯其實很簡單,我們先透過 node
環境進行打包,然後再 copy
到 nginx
環境下即可。
FROM node:10-alpine as builder
WORKDIR /usr/src/build
ADD package.json /usr/src/build
ADD package-lock.json /usr/src/build
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org && cnpm install
COPY . /usr/src/build
RUN npm run-script build
FROM nginx:alpine
COPY --from=builder /usr/src/build/dist /usr/src/app/dist
COPY --from=builder /usr/src/build/app.conf /etc/nginx/conf.d/
ENTRYPOINT ["nginx", "-g", "daemon off;"]
打包測試
首先進入我們 Hyperf
目錄,打包後端服務
cd hyperf
docker build . -t biz-skeleton:latest
然後打包我們的前端程式碼
docker build . -t vue-demo
建立閘道器,如果已經建立過,可以忽略這裡,並使用建立過的閘道器
$ docker network create \
--subnet 10.0.0.0/24 \
--opt encrypted \
--attachable \
default-network
接下來,讓我們把兩個專案都跑起來
docker run -p 9501:9501 --name biz-skeleton --network default-network --rm -d biz-skeleton:latest
docker run -p 8080:80 --name vue-demo --network default-network --rm -d vue-demo:latest
然後透過瀏覽器訪問 http://127.0.0.1:8080/
就可以看到我們的測試結果在終端中輸出了。
釋出
專案釋出這裡就不再贅述了,需要了解的就去看一下 DockerSwarm
叢集搭建,有全自動的打包釋出方案,教程就在 Hyperf
官方文件中。
這裡需要額外提一下的是,打包好的靜態檔案,每次都走伺服器公網流量是很浪費的,這裡推薦大家使用 CDN
,然後配一個回源,可以大大減少流量的壓力。當然,回源策略那裡要注意一下,把介面返回的資料也快取到 CDN
上就不好了。
寫在最後
Hyperf 是基於 Swoole 4.4+ 實現的高效能、高靈活性的 PHP 協程框架,內建協程伺服器及大量常用的元件,效能較傳統基於 PHP-FPM 的框架有質的提升,提供超高效能的同時,也保持著極其靈活的可擴充套件性,標準元件均基於 PSR 標準 實現,基於強大的依賴注入設計,保證了絕大部分元件或類都是 可替換 與 可複用 的。
框架元件庫除了常見的協程版的 MySQL 客戶端、Redis 客戶端,還為您準備了協程版的 Eloquent ORM、WebSocket 服務端及客戶端、JSON RPC 服務端及客戶端、GRPC 服務端及客戶端、Zipkin/Jaeger (OpenTracing) 客戶端、Guzzle HTTP 客戶端、Elasticsearch 客戶端、Consul 客戶端、ETCD 客戶端、AMQP 元件、Apollo 配置中心、阿里雲 ACM 應用配置管理、ETCD 配置中心、基於令牌桶演算法的限流器、通用連線池、熔斷器、Swagger 文件生成、Swoole Tracker、Blade 和 Smarty 檢視引擎、Snowflake 全域性ID生成器 等元件,省去了自己實現對應協程版本的麻煩。
Hyperf 還提供了 基於 PSR-11 的依賴注入容器、註解、AOP 面向切面程式設計、基於 PSR-15 的中介軟體、自定義程式、基於 PSR-14 的事件管理器、Redis/RabbitMQ 訊息佇列、自動模型快取、基於 PSR-16 的快取、Crontab 秒級定時任務、Translation 國際化、Validation 驗證器 等非常便捷的功能,滿足豐富的技術場景和業務場景,開箱即用。
本作品採用《CC 協議》,轉載必須註明作者和本文連結