coscup 2016 workshop: 用 docker 架設班級 git-it 練習環境
TRANSCRIPT
投影片 http://goo.gl/3aHqNd
原檔 https://goo.gl/EiUL61等等會有一些程式碼
在投影片上面不容易複製建議可以在原檔複製
DEMO!
緣起
網路上有很多 git 教學
但是幾乎大多數
都是模擬的系統
偶然之間得知有 git-it
這套教學軟體
除了要在終端機下實機操作 git
還要實機操作 GitHub
Very Good
BUT
但是社團跟系上借的電腦教室
全部都有裝還原卡
一堂課的時間很寶貴
光安裝系統就飽了
練習 git-it 根本來不及
而且電腦教室的網路所有人一起抓軟體時
就會慢到跟烏龜一樣
於是希望可以省掉 git-it 安裝
還希望能有即時成績看板ACM 中毒
使用 docker 架設 git-it 環境
首先 我們需要
能執行 Docker 的主機
以下是我用過的虛擬主機DigitalOcean
Create Droplet→ One-click Apps→Docker 1.x.x on 14.04
AWS EC2
Ubuntu Server 14.04 LTS (HVM)→自己安裝 Docker
如果你需要安裝 Docker官方 Linux 安裝腳本
Ubuntu
其他版本
如果你用 DigitalOcean 的 Docker 1.x.x on 14.04就可以跳過啦。
“
“
實做時間請大家完成到可成功測試 Docker
sudo service docker start sudo docker run hello-world
接下來我們要來寫 Docker le
Docker le 是什麼?
Docker le 包含創建映像檔所需要的全部指令。
我們可以使用 docker build 指令來創建映像檔。
通過減少映像檔和容器的創建程序來簡化部署。
先來看幾個Docker le 的訣竅
撰寫 Docker le 訣竅1. 先開一個基礎的容器
# 開啟一個基礎的 ubuntu:14.04 指令 sudo docker run -ti ubuntu:14.04 /bin/bash
2. 按照安裝教學安裝一次3. 將指令改成 non-interactive (不須互動,自動安裝)
4. 再把指令複製到 Docker le
git-it 安裝教學https://github.com/jlord/git-
it/blob/master/original-readme.md
系統更新sudo apt-get update sudo apt-get upgrade
non-interactive
apt-get update -qq apt-get upgrade -y
git-it 需求Git
Node.js
純文字編輯器 (Text Editor)
英文語系 (English locales)
git 安裝sudo apt-get install git
non-interactive
apt-get install -y git
Node.js & npm 安裝sudo apt-get install nodejs npm # 由於 git-it 預設使用 node 執行,故須 link sudo ln -s /usr/bin/nodejs /usr/bin/node
non-interactive
apt-get install -y nodejs npm ln -s /usr/bin/nodejs /usr/bin/node
純文字編輯器 (Text Editor)sudo apt-get install vim nano
non-interactive
apt-get install -y vim nano
git-it 安裝sudo npm install -g git-it
non-interactive
npm install -g git-it
Docker le 小結FROM ubuntu:14.04 RUN apt-get update -qq RUN apt-get upgrade -y RUN apt-get install -y git nodejs npm vim nano RUN ln -s /usr/bin/nodejs /usr/bin/node RUN npm install -g git-it
接下來
該怎麼讓學員進到自己的蘿蔔坑呢
我們只有很少的主機
一台主機上有很多個 client
不能讓學員從 host 進入 client
r m - r f /
SSHSecure Shell
然後再把每個 client 的 SSH 埠
port forwarding 出來
BUT
Docker 容器通常預設沒有 ssh
架設 ssh 教學Docker 官方範例 https://goo.gl/edqX2W
Docker le 小結# ... 略 RUN apt-get install -y openssh-server RUN mkdir /var/run/sshdRUN echo 'root:git-it' | chpasswd RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/'RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' EXPOSE 22 CMD ["/usr/sbin/sshd", "-D"]
現在
你的 Docker le
已經足以練習 git-it
BUT
一次面對一個班級的時候還是有很多問題
該怎麼快速開很多 client?
docker start
docker-compose
安裝 docker-compose
請注意 Docker Compose 的版本。
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname chmod +x /usr/local/bin/docker-compose docker-compose --version
參考網址
1. https://docs.docker.com/compose/install/
2. https://github.com/docker/compose/releases
“
“
docker-compose.ymlversion: '2' services: client: build: client/ ports: - "22"
YML 的縮行很重要“ “
開多台 client可自由指定數量
sudo docker-compose up -d sudo docker-compose scale client=5
VPS 的 RAM 太小?
設定 swap (建議)
如果開的機器 RAM 較小,則建議手動新增 swap 以供Docker 使用。
https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-14-04
該怎麼指派SSH PORT 給學員?
查詢 port forwarding 列表docker-compose ps
Name Ports --------------------------------------------------------------------gititcoursedocker_client_1 0.0.0.0:32794->22/tcp scoreboard 0.0.0.0:22000->22/tcp, 0.0.0.0:80->80/tcp
client 的密碼所有人都知道該怎麼辦?
強制登入後更改密碼在 Docker le 加上
RUN chage -d 0 root
實做時間使用 SSH 進入 client
登入後立即要求更改 root 密碼
輸入 git-it 後進入選題選單
接下來是比較進階的主題
scoreboard
scoreboard
能幫助我們什麼呢?
scoreboard 能幫我們...顯示 client 的 SSH PORT
顯示哪個 client 還沒有人使用
顯示學員的名字
顯示學員的解題數使用網頁公開資料
scoreboard 該怎麼用程式抓取 client 的 SSH PORT?
先幫 client 的 Docker le 加上LABEL# Dockerfile LABEL role="git-it-client"
使用 LABEL 進行過濾在 Docker Remote API 文件 範例
curl http://host/containers/json?filters={"label":["role=git-it-client"
docker ps 範例
docker ps --filter "label=role=git-it-client" --format '"{{.ID}}":{{.Ports}}'
接下來是 client 的回報程式
client 回報是否有人使用1. 查詢登入密碼是否已被更改
OWNED=`[ "never" = "$(chage -l root | grep 'Password expires' | sed -r 's/^[^:]+: //')
2. client 定期 (cron) 回報給 scoreboard
client 回報學員的名字git-it 的題目會要求幫 git 設定使用者的名字和 GitHub的帳號,所以直接抓 git 的 user.name 和 user.username就好了。
NAME=`git config --global user.name || hostname` GITHUB=`git config --global user.username || echo ''`
顯示學員的解題數git-it 會把解題數存放在 ~/.config/git-it/completed.json
COMPLETED=`test -r /root/.config/git-it/completed.json && cat /root/.config/git-it/completed.json ||
client 需安裝 curlsudo apt-get install curl
non-interactive
apt-get install -y curl
回報資料給 scoreboard#!/bin/bash COMPLETED=`test -r /root/.config/git-it/completed.json && cat /root/.config/git-it/completed.json || MID=`hostname` NAME=`git config --global user.name || hostname` GITHUB=`git config --global user.username || echo ''` OWNED=`[ "never" = "$(chage -l root | grep 'Password expires' | sed -r 's/^[^:]+: //') curl \ --data-urlencode "completed=${COMPLETED}" \ --data-urlencode "mid=${MID}" \ --data-urlencode "name=${NAME}" \ --data-urlencode "github=${GITHUB}" \ --data-urlencode "owned=${OWNED}" \ http://scoreboard/completed/update
為什麼剛剛的回報程式可以用 scoreboard 當作主機?
因為 Docker 的 LINK
會很貼心的幫我們設定DNS 解析 /etc/hosts
於 client 中架設 crontab 定期回報
撰寫 /etc/crontab每分鐘回報 client 的資料給 scoreboard,以 root 身份執行。
* * * * * root /usr/bin/scoreboard-reporter.sh >> /dev/null 2>&1
client Docker le 加入 cron參考 https://github.com/aptible/docker-cron-example
RUN apt-get -y install rsyslog ADD crontab /etc/crontab ADD client-start.sh /usr/bin/client-start.sh ADD scoreboard-reporter.sh /usr/bin/scoreboard-reporter.sh RUN chmod +x /usr/bin/client-start.sh RUN chmod +x /usr/bin/scoreboard-reporter.sh RUN touch /var/log/cron.log
client 啟動腳本由於我們需要執行的程式已經超過一個了,為了避免Docker le 的 CMD 指令太過複雜,所以我們要開新client 要執行的指令都寫在 client-start.sh
#!/bin/sh # client-start.sh sleep 5 rsyslogd cron /usr/sbin/sshd # 刪掉 -D 參數 /usr/bin/scoreboard-reporter.sh # 開機時先回報一次 tail -F /var/log/syslog /var/log/cron.log
修改 Docker le CMD 指令# 要把舊的刪除,因為只有最後一個 CMD 有效 CMD /usr/bin/client-start.sh
實作時間請參考 https://github.com/taichunmin/git-it-course-docker/tree/master/client
client 完成到可以回報資料給 scoreboard
scoreboard
scoreboard Docker le
主要接收 client 的回報還會去跟 Docker Remote API
取得每個 client
所對應的 PORT
單純就是一個 HTTP Server
由於不是每個人都會 PHP
所以就不深入談了
我已經事先把 scoreboard
build 到 Docker Hub
可以直接用 Docker Hub
來寫 docker-compose.yml
scoreboard 的 docker-compose.yml
version: '2' services: scoreboard: # build: scoreboard/ image: taichunmin/git-it-course-docker:scoreboard ports: - "80:80" - "22000:22" container_name: scoreboard volumes: - /var/run/docker.sock:/var/run/docker.sock
port 80 是網頁伺服器port 22 是 SSH,為了方便就固定對應到 22000
設定了 container_name 可以避免誤開多台
設定 volumes 可以讓 scoreboard 存取 Remote API
須開放 Docker Remote API給 scoreboard
開放 Docker Remote API利用 Volumes
version: '2' services: scoreboard: # 省略 volumes: - /var/run/docker.sock:/var/run/docker.sock
然後我們需要修改 client 的docker-compose.yml
version: '2' services: client: build: client/ ports: - "22" links: - scoreboard depends_on: - scoreboard
讓 docker-compose 自動對應 port 22 出來LINK 到 scoreboard,讓 client 可以回報資料depends_on 讓 docker-compose 確保有 scoreboard
到此結束歡迎提問