unsetunset前言unsetunset
AWS S3(Amazon S3,全名為亞馬遜簡易存儲服務(wù)),是亞馬遜公司利用其亞馬遜網(wǎng)絡(luò)服務(wù)系統(tǒng)所提供的網(wǎng)絡(luò)在線存儲服務(wù)。我常用的很多SaaS服務(wù)中提供的文件存儲功能,底層也都是AWS S3,比如:
Cloudflare中的R2基于AWS S3構(gòu)建的
Supabase頁可以兼容AWS S3(自建時,默認直接文件存儲到服務(wù)器本地)
本文,簡單自建一個與AWS S3完全對齊的存儲服務(wù),后面我們自建Supabase時,就可以將文件提交到這里了。
unsetunset基礎(chǔ)環(huán)境unsetunset
我在騰訊云上購買了韓國首爾的ubuntu 22.04 LTS 2核2G,注意要購買海外的,不然要花比較多精力處理網(wǎng)絡(luò)問題。
首先,安裝一下docker。在 Ubuntu 22.04 LTS 上安裝 Docker 非常簡單,你可以按照以下步驟進行:
更新包索引:在終端中執(zhí)行以下命令來確保本地的包索引是最新的:
sudo?apt?update
安裝依賴包:
sudo?apt?install?apt-transport-https?ca-certificates?curl?software-properties-common
添加 Docker 的官方 GPG 密鑰:
curl?-fsSL?https://download.docker.com/linux/ubuntu/gpg?|?sudo?apt-key?add?-
添加 Docker APT 倉庫:
sudo?add-apt-repository?"deb?[arch=amd64]?https://download.docker.com/linux/ubuntu?$(lsb_release?-cs)?stable"
更新包索引(再次):為了確保新添加的 Docker APT 倉庫生效,再次執(zhí)行更新包索引的命令:
sudo?apt?update
安裝 Docker CE:最后,執(zhí)行以下命令安裝 Docker 社區(qū)版(Docker CE):
sudo?apt?install?docker-ce
啟動 Docker 服務(wù):安裝完成后,Docker 服務(wù)會自動啟動。你可以使用以下命令來檢查 Docker 服務(wù)的狀態(tài):
sudo?systemctl?status?docker
如果 Docker 正在運行,你會看到類似于 "Active: active (running)" 的信息。
現(xiàn)在,Docker 已經(jīng)成功安裝在你的 Ubuntu 22.04 LTS 上了。你可以嘗試運行 docker --version
來驗證 Docker 是否安裝成功。
unsetunset基于minio構(gòu)建S3unsetunset
minio官網(wǎng):https://min.io/,它是一個完全兼容S3的開源存儲方案,你可以基于他們的docker鏡像自建minio,從而實現(xiàn)自己的存儲服務(wù),也可以使用他們提供的(Minio自己號稱是世界上最快的對象存儲服務(wù)),這里我們選擇自建。
創(chuàng)建 docker-compose.yml 文件,寫入如下內(nèi)容:
version:?'3.8'
services:
??minio:
????image:?quay.io/minio/minio
????container_name:?minio
????volumes:
??????-?./minio-data:/data
????environment:
??????MINIO_ROOT_USER:?your_root_user
??????MINIO_ROOT_PASSWORD:?your_root_password
??????MINIO_SERVER_URL:?https://storage.yourdomain.com
????command:?server?/data?--console-address?":9090"
???
??nginx:
????image:?'jc21/nginx-proxy-manager:latest'
????restart:?unless-stopped
????ports:
??????-?'80:80'
??????-?'81:81'
??????-?'443:443'
????volumes:
??????-?./nginx-data:/data
??????-?./nginx-letsencrypt:/etc/letsencrypt
你需要修改MINIO_ROOT_USER、MINIO_ROOT_PASSWORD和MINIO_SERVER_URL,用戶名和密碼在你構(gòu)建好minio時,用于登錄minio服務(wù),而MINIO_SERVER_URL是我們上傳文件后,我們需要訪問這個文件時,所需要使用的url,比如,我將MINIO_SERVER_URL設(shè)置成https://s3.xxxx.run,那么當我們訪問minio中的文件,就會使用https://s3.xxxx.run,如下圖:

