最近文章

Raspberry Pi 筆記(三十九):使用 Docker 執行 python 的 gpio 控制 LED 燈

[2017/04/03]
由於硬體的發展迅速,如果在一部伺服主機上只安裝一套作業系統,會有點浪費資源。如果在該伺服主機的作業系統上再建立虛擬化主機,就可以充分應用硬體資源。常見的虛擬化系統,如VMWare、Hyper-V等都是虛擬化的應用。

安裝虛擬化系統之後,要啟動每個虛擬主機,需要分別安裝作業系統,分別執行不同的應用程式。這樣一來,每個虛擬化系統都會重複安裝作業系統,不僅浪費硬碟空間外,在效能上也是大打折扣。

Docker的技術,就是為了解決重複存放的作業系統及提升效能而產生的一種技術,將作業系統從每個虛擬化抽離出來,分別使用容器放置所需執行的服務或程式。

Docker在這幾年成為非常熱門的技術,到底跟虛擬化有什麼不同,以下圖表可瞭解兩者之間的差異:

圖片來源:Docker

Containers 跟 Virtual Machines兩者最明顯的差異是,虛擬機需要安裝作業系統 (Guest OS) 才能執行應用程式,而 Container 不需要安裝作業系統就能執行應用程式。Container 的技術透過共用 Host OS 的作法,取代虛擬化的 Guest OS,讓所需的硬碟空間小,執行的速度也比虛擬機快速。

要學習 Docker ,有三個重要的名稱一定要瞭解,包括:Image、Container及Repository。

• 映像檔(Image):就是一個唯讀的模板。Docker 執行容器前需要本地存在對應的映像檔,如果映像檔不存在本地,Docker 會從映像檔倉庫下載。

• 容器(Container):容器是獨立執行的一個或一組應用,以及它們的執行態環境,對應到虛擬機,類比執行一整套作業系統。Docker 的容器是從映像檔建立的執行實例,它可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平台。

• 倉庫(Repository):是集中存放映像檔檔案的場所。倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式。官方提供 Docker Hub 作為映像檔登錄及註冊(Registry),這是類似 Github 程式碼儲存服務。一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標籤(Tag);每個標籤對應一個映像檔。

[安裝Docker]

安裝Docker 很簡單,只要一行指令就可完成:
$ curl -sSL https://get.docker.com | sh
安裝完成的畫面:

安裝完成後,要將使用者 pi 加到 docker 群組:
$ sudo usermod -aG docker pi

• 開機時,自動執行 Docker:
$ sudo systemctl enable docker

• 重新開機後,手動執行 Docker daemon:
$ sudo systemctl start docker

$ sudo /etc/init.d/docker start

[Docker 指令]

• 搜尋 Docker Hub上可用的映像檔:
$ sudo docker search armhf

• 查詢 Docker上可用的映像檔:
$ sudo docker images

• 從倉庫取得所需要的映像檔。
$ sudo docker pull resin/rpi-raspbian

• 執行安裝映像檔
$ sudo docker run -ti resin/rpi-raspbian
-i 開啟標準輸出入(STDIN)
-t 配置一個虛擬終端機

• 移除本地端映像檔
$ sudo docker rmi -f resin/rpi-raspbian
  ** 注意 docker rm 命令是移除容器。

[在Docker 使用 gpio 控制 LED 燈]

先依照下圖,連接 LED 的兩隻接腳到 Pi的 Pin 9 跟 Pin 11。

[方法一]

(1) 先下載 hypriot/rpi-gpio 映像檔到容器內
$ sudo docker pull hypriot/rpi-gpio

(2) 確認一下gpio 是否正常被執行
$ sudo docker run --rm --cap-add SYS_RAWIO --device /dev/mem hypriot/rpi-gpio readall

(3) 設定 GPIO 0 為輸出 (上圖紅色框)
$ sudo docker run --rm --cap-add SYS_RAWIO --device /dev/mem hypriot/rpi-gpio mode 0 out

(4) 設定 GPIO 0,點亮 LED 燈
$ sudo docker run --rm --cap-add SYS_RAWIO --device /dev/mem hypriot/rpi-gpio write 0 on

(5) 設定 GPIO 0,讓 LED 燈熄滅
$ sudo docker run --rm --cap-add SYS_RAWIO --device /dev/mem hypriot/rpi-gpio write 0 off

[方法二]

使用 resin/rpi-raspbian的映像檔,安裝完成 python 及 gpio等程式後,再建立一個新的映像檔,再將閃爍 Led 的 Python 程式,包在另一個映像檔中執行。

(1) 在Docker中建立一個映像檔,需先建立一個目錄,在該目錄下建立一個檔名為 Dockerfile 的文字檔
$ mkdir gpio
$ cd gpio
$ nano Dockerfile

(2) 輸入文字檔內容:
FROM resin/rpi-raspbian:latest  
ENTRYPOINT []

RUN apt-get -q update && \  
    apt-get -qy install python python-pip \
        python-dev python-rpi.gpio
上述意義是要以 resin/rpi-raspbian 最後版本作為進入點,再繼續執行系統更新、安裝 python、python-rpi.gpio 等程式。

(3) 執行 Dockerfile 的安裝程式後,建立新的映像檔 gpio-test:
$ sudo docker build -t gpio-test .

(4) 編輯一個名為 led.py 的 Python 程式:
import RPi.GPIO as GPIO  
import time  
GPIO.setmode(GPIO.BCM)  
led_pin = 17  
GPIO.setup(led_pin, GPIO.OUT)

while(True):  
    GPIO.output(led_pin, GPIO.HIGH)
    time.sleep(1)
    GPIO.output(led_pin, GPIO.LOW)
    time.sleep(1)

(5) 再將 Dockerfile 的內容修改為:
FROM gpio-test:latest  
ADD ./led.py ./led.py

CMD ["python", "led.py"]

(6)再次執行 build,建立一個名為 blink 的映像檔:
$ sudo docker build -t blink .

(7) 執行 led.py 程式,給予 root 的權限:
$ docker run --privileged blink

此時,會看到 Led燈,每格一秒閃爍一次。

↺ 回到 Arduino & Raspberry pi 筆記目錄 ↺ 

[參考資料]

• GitBook / philipzheng:Docker -- 從入門到實踐
• Explosive stuff:Getting started with Docker on your Raspberry Pi
                               Let's get physical with Docker on the Raspberry Pi
• Alex Ellis Blog:Get Started with Docker on Raspberry Pi

沒有留言