有這麼一個程式,在你的電腦都運作得好好的,結果一到別人那裡就原地解散
你仔細一查才發現對方的環境沒有建立,接著你開始研究該怎麼建立環境,
等你建立好之後發現其中一個環節更新了,然後你發現每次都要幫對方更新不對勁
於是你開始教對方如何更新他的運行環境
接著你發現不只對方要用你的程式,一堆人都排隊需要你去幫他們安裝運行環境,這些人你都要一一教他們該如何更新
然後你就離職了
為了避免以上情形發生,我們有了docker
還記得我們當初講java嗎?
java可以跨平台就是因為在各個平台上都安裝了java虛擬機,因此執行java程式的時候實際上是由java虛擬機代為執行
docker也是類似的概念,不一樣的是java是虛擬了一台機器(電腦)而docker則是模擬了環境,所以實際上運行程式還是用你的電腦在運行而不是docker
這也是為什麼docker可以跑出幾乎原生程式的效能的原因
好,說到這裡docker實際上可以做什麼勒
我們到目前為止已經學了六種語言了,每種語言都要安裝才能使用(除了網頁前端的js)
這樣開發環境會變得很髒亂(工程師的電腦嘛)而且要更新也很麻煩
這時候就可以使用docker
先去安裝吧,我在這裡等你們
通常我們很少會自己建立一個語言的環境,而是使用官方提供的
舉例來說我們想用docker跑看看昨天寫的golang程式,那就可以上dockerhub找看看golang官方提供的image檔
點進去之後應該可以看到各種tag
第一個latest就是指最新版
第二個stretch其實是debian的版本名稱
這邊順便介紹其他有可能遇到的tag的種類代表的含意
大小的差異大概是這樣(golang在這篇文章的時候沒有提供slime版本)
由於我們沒有要做大型的測試,因此這裡就直接用alpine版本吧,左上角可以搜尋
接著你可以用最右邊提供給你的指令複製貼上到你的終端機即可
docker pull golang:rc-alpine3.12
如果你是linux記得要用sudo su進入root才能啟用docker
下載好docker的鏡像之後可以使用
docker images
或是
docker image ls
確認你的鏡像是否存在
docker container run --rm -it -v 你的main.go檔案所在的路徑:/home/go golang:rc-alpine /bin/sh
或是這麼做
docker container run --rm -it -v $PWD:/home/go golang:rc-alpine /bin/sh
$PWD會自動幫你帶入當前的檔案目錄
然後用cd切換到/home/go,就可以使用go run . 來執行你的golang程式了
(如果你需要離開docker就打exit)
看不懂可以看下面的圖片
這就是docker的威力,版本環境什麼的都由docker幫你控管好,你只需要管理好程式碼就好
接下來我們來一段一段解釋docker的指令在做什麼吧
首先,剛才我們使用指令下載下來的東西叫做image,是一個鏡像檔
你可以想像那個是廠商發行的光碟,裡面包含著運行的程式跟環境(linux跟已經安裝好的go)
而當你在docker運行的時候就像是把光碟放入光碟機
就跟以前電腦要跑遊戲的時候需要使用放入光碟才能玩一樣
而我們運行的指令
docker container run
就是將光碟運行起來的容器,你所作的一切都這個容器裡面,
因此你不管做了什麼都跟image沒有關係
因為image只負責提供運行這個容器需要的資訊而已
--rm
代表我們如果關掉了container就要順便把紀錄檔給刪掉
(一般而言我們不會加上這個指令,只是今天剛好我們要測試)
-it
這其實是兩個指令的組合
這邊我們將兩個指令組合就變成了-it
-v 你的main.go檔案所在的路徑:/home/go
-v則是將你的本機目錄掛載到container的目錄,中間使用:作為區隔
這也是為什麼我們進入container的linux後切換到/home/go
因為裡面有我們剛剛掛進去的檔案
golang:rc-alpine
這個則是我們剛剛下載下來的image檔,必須要指定名稱(REPOSIPORY)跟TAG
如果沒有指定TAG會內定使用latest,如果你的電腦沒有他就會自動去dockerhub抓
這邊我們指定用這個image來建立container
/bin/sh
這個則是我們要執行的指令,這邊不使用也沒關係
因為純golang的docker image沒有預設運行的程式,而是來到/go的資料夾
特地拿出來講的原因是要說明alpine版本的linux是沒有/bin/bash的,只能使用/bin/sh
不過我們一般發布服務不使用上面的指令,而是使用dockerfile
啥? 學了一堆結果跟我說用不到
因為工程師們都是懶人,想看看你要給別人服務,還需要告訴別人載哪個golang image,
還要把golang的程式給別人,還要教他打指令到指定目錄,還要告訴他golang的運行指令
真是太麻煩了
於是乎我們來寫dockerfile吧
在你的golang程式資料夾建立一個叫做Dockerfile的檔案(沒有副檔名喔)
FROM golang:rc-alpine
WORKDIR /home/go
ADD . /home/go
CMD ["go", "run","."]
之後使用
docker build -t="convert" .
-t 是用來指定image名稱的
建立起你的image,之後用
docker images
確認是否有成功建立
然後就可以使用
docker container run --rm -it convert:latest
來運行你剛剛包裝的image拉
這時候如果你在命令的最後面加上
/bin/sh
則會蓋掉原本你在dockerfile檔最後面的CMD指令,讓他轉而執行/bin/sh
之後如果你需要給別人使用你的服務或程式,
就把image傳到dockerhub上,請別人去下載下來到docker裡面運行即可
別人根本不用管你的golang版本或是運行環境,甚至不用管你是哪個平台開發的
只要使用你的image就可以得到跟你一模一樣的運行成果
剛剛我們下載下來的image也是類似的方式做出來的喔,你可以點進去image的連結看看
我們一直使用--rm來刪除container是因為我們不需要這個服務使用後一直活著
當你今天運行的是網站後端,運行後需要他一直存在,而你又不想要他一直佔用你的docker頁面
你可以不需要--rm 跟 -it,讓他自己跑起來剩下就可以不管他了
這個是工程師們繼續發揮懶人特性而產生的東西
用途在於當你今天不只要運行一個image的時候
你還要一個一個建立運行,然後串接起來,完成後你才建立好一個服務
工程師們一定會瘋掉
先在你的工作目錄建一個docker-compose.yml的檔案
接著到這裡
然後往下拉,看到這裡
複製這段
# Use root/example as user/password credentials
version: '3.1'
services:
db:
image: mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
adminer:
image: adminer
restart: always
ports:
- 8080:8080
貼上剛才的檔案
接著執行
docker-compose up
這樣你的服務就跑起來了
啥?我什麼都沒看到阿? 我做了什麼?
你建立了一個mariadb的資料庫系統,並且給了他一個adminer的前端來使用
到你的瀏覽器,前往下面的網址
localhost:8080
你應該會看到
Username就是root
Password則是example
登錄進去玩看看吧
這什麼?
這是一個資料庫系統,工程師們就是用他來存放各種資料
我們不會詳細介紹他(不過要當後端工程師你一定要會用)
docker-compose的好處就在這,
如果你的服務需要的不只一個程式,就可以使用他來建立
幫助你快速的將網站或程式發布出去
你可以在另外一個終端機視窗使用
docker container ls
看看你的container有哪些在跑
如果你想要關掉這個服務,使用
docker-compose down
就可以了
docker是進幾年蓬勃發展的技術,主要語言是使用昨天教的golang
這項技術某種範圍內實踐的所有語言的跨平台
開發者們再也不用擔心使用者們的作業系統跟環境,
在本機開發,並於docker上運行及測試,完成後將docker包裝好給使用者,就結束了
雖然在台灣目前還不是所有公司都在使用的技術
不過未來發展指日可待
明天我們就使用這項技術來使用php架設網站
(恩,沒錯,學這麼多天總算要來架網站了)
如果有任何寫不清楚或是觀念沒有很明白的話請留言告知我
會盡快補上
如果有任何寫錯的地方也麻煩留言告知我
會盡快修正
感謝各位