前言
雖然 Swift 支援的系統比先前多,但很多 GNU/Linux 發行版都沒有官方的 Swift 開發環境。由於編譯 Swift 的過程相當複雜,官方的說明文件也不友善,自行編譯幾乎不可行。
為了要在非官方支援的 GNU/Linux 發行版上編譯和執行 Swift 程式,使用 Docker 是相對簡單且可行的方式。本文介紹使用 Docker 建置 Swift 開發環境的過程。
從命令列直接執行 Docker 容器
在動工前,本節先簡要地說明在命令列上直接執行 Docker 容器的方式。
使用 docker run
指令即可直接執行 Docker 容器,其虛擬指令如下:
$ sudo docker run image command
在這個虛擬指令中,image
是系統上已安裝的 Docker 映像檔,command
是要在 Docker 容器中執行的 GNU/Linux 指令。
但 docker run
指令只能執行單行 GNU/Linux 指令。因應這項限制,我們改用 /bin/sh -c "..."
的方式來執行指令:
$ sudo docker run image /bin/sh -c "..."
把實際要執行的指令以字串的型態寫在 "..."
內即可。這時候就可以寫入多行指令,指令間以 ;
隔開即可。
此外,我們要將程式碼拷貝到 Docker 容器中,該容器中的 Swift 編譯器才能讀得到程式碼。處理方式是將本地端的特定資料夾掛載 (mounting) 到 Docker 映像檔中:
$ sudo docker run -w /app -v `pwd`:/app run image /bin/sh -c "..."
-w
參數是在 Docker 容器中新增工作目錄。-v
參數用來指定要掛載的目錄。-v
參數的格式是 src:dest
,其中 src
是本地端的目錄,而 dest
是 Docker 容器內相對應的目錄。
在這裡用 pwd(1)
指令動態地將當前工作目錄掛載到 Docker 容器中,不論工作目錄在那裡,都不需要另外指定程式碼的位置。
前置作業
要先安裝 Docker 才能進行後續的步驟。Docker 是蠻知名的軟體,大部分 GNU/Linux 發行版都有預編好的執行檔。以 openSUSE 為例:
$ sudo zypper install docker
安裝好 Docker 後,要啟動 Docker 服務:
$ sudo systemctl start docker
如果很常用 Docker 的話,可自行將 Docker 服務加入開機啟動項目中。
下載 Swift 官方 Docker 映像檔
使用以下指令下載 Swift 官方映像檔:
$ sudo docker pull swift:5.3
由於此官方映像檔已有完整的 Swift 編譯器,不需要在 Docker 映像檔中再額外安裝其他軟體。
將執行 Docker 的指令包成 Shell 命令稿
執行 Docker 容器的指令比較複雜,每次都手動輸入不太經濟,所以我們將其包成 shell 命令稿 $HOME/bin/swift :
#!/bin/sh
input=$1
if ! [ -f $input ];
then
sudo docker run --rm --cap-drop=all swift:5.3 /bin/sh -c "swift $@"
exit $?
fi
sudo docker run --rm -w /app --cap-drop=all -v `pwd`:/app swift:5.3 /bin/sh -c \
"cp /app/$input /tmp; cd /tmp; swift $@"
這個指令會把程式碼傳入 Docker 容器中,並以該容器的 swift(1)
指令直接編譯及執行程式碼。
由於 swift(1)
在編譯及執行 Swift 程式的過程中會產生一些暫存檔,在 /tmp 目錄執行指令就不需要考慮權限的問題,是最簡單的方式。
將該命令稿加上可執行權限:
$ chmod +x ~/bin/swift
寫一個簡單的 Swift 程式來測試一下開發環境:
print("Hello World")
的確可順利地編譯和執行 Swift 程式:
$ swift hello.swift
Hello World
執行 Docker 容器時省略輸入密碼的過程
由於 Docker 需要 root 權限,使用 sudo(1)
輸入 Docker 指令時系統會多次詢問密碼。為了簡化輸入密碼的過程,可設置 sudo(1)
的權限:
$ sudo visudo
加入以下這行:
user ALL=(ALL) NOPASSWD: /usr/bin/docker
請將 user
換成實際的系統使用者帳號。我們只要快速地執行 Docker 容器,所以不開放其他的指令。
注意事項
本文所提供的 shell 命令稿以內部使用為主。由於此命令稿未考慮使用 Docker 的安全事項,勿將此命令稿用於對外公開的服務程式。
本方案的限制
本文所使用的 shell 命令稿只能執行單一 Swift 程式碼,而且該 Swift 程式也無法讀入外部檔案。如果需要其他的應用情境,請自行修改此命令稿。
對於有多個檔案的 Swift 專案來說,另外寫 Dockerfile 是比較好的選擇。限於篇幅,不在本文說明撰寫 Dockerfile 的方式。