跳至主要内容

Docker好好玩

幹訓特別課程| Ver. 2022​

YoMin Su


回想一下​


身旁有沒有朋友打手遊打到走火入魔?​


13 開的「天堂 2 革命」


或是拿買賣遊戲帳號當日常的朋友?​


為了賺小錢,連虛擬機都拿來用了


甚至是,在一台電腦上裝多個系統?!​


這一台主機裝了 7 個 Windows...

單 CPU 6 台 8K 工作站 Ref: YouTube, Bilibili


以上皆為取自網路的真實案例​


今天要說的 Docker 則是在 Linux 的容器​

(虛擬機的一種)


有沒有想過開 Minecraft 伺服器可以...​


從這樣​


變這樣​


你一定會問,那兩張有差嗎?​

有差,當然有差,不然幹嘛提 xD


那,差在哪?​

一個需要你從官網下載檔案,自己處理所有東西 另一個只需要一條指令,便將所有東西都準備好


除了方便架伺服器外,還能做啥?​

架各種服務、各種實驗環境、服務之間各自切分、etc...


那實際上該怎麼使用呢?​


首先,你需要有 Docker Engine​

相信你們的電腦都準備好了,畢竟,你們的環境都已經在之前的社課讓學長姐們確認過了! (如果不是用 WSL2 的,就會是 VM)


如果沒有呢?​

① 將 WSL 1 升級到 WSL 2,並安裝 Docker Desktop ② 裝任一 Linux 系統到你的筆電上 <-- 推薦!!


良心建議​

如果覺得之後還是會想玩 Docker 的話,建議用 ① 但若你有破釜沉舟的堅毅心態,決定非 Linux 系統不用的話,② 就給它用下去吧!


解決辦法 ①​

wsl -l -v #找到你使用的Distro
wsl --set-version <Distro> 2 #將版本修改為2

記得安裝 Docker Desktop


解決辦法 ②​

雖然很棒,但今天可能不太適合...


相信各位的 Docker 都應該可以使用了,無論你用哪種方法,可以上課的方法,就是好方法~​


首次嘗試​


Hello-World 的部分​

docker run hello-world


執行畫面​


指令分析​

指令用途
docker一切的起頭
run執行一個 Image
hello-worldImage 的名稱

拿 Minecraft 伺服器當範例​

若想開一個伺服器的話...

docker run -e EULA=TRUE -d -p 25565:25565 --name mc itzg/minecraft-server


看起來是不是超複雜,超難懂?​

一臉黑人問號...嗎?


我們一個一個參數來解釋吧!​


「-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 之一

也就 100M+人在用而已啦~


若你玩的是 Bedrock(基岩)版的話...​

好像也有 Image 可以用呢!


除上述以外,「-v」參數​

可以把裡面跟外面的檔案 Mapping 起來 路徑中間用「:」連接

前面是外面,後面是裡面


小測驗時間​

/srv/gitlab:/etc/gitlab

哪個在內?哪個在外?


(Q1)Answer Here~​

橘色在外,藍綠色在內

如果想在容器中執行指令的話​

docker exec -i mc rcon-cli

指令用途
exec執行指令
-i讓介面可以互動
mcContainer 名稱
rcon-cli指令 or 功能

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​

幫你把所有設定集合起來,一次執行的好方法


首先提一下如何使用​


啟動容器​

docker-compose up

加上「-f」可以指定設定檔 加上「-d」可以在背景執行


停止容器​

docker-compose down

若是以指定檔名的方式去啟動的話,記得一樣要指定檔名來結束


接下來來看內容大概長怎樣​


範例的說​


還是範例的說,多個服務​


格式的部分​

首先要注意的是,這是 yml 檔,也就是 YAML 格式

雖然不像 Python 那樣對空格極度敏感,但同級別的項目需要在該行前面有相同的空格數量

父項目與子項目,建議相差 2 格


實際操作時間​

拿前面自己寫好的前端 Image 當範例 我們來實際寫一下 docker-compose.yml


範例內容​

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 的好夥伴

hub.docker.com/_/node


NGINX​

反向代理 or 網頁伺服器 就靠它

hub.docker.com/_/nginx


Dockercraft​

在 Minecraft 中管理你的容器的方法

github.com/docker/dockercraft


加分時間​


Q2. YAML 格式有什麼特點?​

  1. 對空格__,但要求__
  2. 每個項目後面都會加上__
  3. 通常父項跟子項差__個空格

(Q2)Answer Here!​

  1. 對空格不敏感,但要求同階層項目前有相同數量的空白
  2. 每個項目後面都會加上冒號
  3. 通常父項跟子項差2 個空格
let score = 100;
console.log(`每格: {score}分`);

Q3. 如果不希望 Docker 啟動的服務直接對外,在給參數時該怎麼寫?​


(Q3)Answer Here...​

ports:
- "127.0.0.1:<Host Port>:<LXC Port>"
SCORE=250
echo "此題: $SCORE分"

Q4. 續上題,為什麼 Docker 啟動的服務會無視 ufw 建立的防火牆條件?​


(Q4)Answer Here​

因為 Docker Engine 會直接對系統的 iptables 進行修改,加入運作時需要的網路結構,因此 ufw 的設定才無法正確工作。

score = 300
print(f'你可以獲得{score}分!')

感謝你的聆聽​