在FreeBSD上使用Docker

猛禽大叔發表於2018-10-09

需求

FreeBSD是個好東西,因為有ZFS。Docker也是個好東西,因為很爽。

然而之前Docker只支援Linux,所以在其它平臺上都需要搞個Linux虛擬機器才能用,麻煩得很。

當然現在也是一樣,只是官方出了一個docker-machine可以更方便地管理虛擬機器裡的docker。基本用法可以參考這篇《Docker on FreeBSD

不過為了折騰這個東西,我把家裡的伺服器搞崩潰好多次,最後甚至不得不重灌一遍……前前後後折騰了快一個月。

現在把這個血淚教訓總結成本文。

準備環境

docker-machine依賴虛擬機器環境,這裡以最常用的VirtualBox為例。

我的伺服器上本來就跑著VBox,所以當時就直接拿來用了,結果可恥滴失敗了。

首先是需要系統版本:FreeBSD 11以上才提供了docker-machine,所以必須先把我的10升級一下。升級方法以前說過(見《FreeBSD升級失敗的處理》),這裡從略。

升級完成之後還是不能用,建立新machine的時候各種報錯,比如:

Error creating machine: Error in driver during machine creation: Unable to start the VM: /usr/local/bin/VBoxManage startvm dockerhost --type headless failed:
VBoxManage: error: The VMMR0.r0 module version does not match VBoxVMM.dll/so/dylib. If you just upgraded VirtualBox, please terminate all VMs and make sure th
at neither VBoxNetDHCP nor VBoxNetNAT is running. Then try again. If this error persists, try re-installing VirtualBox. (VERR_VMM_R0_VERSION_MISMATCH)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component ConsoleWrap, interface IConsole

Details: 00:00:00.488143 Power up failed (vrc=VERR_VMM_R0_VERSION_MISMATCH, rc=NS_ERROR_FAILURE (0X80004005))
複製程式碼

看上去是某些驅動或服務沒有正常工作。於是參考VirtualBox文件,把vboxdrv和vboxnet都啟用,然後重啟……恭喜,系統崩潰了……

查了很久也沒查出原因,我甚至另外搞了一臺電腦安裝了FreeBSD11重試,還是一樣的問題。

只要下面任意一個命令執行就崩潰:

service vboxnet onestart
kldload vboxdrv.ko
複製程式碼

搜了很久也沒找到原因,搞了好幾天,直到今天搜到有人說了一句:可能跟系統不完全相容。我靈光一閃——對了,我的VBox是通過pkgng安裝的,有可能不相容。於是果斷換成多年不用的ports:

portsnap fetch
portsnap extra  # 或update,如果已經安裝了ports的話
cd /usr/ports/emulators/virtualbox-ose
make config
make
make install clean
複製程式碼

然而仍然沒有那麼順利,因為舊版的還在……

pkg delete virtualbox-ose
複製程式碼

刪除後再編譯,仍然會有一些衝突的依賴包,全部刪除掉改用ports的版本。VBox這東西依賴還是相當多的,斷斷續續編譯了兩天才算完成。最後還編譯安裝了一把virtualbox-ose-kmod

為了保險起見,docker-machinedocker-compose我也是用ports的版本。

需要注意的是,如果你想用非root使用者操作的話,需要先允許這個使用者操作虛擬機器:

pw groupmod vboxusers -m yourname
複製程式碼

使用者需要重新登入一下,如果用了screen或tmux之類的,也需要新開會話(不是新開視窗)才會生效。

另外,為了充分利用ZFS,建立一個ZFS供machine使用:

zfs create -o mountpoint=/home/yourname/.docker tank/docker
複製程式碼

這樣建立的虛擬機器就會在tank/docker這個ZFS裡了。

docker-machine

重點來了,為了使用docker,先得建立一個machine,這就需要使用前面安裝的docker-machine了:

docker-machine create --driver virtualbox \
    --virtualbox-memory 2048 \
    --virtualbox-cpu-count 1 \
    --virtualbox-disk-size 204800 \
    dockerhost
複製程式碼

上面的命令建立了一個叫做dockerhost的虛擬機器,記憶體2G,CPU一顆,硬碟200G,並且自動執行起來。

然後就可以對這個machine進行一系列操作了。

docker-machine ls
docker-machine stop dockerhost  # 停止虛擬機器
docker-machine start dockerhost  # 啟動虛擬機器
docker-machine rm dockerhost  # 刪除虛擬機器
複製程式碼

成功建立或啟動一個machine之後,就可以操作docker了,不過操作之前需要設定一下環境:

eval `docker-machine env dockerhost`
複製程式碼

主要是就是設定幾個環境變數給docker使用。

如果使用root使用者,需要注意的是:

root使用者的預設shell是csh,並不支援這個命令,必須使用bash。

其它使用者如果也是用csh,也要注意這一點。

docker

現在終於可以開始使用docker了:

docker images
docker ps
docker run helloworld
複製程式碼

大功告成!

但是還沒完,docker-machine裡的檔案路徑是對映過的,所以現在試試這個是不會成功的:

docker run -it --rm -v /home/yourname:/var/workdir alpine /bin/sh
# cd /var/workdir
# touch test
# exit
> cd /home/yourname
> ls test  # 並沒有這個檔案
複製程式碼

因為-v對映的路徑不正確,必須使用在machine裡對映過的路徑。預設的對映路徑是:

share => /home
複製程式碼

所以上面那個測試可以改為:

docker run -it --rm -v /share/yourname:/var/workdir alpine /bin/sh
複製程式碼

這樣再做上面的測試就可以成功了。

當然那個預設對映可以自己在VirtualBox裡修改,或者在建立docker-machine的時候指定。

相關文章