搜尋此網誌

2024年7月21日 星期日

Raspberry pi 安裝 docker,執行 dotnet web 程式

緣起:


    假日學 dotnet core 學到無聊,轉去學 docker,想試試看能不能在 pi 上面跑個 dotnet core的 container,跑起來感覺會很酷。


Raspberry pi 安裝 docker:


    搜尋 raspberry pi docker 就能找到 docker 官方的教學文件,不過我的是 pi 5, 它的 Raspbian 是 64 位元的作頁系統,所以要看的是在Debian上的安裝教學

    複製指令跟著下就行了,沒碰上什麼問題

    先把 pi 上舊版的 docker 相關套件給移除,不然會有衝突。我的 pi 之前沒有裝過 docker,所以指令執行完後,它跟我說 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded。

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

    然後下這些指令,安裝 curl 跟 ca-certificates,pi 上是都有了。後面的那些指令是跟憑證的處理有關

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

    那個 install 一開始看還以為是跟安裝什麼之類的有關,後來去查才發現,原來是複製檔案的功能。

    再來是這個指令,設定 docker apt repository

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

    最後下指令安裝,會佔去 300 多 MB 的容量。


sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    最後跑個 sudo docker run hellow-world,如果能看到 container 輸出的 hello world 訊息的話,就代表成功了。


    安裝過程使用的那些指令都蠻值得研究的,有時間會再看看。


加入 docker 群組:


    docker 一開始裝好後,要使用它的指令都要 sudo,蠻麻煩的,所以去找了教學,把自己這個使用者加入 docker 群組後,就可以用 docker 的指令不需要 sudo 了。


新增 dotnet core web 專案並打包成 docker image:


    這是在我 ubuntu 筆電上操作的,看這篇文章跟著做的。新增一個 web 專案

dotnet new web -o DockerTest

    用 vs code 開啟資料㚒,然後複製它的 Program.cs 程式,再來修改 DockerTest.csproj 檔,把 <TargetFrameWork> 區塊改成 net8.0 (我 ubuntu 上安裝的版本),然後用 dotnet run 測試程式可以跑後,接著處理 Dockerfile 的部份。話說我發現那個 logs.txt 檔是産在 {專案根目錄}/logs.txt,原來用 WebApplication 的 Environment.ContentRootPath 取得的路徑是這樣。

    新增一個 Dockerfile,然後輸入内容

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /app

# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "DockerTest.dll"]

    再來 build image,建出一個叫 birdshiu-dockertest 的 image

docker build -t birdshiu-dockertest -f Dockerfile .

    

    用 docker images 可以查看建好的 image


    然後用 docker run 來執行 container

docker run -d --name birdshiutest -p 8080:5007 birdshiu-dockertest:latest

    可以用 docker ps 來列出現在在跑的 container。我在我瀏覽器輸入 localhost:8080,原本期待能看到頁面,但看到的卻是瀏覧器的 network reset 錯誤頁,所以就開始找錯誤。找錯誤時有學到 docker stop {container名稱} => 停止 container,docker rm {container名稱} => 移除 container,container 要先停止後才能被移除,在這邊還有學到怎麼移除所有的 container。如果是想要重啟停止的 container 的話,可以下 docker restart {container名稱}。

    我最後是發現,原來是 appsetting.json 沒有設定, 所以 published 的專案在執行時預設是使用 8080 port,我被 launchSettings.json 給誤導了。


    所以要去修改專案的 appsettings.json,我在這篇找到解法,加上 Kestrel 的區段,指定 port 為 5002。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://0.0.0.0:5002"
      }
    }
  }
}

    再來重新 build image,由於我是用一樣的 tag name,所以會産生 dangling image


    可以下 docker image prune 來移除它。如果有 container 是依照那個 image 建出來的話,image 會刪不掉,可以先把 container 刪除後再下 docker image prune,這樣就能成功刪除了。

    後面我再接著測試重産的 image,run 起來後確認是可以正常運作。


image 的匯出與匯入:


    再來要把建好的 image 給放到 raspberry pi 上。看這個文章跟著操作的,把 image 弄成 tar 檔,放到桌面

docker save birdshiu-dockertest > ~/Desktop/birdshiu-dockertest.tar

    

     然後用 scp 把這個 tar 給複製到我 raspberry pi 的 Desktop

scp ~/Desktop/birdshiu-dockertest.tar birdshiu@{pi的local ip}:/home/birdshiu/Desktop

    檔案傳好後,來到 pi 那邊,移置 Desktop 開啟 terminal,下

docker load < birdshiu-dockertest.tar

    等它處理好後,用 docker images 查看我們匯入的 image。我確定 images 有 load 進來後,再下 docker run 的指令,發現它有錯

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm/v8) and no specific platform was requested
exec /usr/bin/dotnet: exec format error

    hmmmm.....,好像也是吼, pi 是 arm,我筆電是 x86。所以就換個做法,先用 scp 把整個專案搬到 pi 那邊,搬完後再下 docker build 的指令來建 image。花了不少時間,大部份的時間是在載 https://mcr.microsoft.com/dotnet/sdk:8.0。

    再次跑 docker run ,可以成功執行,而且在瀏覽器輸入 localhost:8080 也能成功看到頁面,讚哦。



進入 container 的 shell:


    在這篇文章學到,可以用 docker exec -it {container名稱} /bin/bash 來進入 docker 的 shell。我在我的 pi 再開個 terminal,下

docker exec -it birdshiutest /bin/bash

    就成功進入 container 裡,再用基本的指令查看文件内容


    如果想把東西從 container 裡複製出來的話,可以用 docker cp



沒有留言:

張貼留言