Docker Compose部署隨機圖API

Aicnal發表於2024-08-10

Docker Compose部署隨機圖API

平時我們部署部落格的時候,為了考慮美觀會考慮使用隨機圖來作為文章的封面,現在有很多大佬願意提供隨機圖API,透過API我們可以很方便地部署隨機圖,不必自己尋找圖片,考慮頻寬支出

不過很多時候一些公益API訪問速度很慢,其中很多圖片並不是我們所想要的,這時候我們就要考慮自建隨機圖API了,我參考了很多教程,他們中的很多都是基於寶塔來實現的,但其實我們不必要安裝寶塔皮膚,完全可以在Docker內實現

前置準備

首先我們先建立一個資料夾來方式我們的docker-compose和其他的隨機圖檔案,並且進入該資料夾內:

mkdir random-pic && cd random-pic

之後上傳隨機圖的php檔案,在這裡有三個版本,其中一個版本我嘗試過無法使用(可能是我沒有正確使用?

原理介紹

隨機圖的基本實現是透過新建一個站點,透過向站點傳送請求,站點檔案將請求重定向(301)到隨機圖所在圖鏈,從而實現隨機圖切換:

圖片準備

獲取到原始圖片之後,我建議你對圖片繼續壓縮處理,常見的諸如將圖片轉換成webp,這能有效減小檔案體積,加快使用者端的載入速度,如果你使用的是物件儲存或者套了CDN的話,這能減小頻寬和費用壓力

在這裡推薦一下來自GoogleSquoosh,是一個很全能的圖片壓縮程式,不用下載,直接在瀏覽器中就可以使用:網址

基本上支援了常見圖片型別的轉換和壓縮:

版本1(不支援桌面與移動端切換

<?php
//存放api隨機圖連結的檔名img.txt
$filename = "img.txt";
if(!file_exists($filename)){
    die('檔案不存在');
}
 
//從文字獲取連結
$pics = [];
$fs = fopen($filename, "r");
while(!feof($fs)){
    $line=trim(fgets($fs));
    if($line!='' && substr($str , 0 , 1) != '#'){
        array_push($pics, $line);
    }
}
 
// 從陣列隨機獲取連結
// $pic = $pics[array_rand($pics)];
$pic = $pics[random_int(0, count($pics) - 1)]; # 真隨機
 
//返回指定格式
$type=$_GET['type'];
switch($type){
 
//JSON返回
case 'json':
    header('Content-type:text/json');
    die(json_encode(['pic'=>$pic]));
 
default:
    die(header("Location: $pic"));
}
 
?>

此時你要在該資料夾內新建一個img.txt檔案,用來儲存隨機圖的圖鏈,這裡的圖鏈就決定了你圖片載入的速度,請務必選擇一些速度比較快的圖床,這能夠有效提高使用體驗和載入速度:

此時你的檔案結構應該如下,有img.txtrandom.php兩個檔案

.
├── img.txt
└── random.php

版本2(支援桌面與移動端切換

<?php
// 函式:訪客裝置
function is_mobile() {
    if (empty($_SERVER['HTTP_USER_AGENT']) || 
        strpos($_SERVER['HTTP_USER_AGENT'], 'iPad') !== false) {
        // 因為iPad有類似於PC的長寬比,所以我設定為電腦端
            $is_mobile = false;
        } elseif ( strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false 
            || strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
            || strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
            || strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
            || strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
            || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false
            || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mobi') !== false ) {
        $is_mobile = true;
    } else {
        $is_mobile = false;
    }
    return $is_mobile;
}
 
// 電腦與手機用不同的桌布
if(is_mobile()){
   // 手機桌布
   $filename = "img_mobile.txt";
}else{
   // 電腦桌布
   $filename = "img.txt";
}
 
//存放api隨機圖連結的檔名img.txt
if(!file_exists($filename)){
    die('檔案不存在');
}
 
//從文字獲取連結
$pics = [];
$fs = fopen($filename, "r");
while(!feof($fs)){
    $line=trim(fgets($fs));
    if($line!='' && substr($str , 0 , 1) != '#'){
        array_push($pics, $line);
    }
}
 
//從陣列隨機獲取連結
$pic = $pics[array_rand($pics)];
 
//返回指定格式
$type=$_GET['type'];
switch($type){
 
//JSON返回
case 'json':
    header('Content-type:text/json');
    die(json_encode(['pic'=>$pic]));
 
default:
    die(header("Location: $pic"));
}
 
?>   

使用這種方法,你需要額外新增一個img_mobile.txt檔案來放置用於移動端的圖片,檔案內容同img.txt

此時你的檔案結構應該如下:

.
├── img_mobile.txt
├── img.txt
└── random.php

版本3(尚未成功

此版本需要引用Mobile_Detect.php,用於檢測使用者的裝置型別(如手機、平板、桌面等),你需要自行去GitHub上下載原始碼,並且將它放置到此資料夾內:

  1. 訪問 GitHub 倉庫
    • 訪問 Mobile_Detect GitHub 倉庫
  2. 下載 ZIP 檔案
    • 在倉庫頁面上,點選綠色的 “Code” 按鈕,然後選擇 “Download ZIP” 以下載整個倉庫的壓縮包。
  3. 解壓並找到 Mobile_Detect.php
    • 解壓下載的 ZIP 檔案,在解壓後的目錄中,找到 src/Mobile_Detect.php 檔案。
  4. 將檔案放到正確的位置
    • Mobile_Detect.php 檔案放置到你的專案目錄中,例如 /root/random-pic/

之後random.php的內容為:

<?php
/*
 * 函式:訪客裝置
 * 部落格園:https://www.cnblogs.com/freephp/p/13979503.html
 * Github: https://github.com/serbanghita/Mobile-Detect
*/
function is_mobile(){
    require(__DIR__ . '/MobileDetect.php'); // 修正檔案路徑
    $MobileDetect = new Mobile_Detect();
 
    if ($MobileDetect->isTablet()) {
        // 平板定義為PC類
        return false;
    } elseif ($MobileDetect->isMobile()) {
        return true;
    } else {
        return false;
    }
}
 
// 電腦與手機用不同的桌布
$filename = is_mobile() ? "img_mobile.txt" : "img.txt";
 
// 存放api隨機圖連結的檔名
if(!file_exists($filename)){
    die('檔案不存在');
}
 
// 從文字獲取連結
$pics = [];
$fs = fopen($filename, "r");
while(!feof($fs)){
    $line = trim(fgets($fs));
    if($line != '' && substr($line, 0, 1) != '#'){ // 修正變數名
        array_push($pics, $line);
    }
}
fclose($fs);
 
// 從陣列隨機獲取連結
$pic = $pics[random_int(0, count($pics) - 1)]; // 真隨機
 
// 返回指定格式
$type = $_GET['type'] ?? '';
switch($type){
 
// JSON 返回
case 'json':
    header('Content-type: application/json'); // 修正 Content-type
    die(json_encode(['pic' => $pic]));
 
default:
    die(header("Location: $pic"));
}
?>

此時還是需要新增img_mobile.txt,同版本2

此時檔案結構如下:

.
├── img_mobile.txt
├── img.txt
├── MobileDetect.php
└── random.php

Docker Compose部署

為了部署這個站點,在這裡我們直接使用Docker Compose進行操作:

version: '3.8'
services:
  web:
    image: nginx:latest
    ports:
      - "9000:80"
    volumes:
      - /root/random-pic:/usr/share/nginx/html
      - ./default.conf:/etc/nginx/conf.d/default.conf
    container_name: random-pic
    depends_on:
      - php-fpm
    networks:
      - mynetwork

  php-fpm:
    image: php:7.4-fpm
    volumes:
      - /root/random-pic:/usr/share/nginx/html
    networks:
      - mynetwork

networks:
  mynetwork:
    driver: bridge

這裡為了方便測試我們不佔用80埠,而是使用9000埠,之後使用Nginx或者其他工具進行反代即可

此時不要急著啟動容器,我們還需要定製一下Nginx的配置檔案:

此時新建一個default.conf

server {
    listen 80;
    server_name localhost;

    root /usr/share/nginx/html;
    index random.php;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass php-fpm:9000;
        fastcgi_index random.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

寫入後儲存,你的檔案結構應該是這樣的:

.
├── default.conf
├── docker-compose.yaml
├── img_mobile.txt
├── img.txt
└── random.php

之後正式啟動容器

docker compose up -d

之後訪問域名+埠即可看到隨機圖效果

後語

個人感覺給隨機圖域名套上CDN還是有意義的,因為這個嚴格來說也算個靜態網站,如果有CDN快取的話隨機圖的切換速度會變快很多

如果你對類似專案感興趣的話,不妨訪問我的小站小樹 | Docker Compose部署隨機圖API

參考文獻:Docker系列 WordPress系列 自建隨機圖API之靜態桌布

相關文章