iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
2

寫在前面

有這麼一個程式,在你的電腦都運作得好好的,結果一到別人那裡就原地解散
你仔細一查才發現對方的環境沒有建立,接著你開始研究該怎麼建立環境,
等你建立好之後發現其中一個環節更新了,然後你發現每次都要幫對方更新不對勁
於是你開始教對方如何更新他的運行環境
接著你發現不只對方要用你的程式,一堆人都排隊需要你去幫他們安裝運行環境,這些人你都要一一教他們該如何更新
然後你就離職了

為了避免以上情形發生,我們有了docker
還記得我們當初講java嗎?
java可以跨平台就是因為在各個平台上都安裝了java虛擬機,因此執行java程式的時候實際上是由java虛擬機代為執行
docker也是類似的概念,不一樣的是java是虛擬了一台機器(電腦)而docker則是模擬了環境,所以實際上運行程式還是用你的電腦在運行而不是docker
這也是為什麼docker可以跑出幾乎原生程式的效能的原因

好,說到這裡docker實際上可以做什麼勒
我們到目前為止已經學了六種語言了,每種語言都要安裝才能使用(除了網頁前端的js)
這樣開發環境會變得很髒亂(工程師的電腦嘛)而且要更新也很麻煩
這時候就可以使用docker

先去安裝吧,我在這裡等你們

dockerhub

通常我們很少會自己建立一個語言的環境,而是使用官方提供的
舉例來說我們想用docker跑看看昨天寫的golang程式,那就可以上dockerhub找看看golang官方提供的image檔

https://ithelp.ithome.com.tw/upload/images/20200914/20127836XIHijtqT2J.png

點進去之後應該可以看到各種tag

https://ithelp.ithome.com.tw/upload/images/20200914/20127836ZD2Nxh1I1e.png

第一個latest就是指最新版
第二個stretch其實是debian的版本名稱

https://ithelp.ithome.com.tw/upload/images/20200914/201278365XuYGfgjD0.png

這邊順便介紹其他有可能遇到的tag的種類代表的含意

  • latest 最新功能
  • slim 刪減一些不重要功能後留下的版本
  • alpine 通常來說都是最小的版本

大小的差異大概是這樣(golang在這篇文章的時候沒有提供slime版本)

https://ithelp.ithome.com.tw/upload/images/20200914/20127836PDi0hFzZ1V.png

由於我們沒有要做大型的測試,因此這裡就直接用alpine版本吧,左上角可以搜尋
接著你可以用最右邊提供給你的指令複製貼上到你的終端機即可

docker pull golang:rc-alpine3.12

如果你是linux記得要用sudo su進入root才能啟用docker

下載好docker的鏡像之後可以使用

docker images

或是

docker image ls

確認你的鏡像是否存在

接著我們先跑看看昨天的golang程式

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)
看不懂可以看下面的圖片

https://ithelp.ithome.com.tw/upload/images/20200914/201278363SL2bBZFVW.png

這就是docker的威力,版本環境什麼的都由docker幫你控管好,你只需要管理好程式碼就好

接下來我們來一段一段解釋docker的指令在做什麼吧

image

首先,剛才我們使用指令下載下來的東西叫做image,是一個鏡像檔
你可以想像那個是廠商發行的光碟,裡面包含著運行的程式跟環境(linux跟已經安裝好的go)
而當你在docker運行的時候就像是把光碟放入光碟機
就跟以前電腦要跑遊戲的時候需要使用放入光碟才能玩一樣

container

而我們運行的指令

docker container run

就是將光碟運行起來的容器,你所作的一切都這個容器裡面,
因此你不管做了什麼都跟image沒有關係
因為image只負責提供運行這個容器需要的資訊而已

--rm

代表我們如果關掉了container就要順便把紀錄檔給刪掉
(一般而言我們不會加上這個指令,只是今天剛好我們要測試)

-it

這其實是兩個指令的組合

  • -i 表示我們將原本於container的linux運行的畫面轉到我們的畫面來,讓我們可以看到運行的結果
  • -t 表示我們將原本輸入在本機的指令轉移到container內,使指令在linux上面運行

這邊我們將兩個指令組合就變成了-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

不過我們一般發布服務不使用上面的指令,而是使用dockerfile

啥? 學了一堆結果跟我說用不到

因為工程師們都是懶人,想看看你要給別人服務,還需要告訴別人載哪個golang image,
還要把golang的程式給別人,還要教他打指令到指定目錄,還要告訴他golang的運行指令
真是太麻煩了

於是乎我們來寫dockerfile吧

你的golang程式資料夾建立一個叫做Dockerfile的檔案(沒有副檔名喔)

FROM golang:rc-alpine

WORKDIR /home/go

ADD . /home/go

CMD ["go", "run","."]
  • FROM 表示使用哪個image來建立
  • WORKDIR 表示工作資料夾
  • ADD 表示複製檔案到image的目錄,跟container -v 的作用類似,這裡的 . 表示把當前目錄下的全部拷貝到/home/go
  • CMD 表示一旦image放入到docker運作時執行的預設指令

之後使用

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的連結看看

https://ithelp.ithome.com.tw/upload/images/20200914/20127836RfQJIV8Ds7.png

我們一直使用--rm來刪除container是因為我們不需要這個服務使用後一直活著
當你今天運行的是網站後端,運行後需要他一直存在,而你又不想要他一直佔用你的docker頁面
你可以不需要--rm 跟 -it,讓他自己跑起來剩下就可以不管他了

docker composer

這個是工程師們繼續發揮懶人特性而產生的東西
用途在於當你今天不只要運行一個image的時候
你還要一個一個建立運行,然後串接起來,完成後你才建立好一個服務
工程師們一定會瘋掉

先在你的工作目錄建一個docker-compose.yml的檔案

接著到這裡
然後往下拉,看到這裡

https://ithelp.ithome.com.tw/upload/images/20200914/20127836m2B4kqCTvg.png

複製這段

# 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

你應該會看到

https://ithelp.ithome.com.tw/upload/images/20200914/20127836uAftLDQA07.png

Username就是root
Password則是example

登錄進去玩看看吧

這什麼?

這是一個資料庫系統,工程師們就是用他來存放各種資料
我們不會詳細介紹他(不過要當後端工程師你一定要會用)

docker-compose的好處就在這,
如果你的服務需要的不只一個程式,就可以使用他來建立
幫助你快速的將網站或程式發布出去

你可以在另外一個終端機視窗使用

docker container ls

看看你的container有哪些在跑

如果你想要關掉這個服務,使用

docker-compose down 

就可以了

小結

docker是進幾年蓬勃發展的技術,主要語言是使用昨天教的golang
這項技術某種範圍內實踐的所有語言的跨平台
開發者們再也不用擔心使用者們的作業系統跟環境,
在本機開發,並於docker上運行及測試,完成後將docker包裝好給使用者,就結束了
雖然在台灣目前還不是所有公司都在使用的技術
不過未來發展指日可待

明天我們就使用這項技術來使用php架設網站
(恩,沒錯,學這麼多天總算要來架網站了)


上一篇
golang 為網路而生的Google親兒子
下一篇
php 長相如同半獸人般奇怪,曾經統治中土(網路)的王者
系列文
你會十五種程式語言?不,我會十五種HelloWorld.為了避免這種狀況,因此寫了這篇:淺入淺出十五種程式語言30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
skycover
iT邦新手 4 級 ‧ 2020-09-14 21:46:45

如果有任何寫不清楚或是觀念沒有很明白的話請留言告知我
會盡快補上

如果有任何寫錯的地方也麻煩留言告知我
會盡快修正

感謝各位

我要留言

立即登入留言