除了minio鏡像外,我們還構(gòu)建了nginx-proxy-manager服務(wù),這個服務(wù)其實就是將nginx的各種功能通過一個webui提供出來,方便我們使用,然后還集成了一些其他服務(wù),比如Let's Encrypt服務(wù),這樣我們就可以通過nginx-proxy-manager快速將域名從http轉(zhuǎn)成https了。
docker-compose.yml內(nèi)容解釋完了,我們在docker-compose.yml同目錄下,運行docker compose up -d,然后等待2個鏡像安裝并啟動相應(yīng)的容器,等容器啟動完后,我們訪問:http://your-server-ip:81就可以進入nginx-proxy-manager的頁面,此時我們使用默認賬號密碼登錄(username:admin@example.com,password:changeme),第一次登錄需要修改郵箱和密碼。

unsetunsetnpm配置unsetunset
這里的npm是nginx-proxy-manager的簡稱,不是npmjs。
我們一開始使用ip:81去訪問npm,但這是不太安全的,因為是http,容易被中間人攻擊(雖然我感覺早期沒人會攻擊你,哈哈),所以我們還是用https+域名的方式訪問npm比較好。
進入npm,點擊Hosts -> Proxy Hosts -> Add New Proxy Host。

我在name.com購買了域名,注意,在name.com購買域名時,會默認將域名的SSL證書、whois信息保護給購買,我們需要取消這個,因為我們會使用Let's Encrypt來創(chuàng)建證書,我一開始直接在name.com購買了域名+SSL證書服務(wù),導(dǎo)致npm操作時報錯,然后我又購買了一個新域名,此時沒有去購買SSL證書,操作成功。
這里有一些細節(jié),不同的CA(證書頒發(fā)機構(gòu))是否是沖突的,比如name.com自己的CA去頒發(fā)SSL證書后,是否會導(dǎo)致Let's Encrypt無法成功,我沒有理清這里所有技術(shù)細節(jié)(就是沒花時間去實驗,單純找GPT4聊了一下,感覺GPT4的回答不太符合我的技術(shù)直覺,就不貼出來了),如果你想一口氣成功,就聽我的,不要在name.com上購買SSL證書服務(wù)先。
假設(shè),我購買了xxx.run的域名(沒在name.com上購買SSL證書服務(wù)),此時按下圖操作,將:
xxx.run
www.xxx.run
proxy.xxx.run
s3.xxx.run
s3-dash.xxx.run
都添加成A Type,然后映射到服務(wù)器公網(wǎng)IP上。

回到npm,首先,我們先將proxy.xxx.run設(shè)成成npm的url,并開啟https。
點擊New Proxy Host時,先配置Domain Names。(圖是Edit Proxy Host,是因為我創(chuàng)建成功了,為了截圖,我打開了Edit,截圖給大家看,跟New Proxy Host沒有區(qū)別)

我們將proxy.xxx.run添加到Domain Names里,然后在Scheme中使用http(是的,不是https),然后Forward Hostname/IP處,填入127.0.0.1,然后Forward Port為81,這樣用戶訪問proxy.xxx.run時,就會命中這條proxy host規(guī)則,然后被nginx轉(zhuǎn)發(fā)到127.0.0.1:81的服務(wù)上。
然后去到SSL配置,為域名設(shè)置https。

此時點擊Save,就成功了。
可以看見STATUS為Online。
當然我一開始也踩了坑,STATUS是Unknown,此時,就需要看一下日志。
通過 sudo docker logs -f npm容器id 的方式,實時查看npm的日志,然后重復(fù)去點擊一次Save,看看是否有報錯,然后再基于報錯信息去查詢,不要通過f12,通過chrome的Console中的報錯去Google,因為這里的報錯不準確,你難以定位具體的原因。
設(shè)置成功后,就可以通過proxy.xxx.run訪問npm了,此時就是https的。

接著,我們需要配置一下minio的路由。
我們先創(chuàng)建s3.xxx.run的Proxy Host配置,這里需要跟docker-compose.yml中minio配置的MINIO_SERVER_URL一致,如下圖:

