軟件工程師到運維的 Docker 初體驗

起因

對於各種凌亂的電腦問題,其它行業的人以爲程序員們什麼都會;程序員中,女程序以爲男程序員什麼都會;男程序員中,一般程序員以爲技術好的程序員什麼都會;技術好的程序員,每次都在網上苦苦搜尋答案……

我會做一點公司服務器運維方面的工作,雖然不專業,但是日常維護還是問題不大。不過有一天,代碼服務器被我搞壞了,我只是簡單地想裝個 Git 服務,然後被要求升級,然後升級過程中出現失敗,然後服務器就不能用了——不過還好,我偶然發現從啓動菜單中不帶 “Server” 的那一項啓動系統,除了 SSH 不能用之外,其它服務還能照常運行。又經過一翻嘗試之後決定放棄,免得把事情搞得更糟——現在最多就是需要操作的時候搬臺顯示器去機房,麻煩一點。

又過了一段時間,公司停電,UPS 也耗盡了最後一點能量——重啓的時候發現 Raid 卡報警,硬盤壞了。拆下來一測試,三塊硬盤壞了兩塊,差點全洗白。這事很嚴重,所以馬上買新硬盤順便重做系統,畢竟沒有 SSH 是件很不方便的事情。

目的

老實說我是真心想裝 Windows Server,但是授權問題真的很難解決。如果說用 Linux,有兩件事情讓我很躊躇,一件事就是上面提到的爲了裝 Git 更新各種庫把服務器系統搞壞;另一件事是在這之後,我專門找了一臺舊機器準備玩玩 Linux,結果裝好的第二天,對系統進行自動升級之後它就再也啓動不起來了。所以我擔心以後系統升級和擴展服務內容又會大費周章。

爲了解決這個問題,立刻能想到的就是使用虛擬化技術,虛擬機當然是玩過的,除了本身慢得要死之外,把宿主也拉來慢得要死——在遍網都在說 Docker 的年代,我當然會去了解一下,順便做做嘗試。

最後基本上就這麼決定了,安裝 Linux,配置 Raid 卡,再裝個 Docker 環境,上 Docker Hub 搜點現成的映像做成服務,似乎就已經解決了我們目前的問題……然後就開始了爲期兩週的服務搭建之旅

這兩週都在幹啥

兩週!!!對於專業運維來說,這個時間都可以進行星際旅行了,但是考慮下我的背景,16 年前使用過 Linux,那時候只是在 Linux 下用 Emacs 和 javac 進行開發;沒有運維知識棧,所知到關於運維的一切都來自 Internet 上的技術新聞,當然在軟件開發和設計過程中會有一些涉及,但涉及不深。在目標確定之後接下來要做的一切事情,都是一邊搜索一邊試驗的情況下完成的,所以兩週,似乎可以理解了。

第一週

說起來第一週算是浪費掉了,因爲我想繼續使用 Raid 卡,但又不想延用原來那個古老版本的 Linux 系統。所以先嚐試了 Ubuntu Server 16。各種搜索也沒找到驅動,本來想向 Raid 供應商提個服務單,看到一大堆要填寫的英文信息,還是放棄了。

然後換 CentOS。驅動倒是很快找到了,就是各種裝不上……

最後在朋友的朋友的提示下,決定放棄 Raid 卡,在 Linux 裏做軟 Raid,不過這時候一週已經過去了

第二週

做軟 Raid 配置的過程還算順序,基本上都是按網上的貼子一步步來。就是配置完之後一直不能用,錯誤信息現在已經不記得了,也是各種找原因,最後在 /proc/mdstat 裏發現了一個百分比,而且還是變化着的,英文看得似懂非懂,大概是在同步兩步硬盤吧。所以耐心等着這個百分比走到頭。有驚無險,可以裝 Docker 了。

裝 Docker 是很容易的,不過拉映像還是踩了些坑,大把的時間都花在找映像去了。

Docker 服務環境

當然我們要搭的服務還是有一些,不過最主要的就是 Subversion 服務、Mantis 和 Gogs,以及後面兩個都會用到的 MySQL。

一開始我是直接寫命令的,但是很快我就意識到這是個非常不靠譜的方式。Docker 命令參數那麼多,直接寫命令很容易寫錯,這都不算,大部分命令都是從網絡上來的,總還得嘗試,如果不對還需要修改……而且似乎也應該爲後期維護留下點什麼,所以開個了文件叫 INSTALL.md 來記錄每一步操作。

MySQL 服務

首先是從 MySQL 開始,這個有官方映像,所以沒什麼好選的,直接拉官方映像。

從以前的瞭解,知道 Docker 容器相對封閉,需要通過卷(volume)來指定數據在宿主中的存儲位置。這個從命令行很容易查到是 -v 參數,它會爲容器內某個目錄和宿主某個目錄建議映射關係,這兩個目錄在參數中用一個冒號來分隔,但問題是誰在左誰在右?

-v <宿主中的路徑>:<容器內的路徑>

創建容器之後,發現用 HeidiSQL 連不上,又查了半天,發現原來是沒有做端口映射。在用 -p 參數做端口映射的時候又把參數搞反了,所以又折騰了半天——好吧,其實根據 -v 參數中的順序都可以猜到這個順序

-p <映射到宿主的端口>:<容器內的端口>

MySQL 服務似乎沒有問題了,不過我很擔心重啓服務器之後容器不會自動重啓,所以決定實驗一下。

