本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)javascript
本文做者: 蘇洋css
建立時間: 2019年04月04日 統計字數: 6010字 閱讀時間: 12分鐘閱讀 本文連接: soulteary.com/2019/04/04/…html
平常偶爾會下載百度網盤的資源,可是又嫌棄官方客戶端「限速」和「笨重」,十天前趁着整理 HomeLab 的機會,把 Aria2 封裝成了容器鏡像。前端
本文將介紹如何搭配 Traefik 快速使用 Aria2 ,以及如何調整不兼容 Traefik 的應用與之兼容。java
在開始講解如何作以前,須要先簡單介紹一下鏡像的構成。node
對於長期運行的應用/服務來講,代碼是否透明公開很重要,我已經將代碼上傳至 GitHub:代碼倉庫地址。git
使用到的技術棧/工具主要有如下內容:github
網上盛行使用一個容器同時提供 HTTP + ARIA2 服務,可是這種胖容器其實不符合「單一進程單一容器」的原則,更通俗的說,這樣使用容器,和使用 VM 虛擬機沒有差異。web
因此在使用的過程當中,咱們須要單獨運行這兩個部分,使用 docker-compose.yml
定義的話,或許最簡單的示例就是下面這樣了:docker
version: '3'
services:
web:
container_name: web
image: ${WEBUI_IMAGE}
expose:
- 8888
aria2:
container_name: aria2
image: ${ARIA2_IMAGE}
volumes:
- ./downloads:/downloads
expose:
- 6800
複製代碼
但若是你將 Aria2 WebUI 直接使用在容器裏,你會發現這個 Web 管理界面將 RPC 端口寫死爲了 6800 ,由於項目設計的時候,只考慮了同機部署,而且是 Aria2 在默認配置執行的狀況。
之因此這樣處理,是由於項目自己是一套使用 Angular 編寫的 SPA 程序,不具有服務端接口處理能力,可是實際上,項目在生產環境運行的時候,做者有提供一個簡單的 Node Server,是能夠支持必定程度的接口定製的。
而咱們使用容器將 Web UI 和 Aria2 進行隔離,至關於在兩臺不一樣的服務器中執行這兩個應用,因此這裏咱們要進行一些改造。
影響 WebUI 使用 Aria2 RPC 接口的主要有兩處引用,分別在:
/app/src/js/services/configuration.js
/app/src/js/services/rpc/rpc.js
複製代碼
先處理 configuration.js
的內容:
host: location.protocol.startsWith("http") ? location.hostname : "localhost",
path: "/jsonrpc",
port: 6800,
encrypt: false,
複製代碼
找到程序中上面的代碼部分,將端口 6800
修改成 80
。
接着處理 rpc.js
的內容:
if (["http", "https"].indexOf(uri.protocol()) != -1 && uri.host() != "localhost") {
configurations.push(
{
host: uri.host(),
path: "/jsonrpc",
port: 6800,
encrypt: false
},
複製代碼
一樣找到這段代碼,將端口 6800
修改成 80
。
將代碼改造完畢,你會發現WebUI中全部的請求都被定位到了當前域名下的 80
端口,前面提過,這個界面是一套前端 SPA 應用,是缺少接口處理能力的。
因此,接下來咱們要對服務端進行處理,我使用 ES6 重寫了做者的 Node Server,主要支持了 HTTP
/WS
協議轉發至 aria2
容器對應的端口。
const { createServer } = require("http");
const url = require("url");
const { join, extname } = require("path");
const { exists, statSync, readFile } = require("fs");
const port = parseInt(process.argv[2], 10) || 8888;
const baseDir = join(process.cwd(), "docs");
const httpProxy = require('http-proxy');
const { WEB_PROXY, WS_PROXY } = process.env;
const webProxy = httpProxy.createProxyServer({ target: WEB_PROXY });
const wsProxy = httpProxy.createServer({ target: WS_PROXY, ws: true });
createServer(function (request, response) {
const uri = url.parse(request.url).pathname;
let filename = join(baseDir, uri);
let contentType = "text/html";
switch (extname(filename)) {
case ".js":
contentType = "text/javascript";
break;
case ".css":
contentType = "text/css";
break;
case ".ico":
contentType = "image/x-icon";
break;
case ".svg":
contentType = "image/svg+xml";
break;
}
if (filename.endsWith("jsonrpc")) {
webProxy.web(request, response);
return;
}
exists(filename, function (exists) {
if (!exists) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.write("404 Not Found\n");
response.end();
return;
}
if (statSync(filename).isDirectory()) filename += "/index.html";
readFile(filename, "binary", function (err, file) {
if (err) {
response.writeHead(500, { "Content-Type": "text/plain" });
response.write(`${err}\n`);
response.end();
return;
}
response.writeHead(200, { "Content-Type": contentType });
response.write(file, "binary");
response.end();
});
});
}).on('upgrade', function (req, socket, head) {
wsProxy.ws(req, socket, head);
}).listen(port);
console.log(`WebUI Aria2 Server is running on http://localhost:${port}`);
複製代碼
當用戶訪問管理界面的時候,靜態資源會直接使用 Node.js 的 HTTP 模塊提供服務。而當用戶進行下載狀態查詢,新增下載任務的時候,將經過 Node.js 調用 Aria2 的接口進行處理,並將結果使用 HTTP
或 WS
反饋給用戶。
爲了方便部署和維護,咱們須要將上面的改動記錄在 Dockerfile 中。
FROM node:11.12-alpine
LABEL AUTHOR soulteary
ADD webui-aria2/package.json /app/package.json
ADD webui-aria2/package-lock.json /app/package-lock.json
WORKDIR /app
RUN npm install -g yarn && yarn
ADD webui-aria2/ /app
ADD ./patches/configuration.js /app/src/js/services/configuration.js
ADD ./patches/rpc.js /app/src/js/services/rpc/rpc.js
RUN yarn build
RUN yarn add http-proxy
ADD ./patches/node-server.js /app/node-server.js
CMD [ "node", "./node-server.js" ]
複製代碼
執行 docker build -t soulteary/traefik-aria2-with-webui .
,稍等片刻你將獲得封裝好的容器鏡像。
接下來即是使用容器編排工具,正式使用啦。
Aria2 的鏡像,可使用 ndthuan/aria2-alpine
,無須從新封裝,固然,若是你須要一些新的特性,也能夠參考鏡像提供的 Dockerfile,進行從新構建。
建立一個 docker-compose.yml
,使用下面的示例代碼:
version: '3'
services:
web:
container_name: web
image: ${WEBUI_IMAGE}
expose:
- 8888
networks:
- traefik
environment:
- WEB_PROXY=http://aria2:6800
- WS_PROXY=ws://aria2:6800
labels:
- "traefik.enable=true"
- "traefik.port=8888"
- "traefik.frontend.rule=Host:${BIND_HOSTS}"
- "traefik.frontend.entryPoints=http,https"
aria2:
container_name: aria2
image: ${ARIA2_IMAGE}
volumes:
- ./downloads:/downloads
expose:
- 6800
networks:
- traefik
labels:
- "traefik.enable=false"
networks:
traefik:
external: true
複製代碼
而後再建立一個 .env
文件,在其中填入:
WEBUI_IMAGE=soulteary/traefik-aria2-with-webui
ARIA2_IMAGE=ndthuan/aria2-alpine
BIND_HOSTS=download.lab.com,download.lab.io
複製代碼
使用 docker-compose up
,你將看到相似下面的日誌:
Creating web ... done
Creating aria2 ... done
Attaching to aria2, web
aria2 | 2019-04-04T04:28:41Z 48a00033e530 confd[7]: INFO Backend set to env
aria2 | 2019-04-04T04:28:41Z 48a00033e530 confd[7]: INFO Starting confd
aria2 | 2019-04-04T04:28:41Z 48a00033e530 confd[7]: INFO Backend nodes set to
aria2 | 2019-04-04T04:28:41Z 48a00033e530 confd[7]: INFO Target config /etc/aria2.conf out of sync
aria2 | 2019-04-04T04:28:41Z 48a00033e530 confd[7]: INFO Target config /etc/aria2.conf has been updated
aria2 |
aria2 | 04/04 04:28:41 [WARN] Neither --rpc-secret nor a combination of --rpc-user and --rpc-passwd is set. This is insecure. It is extremely recommended to specify --rpc-secret with the adequate secrecy or now deprecated --rpc-user and --rpc-passwd.
aria2 |
aria2 | 04/04 04:28:41 [NOTICE] IPv4 RPC: listening on TCP port 6800
aria2 |
aria2 | 04/04 04:28:41 [NOTICE] IPv6 RPC: listening on TCP port 6800
web | WebUI Aria2 Server is running on http://localhost:8888
複製代碼
在瀏覽器中打開你在 .env
中定義的域名,不出意外,你將看到屬於你的下載應用。
改變習慣不易,尤爲是你周圍的環境都在使用其餘看起來更「標準成熟」的方案時。
可是一旦當你用慣了 Traefik + Docker 以後,你會發現你的服務搭建效率遠比使用 Nginx 加 vhost 高的多。
最近快忙暈了,臨近小長假,補全了這篇拖了十天的文章,倉促成文,不免有紕漏,歡迎留言指正。
我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。
在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。
喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)