環境
ver: CentOS 7
觀念
只要搞懂什麼是映像檔(Image)、容器(Container)、倉庫(Respository),就會一路好走了。
什麼是映像檔?
「一份最單純環境的檔案。」
如果有經歷過那個燒錄軟體的年代,可能做過屬於自己的系統環境:
先安裝 windows、安裝驅動程式,然後將這個系統環境備份成一個 .iso 檔,燒錄成一個光碟。不管最終形式一份 .iso 檔案,還是一張光碟,代表的意義都是「最單純環境的檔案」。
那這個檔案的用途是幹嘛?當然是用來快速建立、還原自己的基礎系統環境,節省大量的重複時間。在 Docker 裡,映像檔就是這樣的東西,更棒的是,在網路上會有一群人分享他們建立的各種不同環境的映像檔,隨便你取用,讓你可以快速建立自己的測試環境(或線上環境)。
什麼是倉庫?
一堆映像檔,總要有個地方統一存放吧,不然會很散亂,要找起來也不方便啊!所以統一存放映像檔的地方就是倉庫。倉庫又分為公有和私有兩種,大家可以一起分享的叫公有,如果只有自己或者少數一群人可以使用的,就叫私有。這不是廢話嗎?!最有名的公有倉庫是 Docker Hub,可以在上面找到 centos、ubuntu、nginx 最單純的映像檔。
什麼是容器?
有了映像檔,總得安裝到某個機器上吧!但是 Docker 的觀念不是這樣,因為這樣就是傳統虛擬機器做的事,Docker 是依賴 Linux 容器技術(LXC),不太一樣,細節我也不是很清楚,但是差異上大概可以這樣理解:虛擬機器像是重啟一個 os,然後執行到想執行的程式(ex:nginx)為止。而 Docker 卻只是一個行程,這個行程構建出一個虛擬空間,這個空間可以像一般的主機安裝映像檔,之後只要啟動這個虛擬空間,就能讓想要執行的程式(ex:nginx)可以順利執行。而這個虛擬空間,就是所謂的容器。由於容器技術不用重啟一個 os,而裡面的環境又是最單純的狀況,所以容器的啟動很快速。
假設我們想要打造一個單純的 web 服務,我們可以用 Docker 建構一個容器跑 nginx、建構一個容器跑 mysql 、建構一個容器執行 php-fpm。 這樣看起來只是把服務拆分,好處在哪裡?可以參考這個影片。
因為我只想讓開發環境不要全部都喇在一起而已,然後 Docker 在啟動上又很快,所以我抽空來玩看看了。至於線上環境適合不適合使用低耦合的概念來管理,我不是專業的系統人員,沒辦法給答案。
以下,我將示範如何建造一個 hhvm 環境來開發 php。
操作
安裝 docker
sudo yum install docker sudo systemctl enable docker sudo systemctl start docker
尋找映像檔
docker search 會去 Docker Hub 找映像檔
sudo docker search <keyword>
因為 hhvm 支援程度最高的作業系統是 ubuntu,所以我拿 ubuntu 映像檔當我的基礎環境。所以先來查看看有提供哪些 ubuntu 的
sudo docker search ubuntu
就會看到一串結果
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED docker.io docker.io/ubuntu Ubuntu is a Debian-based Linux operating s... 2755 [OK] docker.io docker.io/ubuntu-upstart Upstart is an event-based replacement for ... 47 [OK] docker.io docker.io/torusware/speedus-ubuntu Always updated official Ubuntu docker imag... 25 [OK] ... ... ...
容器的開開關關
使用第一個映像檔,新增並進入容器
sudo docker run -it ubuntu:15.04 /bin/bash
這個 run 指令在我這邊其實做了兩個動作,因為我之前沒有下載過 ubuntu:15.04,所以他會先去網路幫我 pull 出 ubuntu:15.04,然後拿這個映像檔建立容器,並執行它。如果照上面指令執行,會看到出現這樣的畫面:
sudo docker run -it ubuntu:15.04 /bin/bash c9caefea4a076adb394334dd5ef0d93f13309ab54074311ddc1947429616e363 root@5b0ae5548308:/#
看到「root@5b0ae5548308」就代表已經跑到容器裡(5b0ae5548308 就是所謂的 container id),並執行容器裡的 bash 程式(在 ubuntu 裡)。
離開容器
root@5b0ae5548308:/# exit
檢視目前所有容器
離開了,然後呢?原來離開了之後,會順便中止(stop)這個容器。可以使用以下的指令查看已經建立起來的所有容器。
sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5b0ae5548308 ubuntu:15.04 "/bin/bash" 46 hours ago Exited (0)... sad_tesla
目前容器只有一個,所以很好認,我們會看到剛剛的容器是 Exited 的狀態。每個容器一旦被建立起來,就會配給一個 container id 和 name (如果沒有使用 –name 指定名稱的話)。大概注意一下,接下來操作最常使用的資訊就是 container id 和 name 了。
可是這樣怪怪的啊,只要我 exit ,容器就停止執行,那不就得一直呆在容器裡,想要執行的服務或程式才能運作?只要在 docker run 時,加上 -d 參數就能讓容器在背景跑:
sudo docker run -itd ubuntu:15.04
執行完這行會看到自己還停留原始環境中,而不是跑到容器裡(停留在 centos):
ueicren@nginx.pd.net:/var/www/nginx/php$ docker run -idt ubuntu:15.04 c9caefea4a076adb394334dd5ef0d93f13309ab54074311ddc1947429616e363 ueicren@nginx.pd.net:/var/www/nginx/php$
檢視運行中的容器
這時候我們來查看有沒有「運行中」的容器,很簡單,不要加上 -a 參數即可,只會列出運行中的容器:
sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5b0ae5548308 ubuntu:15.04 "/bin/bash" 46 hours ago Exited (0)... sad_tesla
進入運行中的容器
剛剛我們讓容器跑起來了,可是總得要能夠隨心所欲地進去容器吧,不然也沒意義啊!主要有以下三種方式,我個人比較喜歡 docker exec。
使用 docker exec 指令
sudo docker exec -it <container id or name> bash
- 執行 exit 時,不會中止容器。
使用 docker attach
sudo docker attach <container id or name>
- 很有趣,多個窗口一起進去容器時,會互相影響。然後執行 exit 時,就會中止容器。
使用 nsenter
PID=$(sudo docker inspect --format "{{ .State.Pid }}" <container id>) sudo nsenter --target $PID --mount --uts --ipc --net --pid
- 執行 exit 時,不會中止容器。
控制容器的常用操作
停止活動中的容器
sudo docker stop <container id or name>
重新啟動停止的容器
sudo docker start <container id or name>
刪除已經停止的容器
sudo docker rm <container id or name>
強制刪除活動中的容器
sudo docker rm -f <container id or name>
建立映像檔
好啦,容器的基本操作介紹完,接著我進入到新建的容器裡,開始安裝 hhvm 的環境。由於是介紹 Docker 的使用,細節就快速省略,主要就是慢慢執行以下指令:
apt-get install -y software-properties-common apt-get install -y vim apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449 add-apt-repository "deb http://dl.hhvm.com/ubuntu $(lsb_release -sc) main" apt-get update apt-get install -y hhvm
手動建立映像檔
容器裡的環境已經被我們調整成可以玩 hhvm,接下來就可以把這個環境做成新的映像檔,這樣以後就不用這樣從頭做:
sudo docker commit -m "15.04 + hhvm" -a "author_name" 0b2616b0e5a8 docker.io/ubuntu:15.04_hhvm
檢視目前有哪些映像檔
sudo docker images
就會看到新建立的映像檔
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE docker.io/ubuntu 15.04_hhvm 8c1bf272259a 47 hours ago 481.6 MB docker.io/ubuntu 15.04 db672630245b 13 days ago 131.3 MB
使用 Dockerfile 建立映像檔
這個是讓我最開心的功能,只要以一個映像檔為基礎,透過撰寫 Docker file,類似 shell 的執行指令稿,就能透過分享 Dockerfile 達到分享環境的方式,超方便。
先產生一個目錄,在裡面撰寫 Dockerfile,然後執行 docker build 指令即可。
# Dockerfile START FROM ubuntu:15.04 MAINTAINER ueicren <ueicren@gmail.com> RUN apt-get install -y software-properties-common RUN apt-get install -y vim RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449 RUN add-apt-repository "deb http://dl.hhvm.com/ubuntu $(lsb_release -sc) main" RUN apt-get update RUN apt-get install -y hhvm # Dockerfile END
建立映像檔
sudo docker build -t=”docker.io/ubuntu:hhvm” .
截至目前為止,算是大功告成,作出了可以給自己重複使用的映像檔了。只要使用 docker run 就可以建立新的可以跑 hhvm 的容器了。在開發環境中,就會體驗到這個工具有多方便,環境被玩爛了,只要重建一個新容器就好。