我擔心的事情出現了,MySQL 容器果然沒有重啓。於是繼續搜,發現了 --restart 參數。所以又重新創建了一次容器,加上了 --restart=always 解決問題。

好吧,現在還有最後一個問題——爲什麼創建容器之後終端會阻塞在那裏,我需要另開一個終端來進行其它操作?繼續求助於強大的搜索引擎,最後搞明白,需要在 docker run 的時候加個 -d 參數。

Mantis 服務

Mantis 服務需要 MySQL,還需要 PHP5 以上版本。在 Docker Hub 上並沒找到現成的,所以退而求其次,找了個帶 PHP 的 Apache:nimmis/apache-php7。

有了之前的經驗,這個配置起來很簡單,Mantis 很快就運行起來了,但是問題也來了。

首先就是怎麼訪問數據庫?藉助搜索引擎的力量,我找到了 --link 參數。當然還有 Docker Compose 技術,不過這個 Compose 看起來有點深奧,以後再研究吧。

--link 似乎是以類似域名解析的方式將指定的容器綁定到指定的名稱(域名),所以當前容器內部就可以通過這個名稱來訪問另一個容器了,而且另一個容器的端口是不需要映射到宿主的。當然,--link 參數的冒號左右分別是什麼這個問題也需要搞清楚,根據之前的經驗,左邊接近宿主,右邊接近容器內部,所以

--link <另一個容器名稱>:<當前容器內部可用的域名>

現在還有第二個問題,Mantis 提示需要安裝 PHP 的插件 mbstring。怎麼辦?繼續搜!最後搜出來有兩個辦法:

  1. 基於原有映像創建自己的映像,安裝 mbstring,然後使用這個新映像創建容器

  2. 直接進入容器安裝 mbstring

我選用了第二種辦法,使用 docker exec 進入容器——它居然是通過運行容器的 bash 命令來進入的,別忘了 -i -t 參數

docker exec -it httpd bash

這裏 httpd 是創建的 Apache with PHP7 容器的名稱,-it 是合併了 -i-tbash 就是執行的命令。

安裝 mbstring 的過程很順利,最後是恢復 Mantis 的數據庫,一開始是直接把 MySQL 數據庫文件拷貝過來的,很遺憾,提示找不到表。所以不能偷懶,還是老實的 mysqldump 出來再通過 mysql 命令導入。

Gogs 和 Subversion

安裝 Gogs 幾乎沒遇到什麼困難,因爲前面已經遇到並解決了所有它可能遇到的問題。

到是 Subversion 裝起來比較費事。一開始找了兩個 Subversion 的 Docker,Subversion 都是 1.8 版本,而宿主上偏偏又裝不了 1.8 版本的 Subversion,只能裝 1.9 的(我搞不懂爲什麼,也懶得去搞懂了)。這麼一來,我擔心在宿主上通過 svnadmin 創建的庫不能被容器內運行的 svn 服務兼容。如果在容器內去創建庫又比較麻煩。

原本以爲很簡單的 Subversion 卻在尋找映像這裏卡住了。最好嘗試了好久,總算找了個 Subversion Edge 的映像,Web 界面管理庫,雖然功能並不是很強大,但是簡單的管理是沒有問題了。說起來,還是很想念 Windows 下的 VirtualSVN Server。

Nginx 反向代理

Docker 服務的端口只要不映射出來,就只能內部訪問,這看起來還是增強了安全性的,然並卵,因爲不映射出來外面就不能使用這些服務。早就聽說過 Nginx 的大名,所以乾脆用 Nginx 映像來做個反向代理容器,然後以 HTTPS 協議來代理後面的 HTTP 服務。

配置都在從網上抄的,所以就不貼出來了,不過對於 SVN,後來是遇到 svn copy 總是 502 錯誤的問題,又在網上去搜索了一番,發現需要在 location 配置里加這麼一段

# 解決 svn copy 報 502 錯誤的問題set $fixedDescination $http_destination;if ($http_destination ~* ^https(.*)$) {    set $fixedDescination http$1;
}
proxy_set_header    Destination $fixedDescination;

然後又遇到提交數據過大的問題,於是又加了一項

client_max_body_size    48m;

最後完整的配置如下,基本上可以代表所有 location 的反向代理配置了

# svn server - svn
location /svn/ {    proxy_set_header    Host                $host;    proxy_set_header    X-Forwarded-Host    $host;    proxy_set_header    X-Forwarded-Server  $host;    proxy_set_header    X-Real-IP           $proxy_protocol_addr;    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;    proxy_buffering     on;    # 解決 svn copy 報 502 錯誤的問題    set $fixedDescination $http_destination;
   if ($http_destination ~* ^https(.*)$) {
       set $fixedDescination http$1;    }    proxy_set_header    Destination $fixedDescination;    proxy_pass              http://svn-server:18080/svn/;    client_max_body_size    48m; }

還是假裝總結一下吧

  1. 文檔和記錄很重要,就是前面提到的 INSTALL.md

  2. 搜索引擎很重要,如果中文搜不到就搜英文

  3. Docker 是個好東西

  4. Nginx 也是個好東西

  5. 有沒有想在成都或者綿陽找工作的運維?




與原文相比,本文略有縮減,敬請閱讀原文 ↓

本文分享自微信公衆號 - 邊城客棧(fancyidea-full)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章