# Docker好好玩 ### 幹訓特別課程|Ver. 2022 *YoMin Su* --- ## 回想一下 ---- ### 身旁有沒有朋友打手遊打到走火入魔? ---- ![](https://i.imgur.com/xVRLp9h.jpg) 13開的「天堂2革命」 ---- ### 或是拿買賣遊戲帳號當日常的朋友? ---- ![](https://i.imgur.com/7w3XCED.jpg) 為了賺小錢,連虛擬機都拿來用了 ---- ### 甚至是,在一台電腦上裝多個系統?! ---- ![](https://i.imgur.com/otejJPs.png) 這一台主機裝了7個Windows... > 單CPU 6台 8K工作站 > Ref: [YouTube](https://youtu.be/1yFQd4MaKK0), [Bilibili](https://www.bilibili.com/video/BV1jt411A78R/) ---- ### 以上皆為取自網路的真實案例 ---- ### 今天要說的Docker則是在Linux的容器 ![](https://i.imgur.com/4gwSdo4.png =500x) (虛擬機的一種) ---- ### 有沒有想過開Minecraft伺服器可以... ---- ### 從這樣 ![](https://i.imgur.com/jw9aUYm.png) ---- ### 變這樣 ![](https://i.imgur.com/m9cbnDx.png) ---- ### 你一定會問,那兩張有差嗎? 有差,當然有差,不然幹嘛提xD ---- ### 那,差在哪? 一個需要你從官網下載檔案,自己處理所有東西 另一個只需要一條指令,便將所有東西都準備好 ---- ### 除了方便架伺服器外,還能做啥? 架各種服務、各種實驗環境、服務之間各自切分、etc... --- ## 那實際上該怎麼使用呢? ---- ### 首先,你需要有Docker Engine 相信你們的電腦都準備好了,畢竟,你們的環境都已經在之前的社課讓學長姐們確認過了! (如果不是用WSL2的,就會是VM) ---- ### 如果沒有呢? ①將 WSL 1升級到 WSL 2,並安裝Docker Desktop ②裝任一Linux系統到你的筆電上 <-- 推薦!! ---- ### 良心建議 如果覺得之後還是會想玩Docker的話,建議用① 但若你有破釜沉舟的堅毅心態,決定非Linux系統不用的話,②就給它用下去吧! ---- ### 解決辦法① ```shell= wsl -l -v #找到你使用的Distro wsl --set-version <Distro> 2 #將版本修改為2 ``` > 記得安裝Docker Desktop ---- ### 解決辦法② 雖然很棒,但今天可能不太適合... ---- ### 相信各位的Docker都應該可以使用了,無論你用哪種方法,可以上課的方法,就是好方法~ --- ## 首次嘗試 ---- ### Hello-World 的部分 > docker run hello-world ---- #### 執行畫面 ![](https://i.imgur.com/caZDzET.png) ---- ### 指令分析 | 指令 | 用途 | | ----------- | ------------- | | docker | 一切的起頭 | | run | 執行一個Image | | hello-world | Image的名稱 | ---- ### 拿Minecraft伺服器當範例 若想開一個伺服器的話... > docker run > -e EULA=TRUE > -d > -p 25565:25565 > \-\-name mc > itzg/minecraft-server ---- ## 看起來是不是超複雜,超難懂? ![](https://i.imgur.com/eJvHLil.png) 一臉黑人問號...嗎? ---- ## 我們一個一個參數來解釋吧! ---- ### 「-e」參數 用於設定環境變數 > EULA=TRUE ---- ### 「-d」參數 用於讓Container執行在背景 > 就在背後跑,沒啥好說的~ ---- ### 「-p」參數 Port映射,將容器裡面的Port對到容器外面 前面是外面,後面是裡面 > 25565:25565 ---- #### 友情提醒 預設情況下,Docker會直接操作系統的iptables,因此會直接跨過ufw,若你希望服務只能在Local存取,請在Port前面加上127.0.0.1,就像範例這樣 > 127.0.0.1:25565:25565 ---- ### 「\-\-name」 幫容器取名字,方便你管理 > mc ---- ### itzg/minecraft-server 就是MC伺服器的Image之一 ![](https://i.imgur.com/IRe16rS.png) > 也就100M+人在用而已啦~ ---- ### 若你玩的是Bedrock(基岩)版的話... ![](https://i.imgur.com/bGeXb9v.png) > 好像也有Image可以用呢! ---- ### 除上述以外,「-v」參數 可以把裡面跟外面的檔案Mapping起來 路徑中間用「:」連接 > 前面是外面,後面是裡面 ---- #### 小測驗時間 > /srv/gitlab:/etc/gitlab 哪個在內?哪個在外? ---- #### (Q1)Answer Here~ > <span class=orange>/srv/gitlab</span>:<span class=bluegreen>/etc/gitlab</span> <span class=orange>橘色</span>在外,<span class=bluegreen>藍綠色</span>在內 ```json= { "score": "200", "msg": "你答對了嗎?" } ``` ---- ### 如果想在容器中執行指令的話 > docker exec -i mc rcon-cli | 指令 | 用途 | | ---- | -------------- | | exec | 執行指令 | | -i | 讓介面可以互動 | | mc | Container名稱 | | rcon-cli | 指令or功能 | --- ## Dockerfile 容器映像的起承轉合 ---- ### 用途 別人的映像很方便,我也想自己弄一個,可以嗎? > 當然可以! ---- ### 教學時間 我們來包前面設計出來的網頁吧! ```dockerfile= # Build Stage FROM node:lts-alpine as build-stage WORKDIR /app COPY . . RUN apk add make g++ \ && npm install \ && npm run build # Production Stage FROM nginx:stable-alpine as production-stage COPY --from=build-stage /app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ---- ### 快速解釋時間 | | | | ---------- | ------------------------------ | | FROM | 讓此映像建立在另一個映像上 | | WORKDIR | 容器內的預設工作目錄 | | CPOY | 將目錄內的檔案複製到映像中 | | RUN | 在映像中執行指令 | | EXPOSE | 開一個"門"讓外側可以Bind通訊埠 | | CMD | 在映像啟動後執行的指令(程式) | ---- ### 範例內容 嘿,就是你們前面在上前端課程時的成果啦! > 記得剛剛寫好的 Dockerfile > 要放在專案的根目錄喔! --- ## Docker很厲害,但有沒有方便執行的工具? ---- ### 當然有,就是Docker-Compose ![](https://i.imgur.com/nVsjp6M.png =800x) 幫你把所有設定集合起來,一次執行的好方法 ---- ### 首先提一下如何使用 ---- ### 啟動容器 > docker-compose up 加上「-f」可以指定設定檔 加上「-d」可以在背景執行 ---- ### 停止容器 > docker-compose down 若是以指定檔名的方式去啟動的話,記得一樣要指定檔名來結束 ---- ### 接下來來看內容大概長怎樣 ---- #### 範例的說 ![](https://i.imgur.com/z49neWK.png) ---- #### 還是範例的說,多個服務 ![](https://i.imgur.com/FYjX4mL.png) ---- ### 格式的部分 首先要注意的是,這是yml檔,也就是YAML格式 雖然不像Python那樣對空格極度敏感,但<span class=bluegreen>同級別的項目</span>需要在該行前面有<span class=bluegreen>相同的空格數量</span> > 父項目與子項目,建議相差2格 ---- ### 實際操作時間 拿前面自己寫好的前端 Image 當範例 我們來實際寫一下docker-compose.yml ---- ### 範例內容 ```yaml= version: "3" services: front: build: . image: yunnet-training/frontend ports: - "127.0.0.1:3000:80" ``` ---- ### 特殊情況:只要啟動其中一個 若今天只需要啟動yml中的其中一個容器,可以透過在啟動指令的最後方加上服務名稱,即可單獨啟動 > docker-compose up -d front ---- #### 額外補充 前一頁所提到「加上服務名稱」的方法,基本適用於大部分docker-compose指令。也就是說,如果今天有單一容器需要更新或是重建,可以單獨重新up該容器,就可以處理好。 --- ## Image分享 ---- ### NodeJS 執行JavaScript的好夥伴 ![](https://i.imgur.com/UuZv6vO.png =400x) > hub.docker.com/\_/node ---- ### NGINX 反向代理 or 網頁伺服器 就靠它 ![](https://i.imgur.com/g4Gcuuo.png =400x) > hub.docker.com/\_/nginx ---- ### Dockercraft 在Minecraft中管理你的容器的方法 ![](https://i.imgur.com/ayXlDid.png) > github.com/docker/dockercraft --- ## 加分時間 ---- ### Q2. YAML格式有什麼特點? 1. 對空格__,但要求__ 2. 每個項目後面都會加上__ 3. 通常父項跟子項差__個空格 ---- ### (Q2)Answer Here! 1. 對空格<span class=blue>不敏感</span>,但要求<span class=blue>同階層項目前有相同數量的空白</span> 2. 每個項目後面都會加上<span class=blue>冒號</span> 3. 通常父項跟子項差<span class=blue>2個</span>空格 ```javascript= let score = 100; console.log(`每格: {score}分`); ``` ---- ### Q3. 如果不希望Docker啟動的服務直接對外,在給參數時該怎麼寫? ---- ### (Q3)Answer Here... ```yaml= ports: - "127.0.0.1:<Host Port>:<LXC Port>" ``` ```bash= SCORE=250 echo "此題: $SCORE分" ``` ---- ### Q4. 續上題,為什麼Docker啟動的服務會無視ufw建立的防火牆條件? ---- ### (Q4)Answer Here \\\|\/ 因為Docker Engine會直接對系統的iptables進行修改,加入運作時需要的網路結構,因此ufw的設定才無法正確工作。 ```python= score = 300 print(f'你可以獲得{score}分!') ``` ---- ### 感謝你的聆聽 ![](https://i.imgur.com/PwULMqk.png =700x) <style> .orange { color: #FF8800; } .red { color: #FF0000; } .bluegreen { color: #00FFCC; } .gray { color: #272727; } .blue { color: #00E3E3 } </style>
{"metaMigratedAt":"2023-06-17T14:17:34.594Z","metaMigratedFrom":"YAML","title":"Docker好好玩","breaks":true,"slideOptions":"{\"transition\":\"concave\",\"allottedMinutes\":90}","description":"YoMin Su","contributors":"[{\"id\":\"86b6dc70-72ec-4014-84f0-bfb2a06c3dc4\",\"add\":7152,\"del\":986}]"}
    177 views