注意,F(xiàn)orward Hostname/IP 處,我們寫minio,Port使用的是9000,這是docker-compose.yml中minio的名稱,即docker內(nèi)部網(wǎng)絡(luò)可以通過http://minio:9000去訪問minio服務(wù),這樣用戶訪問s3.xxx.com,nginx會將流量轉(zhuǎn)發(fā)到http://minio:9000服務(wù)上。
怎么判斷Port是9000的?我們可以通過sudo docker ps查看到。

然后,SSL設(shè)置,也是一樣的,通過Let's Encrypt服務(wù)為s3.xxx.run生成SSL證書,開啟https。

因為s3.xxx.run是給上傳文件使用的,比如我們上傳了圖片到minio構(gòu)建的存儲服務(wù),此時想訪問這個圖片時,就需要使用s3.xxx.run,因為資源名稱、資源大小、資源類型不可控,為了避免資源無法被訪問,我們還需要配置一下nginx,實現(xiàn)如下效果:
允許url中存在特殊字符
允許訪問任意大小的資源
停用緩存
上圖的內(nèi)容如下:
#?Allow?special?characters?in?headers
ignore_invalid_headers?off;
#?Allow?any?size?file?to?be?uploaded.
#?Set?to?a?value?such?as?1000m;?to?restrict?file?size?to?a?specific?value
client_max_body_size?0;
#?Disable?buffering
proxy_buffering?off;
proxy_request_buffering?off;
至此,s3.xxx.run就配置完了,我們還需配置一個url,才能訪問minio的web ui服務(wù),通過web ui服務(wù),我們才能創(chuàng)建api key,有了api key,我們才能使用代碼上傳文件。

Port使用了9090,這是因為docker-compose.yml中minio的配置,command使用了9090,所以我們需要轉(zhuǎn)發(fā)到9090。
然后SSL是一樣的設(shè)置。

此時,訪問s3-dash.xxx.com,就可以訪問到minio服務(wù)了,使用docker-compose.yml中你設(shè)置的username和password。

進來后,我們點擊【Object Browser】 -> 【Create a Bucket】,創(chuàng)建好,用于存儲資源的桶。

然后,我們上傳一張圖片:

查看圖片信息:

此時,點擊share,就會獲得圖片的url,其他用戶就可以通過這個url訪問這張圖片資源了。
為了讓代碼可以使用,我們可以創(chuàng)建Access Keys。

創(chuàng)建好后,可以直接修改一下將文件上傳到aws s3的代碼,換一下access key等內(nèi)容,代碼如下:
import?boto3
from?botocore.client?import?Config
access_key?=?'xxx'
secret_key?=?'xxx'
#?桶名稱
bucket_name?=?'test'
#?S3?兼容的終端節(jié)點
endpoint_url?=?'https://s3.xxx.run'
#?創(chuàng)建?S3?客戶端
s3_client?=?boto3.client('s3',?
?????????????????????????endpoint_url=endpoint_url,
?????????????????????????aws_access_key_id=access_key,
?????????????????????????aws_secret_access_key=secret_key,
?????????????????????????config=Config(signature_version='s3v4'))
#?要上傳的文件路徑
file_path?=?'cover.jpg'
file_key?=?'cover-1.jpg'??#?存儲桶中的文件名
#?上傳文件
try:
????s3_client.upload_file(file_path,?bucket_name,?file_key)
????print(f'文件成功上傳到?{bucket_name}/{file_key}')
except?Exception?as?e:
????print(f'上傳失敗:?{e}')
運行上面的代碼,會成功,然后刷新一下minio,就會看到conver-1.jpg,可以正常訪問和下載。
minio還提供Monitoring等功能,可自行探索。

unsetunset結(jié)尾unsetunset
至此,自建aws s3就完成了。文章來源:http://www.zghlxwxcb.cn/news/detail-830311.html
我是二兩,下篇文章見,后面幾篇文章,我會開始分析supabase源碼。文章來源地址http://www.zghlxwxcb.cn/news/detail-830311.html
到了這里,關(guān)于自建AWS S3存儲服務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!