30 分鐘跑起第一臺雲伺服器:選區域、建實例、配金鑰,用 Docker Compose 部署應用、解析域名、Caddy 自動簽發 HTTPS,命令可直接複製。
「雲伺服器怎麼用」這個問題,大部分人卡住的不是難,而是不知道從哪一步開始:機器買了,SSH 連不上;連上了,不知道裝什麼;裝完了,域名和 HTTPS 又不知道怎麼弄。這篇按真實上線順序走一遍——30 分鐘跑起你的第一臺雲伺服器,從選區域到瀏覽器裡看到小鎖,每條命令都能直接複製。
本文假設:一臺全新的 Ubuntu 24.04 LTS 實例、一個已經解析到這臺伺服器的域名、你的電腦上能執行 ssh。還沒買域名也能跟到最後,只是第八步的 HTTPS 先跳過,用 IP + 埠訪問即可。
30 分鐘路線圖:每一步花多久
先看全域性,再動手。整條鏈路只有 8 個動作,難度從「點點滑鼠」到「貼一段配置」,沒有需要翻文件的黑魔法。
| 時間 | 動作 | 完成的標誌 |
|---|---|---|
| 第 0–3 分鐘 | 選區域 + 最小規格 | 確定 2 核 2G / Ubuntu 24.04 / 40GB 系統盤 |
| 第 3–7 分鐘 | 建立實例,繫結 SSH 金鑰與安全組 | 拿到公網 IP 和金鑰對 |
| 第 7–10 分鐘 | 第一次 SSH 登入 | 命令列提示符出現在雲主機上 |
| 第 10–14 分鐘 | ufw + 系統更新 + 時區 | 只剩 22 / 80 / 443 三個入口 |
| 第 14–19 分鐘 | 裝 Docker 與 Compose 外掛 | hello-world 列印成功 |
| 第 19–23 分鐘 | Compose 部署一個 Nginx 站點 | curl 127.0.0.1 返回 200 |
| 第 23–26 分鐘 | 加 A 記錄解析域名 | dig +short 拿到伺服器 IP |
| 第 26–30 分鐘 | Caddy 自動簽發 HTTPS 證書 | 瀏覽器位址列出現小鎖 |
- 選區域、選最小規格、想清楚要不要開自動續費
- 建立實例:映象用 Ubuntu 24.04 LTS,現場生成一對 ed25519 金鑰
- 安全組放行三條規則:22(只對自己的 IP)、80、443
- SSH 登入,把預設使用者和金鑰許可權確認一遍
- 最小加固:
ufw+ 自動安全更新 + 對時 - 用官方 APT 倉庫裝 Docker 與 Compose 外掛
- 寫一個
compose.yaml,把 Nginx 站點跑起來 - 解析域名,再讓 Caddy 接管 80/443 簽發證書
按這個順序走,每一步都有明確的「做完了」標誌,不用回頭驗證前面。反過來做(比如先配 HTTPS 再解析域名)會把大量時間浪費在等待和排錯上。
第一步:選區域和規格,2 核 2G 夠起步
第一臺雲伺服器不用買大。 你現在的目標是跑通流程,不是承載流量——配置越複雜,出錯點越多。如果只想開一臺跑部落格或測試,輕量應用伺服器 這種「計算 + 儲存 + 頻寬打包計費」的形態更省心,不用自己算流量。
- 系統:Ubuntu 24.04 LTS。文件多、軟體源新(自帶 Docker 官方倉庫),
apt裝任何東西都不會缺 - 規格:2 vCPU / 2 GB 記憶體。跑 Nginx + Caddy + 一個輕量應用,長期 CPU 使用率通常在 20% 以內
- 系統盤:40 GB SSD 夠用。系統映象本身佔 3–6 GB,剩下的留給日誌和構建產物
- 頻寬:1–5 Mbps 固定頻寬,或直接選按流量計費。第一個站不會有大流量,先別為峰值買單
- 區域:離使用者近的那一個。面向中文使用者的香港 / 新加坡 / 日本節點,回源延遲一般落在 15–40ms 區間
如果這臺機器要跑訓練任務、資料庫或編譯大型專案,規格另說。先按 2 核 2G 起步,因為大多數雲服務商支援隨時升降配:擴容幾秒生效,縮容按比例退費,猜錯的成本很低。
別跳過區域這一步。 區域決定了延遲、合規要求和備份位置,而且事後遷移要換 IP、重做解析、下游證書全部重籤——是所有決策裡最難撤回的一個。價格差異在 20% 量級時,延遲帶來的轉化損失往往更大。
第二步:建立實例,映象、金鑰與安全組一次配對
各家控制檯的名字略有差別(建立實例 / 新建雲主機 / Launch instance),但要填的東西是同一組。下面三處是新手最容易漏的,填錯一項會讓你在後面某一步卡住。
- 映象:Ubuntu 24.04 LTS(x86_64)。不要選預裝寶塔 / 1Panel 之類的第三方面板映象,也不要選來源不明的 Marketplace 映象——後面所有命令都按官方映象寫
- 規格:2 核 2G + 40GB 系統盤,儲存型別選 SSD / 高效能雲盤。計費方式先按量,測試完再轉包月
- 登入憑據:在控制檯現場生成一對 SSH 金鑰(演算法選 ed25519),或選「已有金鑰」後貼上自己的公鑰。能在文件裡看到
ubuntu使用者,就說明這是標準雲映象 - 網路:繫結一個彈性公網 IP;安全組只放行三條規則——
22埠來源填你自己的公網 IP(不要填 0.0.0.0/0),80與443埠來源 0.0.0.0/0 - 收尾:實例命名成能認出來的名字(如
first-web-01),並確認自動續費是否開啟——純測試的機器到期就釋放,別讓它一直計費
私鑰是私有的,別貼進任何線上工具、截圖或聊天視窗。 控制檯生成的私鑰通常只完整展示一次,下載到本地後立刻收緊許可權:
chmod 600 ~/Downloads/你的金鑰檔案.pem
許可權比 600 寬鬆(比如 644),OpenSSH 會直接拒絕使用這把金鑰,報 UNPROTECTED PRIVATE KEY FILE。
在控制檯裡查到這臺機器的公網 IP 並記下來。下面用 203.0.113.10 指代它,實際執行時換成你自己的 IP,或者直接用之後繫結的域名。
第三步:第一次 SSH 登入
在你自己的電腦上執行(不是伺服器上):
ssh -i ~/Downloads/你的金鑰檔案.pem [email protected]
第一次連線會問 Are you sure you want to continue connecting (yes/no)?——這是首次連線在建立主機指紋,確認 IP 沒輸錯後輸入 yes。成功後你會看到類似 ubuntu@first-web-01:~$ 的提示符。
如果報 Permission denied (publickey),按順序查三件事:① 使用者名稱是 ubuntu 而不是 root(官方雲映象預設禁 root 直登);② -i 指向的是私鑰,沒有 .pub 字尾;③ 建立實例時繫結的公鑰,和你手上這把確實是同一對。
另外注意安全組:如果 22 埠只放行了你家網路的公網 IP,而你的出口 IP 變了(換 WiFi、VPN、公司網路),就會連不上。查自己的公網 IP 用 curl ifconfig.me。
進去之後先花 30 秒確認環境,別急著裝東西:
cat /etc/os-release | head -n 3
whoami
ip -br addr
curl -sI http://ifconfig.me
whoami 應輸出 ubuntu;ip -br addr 裡能看到那塊公網網絡卡;最後一條用來確認這臺機器的出口 IP,方便你在安全組裡放行 22 時填對來源。
再給 ~/.ssh/config 加一段,以後一個 ssh web 就能直連,不用記長命令:
Host web
HostName 203.0.113.10
User ubuntu
IdentityFile ~/Downloads/你的金鑰檔案.pem
寫完直接 ssh web 驗證。這段配置就是後面加 deploy 使用者、加新機器時唯一需要複製的東西。把 ubuntu 當成你唯一的日常入口。 需要 root 的命令一律加 sudo,許可權邊界清晰、審計也乾淨。萬一後面要建獨立的 deploy 使用者,直接把這份入口公鑰複製過去就行。
第四步:最小加固:ufw 與系統更新
雲安全組是第一道牆(流量到主機前就被丟棄),主機內的 ufw 是第二道牆。兩道牆都留著,成本幾乎為零。 順序有講究:先放行 22,再啟用預設拒絕。這一步只做最小可用;正式對外服務前該補的另外 8 項,見 雲伺服器安全基線清單。
sudo ufw default deny incoming
sudo ufw allow 22/tcp
sudo ufw allow 80,443/tcp
sudo ufw enable
sudo ufw status verbose
ufw allow 22/tcp 必須在 ufw enable 之前。 順序反了會當場踢掉你當前的 SSH 會話。真被踢出去也不要慌:雲廠商一般提供 VNC / 串列埠救援控制檯,進去 sudo ufw disable 修好安全組再重開就行。
另一條同樣重要:ufw 生效後不要順手關掉雲安全組的 22 埠——兩道牆要同時是通的才連得上。
接著把系統補丁、時區和自動更新一次性處理掉。
sudo apt-get update && sudo apt-get -y upgrade
sudo timedatectl set-timezone Asia/Shanghai
timedatectl
最後一條會打出本地時間與 NTP 同步狀態。時間不對會讓日誌時間線、證書有效期校驗、cron 定時任務全部錯亂,值得多花這 30 秒。
新裝的機器通常欠幾十個安全補丁,再開啟自動更新:
sudo apt-get install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
把當前使用者加進 docker 組能省掉成千上萬次 sudo,但先知道代價。 sudo usermod -aG docker $USER 之後 docker 命令不再需要 sudo——而能操作 Docker 就等於能以 root 身份做任何事。個人專案圖省事完全可以接受;多人共用的機器請老老實實寫 sudo docker。
第五步:裝 Docker,走官方倉庫
生產機器建議走官方 APT 倉庫:版本新,且能被系統包管理器正常升級。便利指令碼 get.docker.com 適合一次性實驗環境,裝出來的版本不受 apt 管理,以後升級容易出岔子。
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
第四行是匯入 GPG 公鑰,第五到七行是新增倉庫源——$(. /etc/os-release && echo "$VERSION_CODENAME") 會自動取到當前系統代號(24.04 是 noble),所以這段命令換版本也照樣能用。裝完啟動並自檢,這是整條鏈路上第一個真正的「做完了」標誌:
sudo systemctl enable --now docker
systemctl is-active docker
docker compose version
sudo docker run --rm hello-world
systemctl is-active docker 期望輸出 active;docker compose version 期望輸出 Docker Compose version v2.x(v2 才是 docker compose 這種寫法);最後一條會拉一個不到 30MB 的映象並列印歡迎資訊,看到 Hello from Docker! 就說明映象倉庫、容器執行時、網路全都正常。報 permission denied while trying to connect to the Docker daemon socket? 說明當前使用者還沒進 docker 組。執行 sudo usermod -aG docker $USER 後必須退出 SSH 重新登入才生效(組資訊在登入時載入),用 groups | tr " " "\n" | grep docker 確認。
第六步:用 Compose 部署第一個應用
現在把第一個應用放上去。用 Compose 的好處是以後換應用只改一個 YAML 檔案,不用記 docker run 的一長串引數,也不用自己記容器名。
mkdir -p ~/site/nginx && cd ~/site
cat > nginx/index.html <<'EOF'
<!doctype html><meta charset=\"utf-8\"><title>it works</title>
<h1>第一臺雲伺服器,跑起來了</h1>
EOF
cat > nginx/default.conf <<'EOF'
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / { try_files $uri $uri/ =404; }
}
EOF
cat > compose.yaml <<'EOF'
services:
app:
image: nginx:1.27-alpine
restart: unless-stopped
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./nginx:/usr/share/nginx/html:ro
ports:
- \"80:80\"
EOF
最後那個 nginx:1.27-alpine 是官方精簡映象,幾十 MB 起步快。restart: unless-stopped 讓它隨開機自啟,容器意外退出也會被拉起。
啟動與驗收:怎麼確認容器真的跑起來了
啟動並驗收:
cd ~/site && docker compose up -d
docker compose ps
curl -I http://127.0.0.1
docker compose ps 裡 app 狀態是 Up;curl -I 返回 HTTP/1.1 200 OK 和 Server: nginx/1.27.x。要跟日誌用 docker compose logs -f app,改配置後用 docker compose restart app 生效(只改靜態檔案不用重啟,掛載的是目錄,重新整理瀏覽器就夠)。
如果 docker compose ps 顯示 Exit (1),用 docker compose logs app 看真實原因,九成是 default.conf 語法錯誤——先 docker compose logs --tail 20 app 再動手改。image: 和 build: 的區別先分清:拉現成映象寫 image: nginx:1.27-alpine;自己有 Dockerfile 寫 build: ./app(第一次要加 --build 才會構建);兩個都寫則構建並按 image 命名產物。部署自己的應用時,把 image: 換成 build: ./app,其餘流程一字不改。
看到 200 OK 的這一刻,伺服器已經是一個能對外提供服務的網站了——只是還沒人知道它的地址。下一步解決「別人怎麼找到它」。
第七步:域名解析,兩條記錄搞定
把域名的 A 記錄指向伺服器公網 IP。多數控制檯在「網站 / DNS / 域名解析」裡操作,新增記錄時填三項:主機記錄、記錄型別、記錄值。
| 主機記錄 | 記錄型別 | 記錄值 | 用途 |
|---|---|---|---|
| @ | A | 203.0.113.10 | 裸域 example.com |
| www | CNAME | @ | www.example.com 跟隨裸域 |
儲存後等解析生效。全球 TTL 生效通常幾分鐘,本地快取最久要等一個原 TTL 週期(常見 600 秒)。這段時間不要反覆改配置,越改越慢。
dig +short example.com
dig +short example.com @1.1.1.1
curl -I http://example.com
dig +short 直接輸出 203.0.113.10 就說明已生效;curl 返回 200 說明流量真的到了你的 Nginx。dig @1.1.1.1 是繞開本地 DNS 快取直接問公共解析,排查「我這邊不通但別人能通」時特別有用。
如果你用了 CDN,先把代理開關關掉(灰色小雲朵 / DNS only)。下一步的 HTTP-01 證書驗證需要請求直達源站,代理開著有時會卡住驗證;證書簽發成功後再開啟代理。第八步:上 HTTPS,讓 Caddy 自動簽證書
Caddy 的價值在於把證書變成零維護:自己申請、自己續期、到期前自動更換,回應用 Nginx + certbot 也能做到,但需要你記得手動 renew 並 reload。下面用 Caddy,主打省心。
做法是讓 Caddy 接管 80/443 埠再反代到 Nginx,Nginx 則改為只在 Docker 內網可達。覆蓋 ~/site/compose.yaml:
cat > ~/site/compose.yaml <<'EOF'
services:
app:
image: nginx:1.27-alpine
restart: unless-stopped
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./nginx:/usr/share/nginx/html:ro
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
EOF
cat > ~/site/Caddyfile <<'EOF'
example.com, www.example.com {
reverse_proxy app:80
}
EOF
cd ~/site && docker compose up -d
注意 app 上的 ports: 已經整段刪掉了——它不再直接對外,只透過 Docker 內網被 Caddy 訪問。Caddyfile 裡的 app:80 是 Compose 服務名,不要寫成 127.0.0.1:80,那樣 Caddy 容器會去找它自己,永遠 502。Caddy 啟動時會自動讀取這個檔案、發現域名並立刻去申請證書。
HTTPS 證書怎麼簽發與續期,以及 certbot 備選方案
證書這一步有三件事最值得先知道:證書被存在哪裡、簽發成功時日誌長什麼樣、以及不想用 Caddy 時的等價做法。把這三點看懂,證書問題基本就能自己排掉。
caddy_data 這個卷是證書的存放位置,別省。 沒有它,每次 docker compose down 都會讓 Caddy 重新申請證書,很快撞上 Let's Encrypt 的速率限制(同一組域名每週 5 次),然後你會看到一堆 too many certificates already issued for this exact set of domains。真撞上了只能等一週,或用測試環境證書臨時頂一下。
docker compose logs -f caddy | grep -iE 'certificate|error'
看到 certificate obtained successfully 就成功了,首次簽發通常 5–20 秒。HTTP 會自動 301 跳到 HTTPS,這是 Caddy 的預設行為,不用額外配置。簽發失敗最常見的原因是域名還沒解析到這臺機器(dig 沒返回 IP),或者安全組 / ufw 沒放行 80。
證書續期由 Caddy 自己在到期前完成,不需要 cron。
想用 Nginx + certbot 的話,等價路徑是:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
互動裡選 Nginx 配置中的 1,certbot 會自動加上 443 監聽和跳轉。續期由 systemd timer 負責,第一次務必先幹跑一次確認:sudo certbot renew --dry-run。這條路徑要多背兩個概念(證書鏈 + 定時續期),所以本文預設走 Caddy。
驗收清單:怎麼確認真的上線了
別憑感覺判斷「應該成功了」,逐條跑一遍。任何一條不通,就回到對應章節修,不要往下走——很多「HTTPS 配好了但打不開」其實是第 8 條防火牆的問題。
| # | 檢查項 | 命令 | 期望結果 |
|---|---|---|---|
| 1 | 本機服務活著 | curl -I http://127.0.0.1 | 200 OK |
| 2 | 容器都在跑 | docker compose ps | app 與 caddy 均為 Up |
| 3 | 埠在監聽 | ss -tlnp | grep -E ':(80|443)' | 兩個埠都有 docker-proxy |
| 4 | 域名已解析 | dig +short example.com | 輸出伺服器公網 IP |
| 5 | HTTPS 可用 | curl -I https://example.com | 200 OK |
| 6 | HTTP 跳 HTTPS | curl -I http://example.com | 301,Location 是 https |
| 7 | 證書在有效期內 | echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates | notBefore 在過去、notAfter 在未來 |
| 8 | 防火牆沒擋住 | sudo ufw status verbose | 22 / 80 / 443 均為 ALLOW |
最後在真實瀏覽器裡開啟 https://example.com 一次——瀏覽器比 curl 更嚴格,它會額外校驗證書鏈、SNI 和混合內容。這一步透過,你的第一臺雲伺服器就算正式上線了。
怎麼做到「下次重來只要 5 分鐘」:把 ~/site 裡的 compose.yaml、Caddyfile、nginx/ 提交進一個 Git 倉庫。重建機器時 git clone + docker compose up -d,配置一行都不用重寫。可復現的部署本身就是最好的備份。
上線之後:備份、監控與新手最常踩的坑
- 備份:給系統盤開定時快照(每天一次、保留 7 天)。快照是雲廠商側操作、不額外佔你的磁碟,但它不等於資料備份——資料庫要自己匯出並放到另一處
- 監控:裝一個 Uptime Kuma 之類的探活工具,從外部每分鐘撥一次你的域名,掛了立刻收到通知。沒有外部探活,伺服器半夜掛掉你只能等使用者投訴才知道
- 日誌輪轉:
docker compose logs不會自動輪轉,長期跑要在daemon.json裡設log-opts.max-size與max-file,否則單個日誌檔案能把 40GB 系統盤寫滿 - 憑證不進 Git:私鑰和
.env一旦進了倉庫(哪怕後來刪掉)就按已洩露處理,要輪換而不是隻刪檔案
新手最常踩的四個坑:① 安全組只放了 22 忘了放 80/443,本機 curl 正常但外網打不開;② 域名解析指向了內網 IP 或換機前的舊 IP;③ ufw 先 enable 後放行 22,把自己鎖在門外;④ caddy_data 卷沒掛,證書反覆重籤觸發速率限制。前三個兩分鐘內能定位,第四個最費時間。
如果你卡在任意一步,別反覆重試——把報錯原文、加上 docker compose ps 和 docker compose logs --tail 50 的輸出、以及你執行到第幾步,一併發給我們的工程師,我們陪你一起看。還沒下單、想讓工程師先幫你確認區域和規格再買的,也可以先來問一輪:第一臺伺服器選錯的成本,比多花半小時高得多。