主題: Docker 實作與應用
分享者:張明泰 mtchang.tw@gmail.com
講者BLOG: http://blog.jangmt.com/
日期: 2015.3. 10
地點:管CM2016 教室
時間 19:00 ~ 21:00
19:00 ~ 19:30 報到
19:30 ~ 21:00 活動開始
21:00 ~ 21:30 討論
摘要:
本次分享的主題,主要介紹 Docker 的實作與應用。
Docker 是一個類似虛擬化主機功能的容器,但他少了很多虛擬化主機的層層堆疊。
他讓 Linux 系統上的應用程式的分派、部署和管理都變得有效率和輕鬆。
使用 Docker 需要有一些 Linux 的系統概念,但不論你的 Linux 作業系統是 Ubuntu 或是 CentOS 都可以方便快速的佈署 Docker 系統。
此分享將示範如何建立、管理與應用,並將以常見的 Apache + MySQL + PHP 服務的應用情境,說明如何透過 Docker 來使用協助網站的開發。
--------------------------------
以下正文分隔線
--------------------------------
(1) 簡介:
Docker是一個開放原始碼軟體專案,在軟體容器下自動布署應用程式,藉此在Linux作業系統上,提供了一個額外的軟體抽象層,以及作業系統層虛擬化的自動管理機制。Docker利用Linux內核中的資源分離機制,例如cgroups 及Linux 內核名稱空間 (name space),來建立獨立的軟體容器(containers)。這可以在單一 Linux 實體下運作,不用啟動一個完整的虛擬機器。
(引用:維基百科:http://zh.wikipedia.org/wiki/Docker_%28%E8%BB%9F%E9%AB%94%29 )
也可以說,透過 Docker 建立的容器跑起來像是一台虛擬機器的功能,但是又沒有虛擬機器的層層堆疊。底下示意圖可以顯示 VMs 和 Container 兩者的差異:
ref: http://www.logitrain.com.au/blog/wp-content/uploads/2014/09/docker.png
如果把 Containers 和 Linux 上面的 Processes 比較,差別在於 container 有對於所執行的程式的資源使用限制。也因為 Linux 可以支援對於各種系統資源的使用限制,所以可以跑起來類似虛擬機器一樣的具有資源的獨立性。
底下為 Docker 透過 Linux 核心提供的資源限制的功能示意圖。
ref: http://lab.howie.tw/2014/08/docker-docker-lxc-hypervisor.html
ref:http://en.wikipedia.org/wiki/Docker_(software)
CGroups
cgroups 是一個 linux 核心的功能一個設計目標是為不同的應用情況提供統一的介面,從控制單一行程(像nice)到系統級虛擬化(像opeNVZ,Linux-VServer,LXC)。
cgroups提供:
資源限制:組可以被設定不超過設定的記憶體限制;這也包括虛擬記憶體。
優先化:一些組可能會得到大量的CPU 或磁碟輸入輸出通量。
報告:用來衡量系統確實把多少資源用到適合的目的上。
分離:為組分離命名空間,這樣一個組不會看到另一個組的行程、網路連線和檔案。
控制:凍結組或檢查點和重新開機動。
ref:https://mairin.wordpress.com/2011/05/13/ideas-for-a-cgroups-ui/
UnionFS
可合併指定的所有實體目錄(branch),並建立一個單一的目錄(ex. union )集合去堆疊所有目錄來使用,並不會真正去變更到指定的所有目錄資料,全部的變更資料均會儲存在建立的目錄資料夾內(union)。(ref:http://gis.nchc.org.tw/lsi/Linux_Basic/discuss/look.asp?id=875&Page=7&ADMIN=1 )
Docker 的架構:
Docker client 負責與 server 端的 docker deamon 溝通,下達 docker 的操作指令 (ex: docker pull , docker run 等...)。一般而言 Docker client 與 Docker deamon 都在同一台機器上面。架構圖如下:
ref: http://www.slideshare.net/winggundamth/docker-cd-workshop
Docker 的元件:
Docker 有幾個重要的元件
Docker images & Containers: Docker images 是用來產生 container 的樣板檔案,他會以一公版的 linux 影像檔當成基礎,且使用者可透過 docker commit 擴展修改成為一個適合自己用的 docker images ,並且可以透過 docker registries 來分享。
Docker registries:是用來存放 images 的倉庫,預設的公用 Registry 就是 Docker Hub (https://hub.docker.com),提供類似套件儲存庫的功能。你可以透過 Docker Hub 下載及分享影像檔案,他類似 github 是一個有社交功能的公用倉庫。
(2) Docker 安裝:
Docker 的運作是在 Linux kernel 的基礎上,在非 Linux 的平台如 Windows 他是透過 輕量級的 VM 元件產生一個虛擬機器在系統上執行,這個元件叫做 Boot2Docker (https://docs.docker.com/installation/windows/),所以跑起來和 Linux 不太一樣。所以在 MAC OS X 上面的 Docker 用的 Boot2Docker(https://docs.docker.com/installation/mac/ ) 也是用類似的方式達成的。
ref: https://docs.docker.com/installation/mac/
我不建議在非 Linux 平台上面使用 Docker ,使用一個完整的 Linux 來使用 Docker 才是較為正確的方式。
ref: https://docs.docker.com/installation/mac/
目前在 ubuntu 及 centos 可以用的的維護套件名稱為 docker.io ,ubuntu 由 http://www.ubuntuupdates.org/ppa/docker 這裡在維護提供。 Centos 7的 Docker 從 RHEL7 重新編譯,目前收錄在 CentOS-Extras 套件庫中( http://wiki.centos.org/zh-tw/Cloud/Docker )。
如果可以建議你使用 ubuntu 最新的14.04 LTS 版本
http://www.ubuntu-tw.org/modules/tinyd0/
Linux mint 對應 Ubuntu 14.04 的版本為 Linux Mint 17.1 Rebecca
http://www.linuxmint.com/download.php
使用 CnetOS 7 最新的版本來安裝
http://www.centos.org/download/
如果你不是用這些新的版本的 Linux,請你參考 docker 官方網站的說明來解決你安裝上的問題。
https://docs.docker.com/installation/
(2.1) CentOS 7 的 Docker 服務安裝:
# Install Docker in CentOS 7 , lsb_release 確定一下目前的 linux 版本
[mtchang@mtchang ~]$ sudo lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.0.1406 (Core)
Release: 7.0.1406
Codename: Core
# 直接安裝 docker 和 docker-registry
[mtchang@mtchang ~]$ sudo yum -y install docker docker-registry
# 在 centos 7 使用 systemctl 管控 docker.service ,這裡是把服務預設開機啟動
[mtchang@mtchang ~]$ sudo systemctl enable docker.service
ln -s '/usr/lib/systemd/system/docker.service' '/etc/systemd/system/multi-user.target.wants/docker.service'
# 手動啟用 docker service
[mtchang@mtchang ~]$ sudo systemctl start docker.service
# 驗證是否已經啟動
[mtchang@mtchang ~]$ sudo systemctl status docker.service
docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
Active: active (running) since Sat 2015-02-21 15:22:01 CST; 15s ago
Docs: http://docs.docker.com
Main PID: 4346 (docker)
CGroup: /system.slice/docker.service
└─4346 /usr/bin/docker -d --selinux-enabled -H fd://
Feb 21 15:21:51 mtchang docker[4346]: 2015/02/21 15:21:51 docker daemon: 1.3.2 39fa2fa/1.3.2; execdriver: nat...iver:
Feb 21 15:21:51 mtchang docker[4346]: [aec76134] +job serveapi(fd://)
Feb 21 15:21:51 mtchang docker[4346]: [info] Listening for HTTP on fd ()
Feb 21 15:22:00 mtchang docker[4346]: [aec76134] +job init_networkdriver()
Feb 21 15:22:00 mtchang docker[4346]: [aec76134] -job init_networkdriver() = OK (0)
Feb 21 15:22:01 mtchang docker[4346]: [info] Loading containers:
Feb 21 15:22:01 mtchang docker[4346]: [info] : done.
Feb 21 15:22:01 mtchang docker[4346]: [aec76134] +job acceptconnections()
Feb 21 15:22:01 mtchang docker[4346]: [aec76134] -job acceptconnections() = OK (0)
Feb 21 15:22:01 mtchang systemd[1]: Started Docker Application Container Engine.
Hint: Some lines were ellipsized, use -l to show in full.
# 從 docker registry 抓取 ubuntu 的影像檔案
[mtchang@mtchang ~]$ sudo docker pull ubuntu
Pulling repository ubuntu
2d24f826cb16: Download complete
511136ea3c5a: Download complete
fa4fd76b09ce: Download complete
1c8294cc5160: Download complete
117ee323aaa9: Download complete
Status: Downloaded newer image for ubuntu:latest
# docker run 指令執行以 ubuntu 影像檔為基礎的一個 container
# mtchang@mt ~ $ sudo docker run --help
# 語法: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# -i 可以保持 STDIN 輸出訊息打開
# -t 可以取得一個 pseudo-TTY (虛擬終端機界面)
[mtchang@mtchang ~]$ sudo docker run -i -t ubuntu /bin/bash
# 已經切換到docker container 內, ip 也變換成為虛擬網段 172.17.0.xx。
root@bc44ac88d7a4:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:19 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2173 (2.1 KB) TX bytes:508 (508.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@bc44ac88d7a4:/# exit
exit
(2.2) Linux Mint 17 OR Ubuntu 的 Docker 服務安裝:
# Linux mint 安裝 docker
mtchang@mt ~ $ lsb_release -a
No LSB modules are available.
Distributor ID: LinuxMint
Description: Linux Mint 17 Qiana
Release: 17
Codename: qiana
# ubuntu 因為安裝過程很煩,所以它把安裝過程寫成了script 放在 https://get.docker.com/ubuntu/ ,所以底下的安裝需要先透過 curl 抓回 script ,然後透過 shell 執行安裝。
mtchang@mt ~ $ sudo apt-get install curl
# 它需要有 apparmor ,這是一個應用程式安全性的控管機制
mtchang@mt ~ $ sudo apt-get install apparmor
# 安裝由 ubuntu 維護的 docker.io 套件,不要安裝原本 ubuntu 提供的 docker 套件
mtchang@mt ~ $ sudo apt-get install docker.io
# 載入 bash 環境變數
mtchang@mt ~ $ source /etc/bash_completion.d/docker.io
# 抓取安裝 script 並執行
mtchang@mt ~ $ curl -sSL https://get.docker.com/ubuntu/ | sudo sh
# 直接執行 ubuntu 的影像檔
mtchang@mt ~ $ sudo docker run -i -t ubuntu /bin/bash
# 第一次執行會發現還沒有 ubuntu 這個影像檔,會直接從網路上抓取
Unable to find image 'ubuntu' locally
Pulling repository ubuntu
5ba9dab47459: Download complete
511136ea3c5a: Download complete
27d47432a69b: Download complete
5f92234dcf1e: Download complete
51a9c7c1f8bb: Download complete
# 然後就直接進入 container
root@6bcf5474cbf3:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:43 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:7262 (7.2 KB) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@6bcf5474cbf3:/# df -lh
Filesystem Size Used Avail Use% Mounted on
rootfs 451G 28G 401G 7% /
none 451G 28G 401G 7% /
tmpfs 1.9G 0 1.9G 0% /dev
shm 64M 0 64M 0% /dev/shm
/dev/disk/by-uuid/600e3388-c76f-4b56-ba18-14b58274f430 451G 28G 401G 7% /etc/hosts
tmpfs 1.9G 0 1.9G 0% /proc/kcore
root@6bcf5474cbf3:/# exit
exit
mtchang@mt ~ $ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu trusty 5ba9dab47459 13 days ago 188.3 MB
ubuntu 14.04 5ba9dab47459 13 days ago 188.3 MB
ubuntu 14.04.1 5ba9dab47459 13 days ago 188.3 MB
ubuntu latest 5ba9dab47459 13 days ago 188.3 MB
安裝參考:https://docs.docker.com/installation/ubuntulinux/#ubuntu-trusty-1404-lts-64-bit
Docker 的網路:
docker 安裝好後會在系統產生一個 docker0 的虛擬網卡,通常 ip 會是 172.17.42.1 ,內部的 container 會自動取得 172.17.0.0/24 的 ip ,並且預設就可 nat 連接到 eth0 出去。
外界如果需要連接到 container 內的網路,需要透過docker -p 外部 port : 內部 port 的 DNAT port 對應方式,來指定允許存取容器的主機上的 IP、界面。
例如:
$ sudo docker run --name="jangmt0305" -p 8080:80 -i -t ubuntu /bin/bash
這會讓本地端的 8080 port 對應到 container 內的 80 port
Docker 的儲存裝置:
資料卷 docker volume ,在 docker container 內如果需要存取外部的儲存裝置,可以透過建立 docker volume 和 docker host 產生目錄的對應。 當然也可以透過 mount 之類的方式掛載外界的資源,但 docker container 內部是一個非常精簡的 linux 這會需要多增加安裝更多的程式。
使用的方法為在 docker run 的時候加入 -v 指定一個本地端主機到 docker container 內。
例如:
$ sudo docker run -i -t --name web -v /home/webapp:/var/www/html/webapp /bin/bash
這會把本地端的 /home/webapp 對應到 container 內的 /var/www/html/webapp 目錄內。
ref: http://jam.sg/blog/mongodb-docker-part-2/
(3) Docker 常用指令:
docker search 搜尋 docker hub 上面的 images 檔案
docker pull 抓取影像檔
docker login 登入 docker hub
docker push 將影像檔上傳道 docker hub
docker commit 將修正的 container 資料提交成為新的影像檔
docker run 以某個 image 執行 container
docker ps 觀看目前系統正在執行的 container
docker images 觀看系統擁有的影像檔
docker build 依據 docker file 的描述,建立一個 docker images
# 詳細可以觀看 docker help 的說明
# docker help
Usage: docker [OPTIONS] COMMAND [arg...]
A self-sufficient runtime for linux containers.
.. 略...
Commands:
attach Attach to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders from a container's filesystem to the host path
create Create a new container
diff Inspect changes on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Stream the contents of a container as a tar archive
history Show the history of an image
images List images
import Create a new filesystem image from the contents of a tarball
info Display system-wide information
inspect Return low-level information on a container or image
kill Kill a running container
load Load an image from a tar archive
login Register or log in to a Docker registry server
logout Log out from a Docker registry server
logs Fetch the logs of a container
port Lookup the public-facing port that is NAT-ed to PRIVATE_PORT
pause Pause all processes within a container
ps List containers
pull Pull an image or a repository from a Docker registry server
push Push an image or a repository to a Docker registry server
rename Rename an existing container
restart Restart a running container
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save an image to a tar archive
search Search for an image on the Docker Hub
start Start a stopped container
stats Display a live stream of one or more containers' resource usage statistics
stop Stop a running container
tag Tag an image into a repository
top Lookup the running processes of a container
unpause Unpause a paused container
version Show the Docker version information
wait Block until a container stops, then print its exit code
Run 'docker COMMAND --help' for more information on a command.
(4) 應用情境:( 以 ubuntu 的 docker 影像檔基礎為範例)
目前 docker 的應用都是透過網路上 docker hub 這種發布的平台,發布分享影像檔案。開發者透過釋放出來的影像檔,提交 commit 自己修改過的影像檔案。 docker 有各教學的連結,教你如何使用 docker 來使用別人提交的現成 images https://www.docker.com/tryit/ ,你可以花各 10 min 試試看這個互動式教學文件。
ref: http://developer-blog.cloudbees.com/2014/07/announcing-dockerhub-jenkins-plugin.html
ref: http://blog2dev.blogspot.fr/2014/06/docker-mise-en-pratique.html
https://www.docker.com/tryit/ 線上互動教學
應用情境案例(1):一個 Apache2 + PHP 服務安裝為例
# 啟動一個以 ubuntu image為主 的 container , 名稱命名為 jangmt0305 ,並將本地端的 tcp port 8080 對應到 container 80 ,並且 -i 將 STDIN 保留, -t 取得一個虛擬終端機,並執行 /bin/bash 的程序。
mtchang@mt ~ $ sudo docker run --name="jangmt0305" -p 8080:80 -i -t ubuntu /bin/bash
# 底下為在 docker container 內的 /bin/bash 執行
root@b29f95d30b68:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:09
inet addr:172.17.0.9 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:9/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:508 (508.0 B) TX bytes:508 (508.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
# docker host 另開一個新視窗,從外部來看目前的 container 執行狀況
mtchang@mt ~ $ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b29f95d30b68 ubuntu:14.04 "/bin/bash" 36 seconds ago Up 35 seconds 0.0.0.0:8080->80/tcp jangmt0305
# 可以透過 Linux 的 iptables 看到系統開了一個 DNAT 對應 tcp dpt:8080 to:172.17.0.9:80
mtchang@mt ~ $ sudo iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.9 172.17.0.9 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.9:80
# 回到 docker container 內,可以執行安裝程序。
root@b29f95d30b68:/# apt-get install apache2 php5-cli libapache2-mod-php5
# 啟動服務
root@b29f95d30b68:/# /etc/init.d/apache2 restart
* Restarting web server apache2 AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.9. Set the 'ServerName' directive globally to suppress this message [ OK ]
root@b29f95d30b68:/# netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp6 0 0 :::80 :::* LISTEN -
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node PID/Program name Path
# 用瀏覽器測試看看觀看網址 http://<docker host IP>:8080/
# 把剛剛的 container 重新載入啟動,需要記住 container ID 號碼,可以使用 docker ps -a 來查詢。
mtchang@mt ~ $ sudo docker start b29f95d30b68
b29f95d30b68
mtchang@mt ~ $ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b29f95d30b68 ubuntu:14.04 "/bin/bash" 19 minutes ago Up 6 seconds 0.0.0.0:8080->80/tcp jangmt0305
# 可以透過 docker attach 取回 container ,重新取得 /bin/bash
mtchang@mt ~ $ sudo docker attach b29f95d30b68
root@b29f95d30b68:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:0a
inet addr:172.17.0.10 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:a/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
應用情境案例(2):把這個 container 提交並且上傳到 docker hub:
# 把系統中最後狀態的 container commit ,並且上傳道 docker hub 提供分享。
# 先使用 docker ps -a 觀看 container ID
mtchang@mt ~ $ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
…(skip) ...
b29f95d30b68 ubuntu:14.04 "/bin/bash" 20 hours ago Exited (0) 17 minutes ago
# 使用 docker commit 提交 -m 為提交的說明 -a 為作者資訊
# b29f95d30b68 為提交的 container ID
# mtchang/lamp 為 REPOSITORY[:TAG] ,在本機提交後顯示成為 docker images 的 REPOSITORY 及 TAG ,並且產生一個新的 hash code
mtchang@mt ~ $ sudo docker commit -m="jangmt/lamp v1" -a="mtchang" b29f95d30b68 mtchang/lamp
cfa9495f5d8f62278ff235a6124309b81aff48afdec74adb625d118a39b36cbf
# 檢查看看提交後的 docker images
mtchang@mt ~ $ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mtchang/lamp latest cfa9495f5d8f 29 seconds ago 248.9 MB
Docker HUB 提交 push
# 版本更新,在提交一次。
$ docker commit -m="jangmt/lamp v4" -a="mtchang" 0b65d5ceae03 mtchang/lamp
59480b898c911ed8551eb18c24bf35992d2561714be15c0919f9c5a15008290d
# 登入 docker hub ,先確定你在 docker hub 已經有帳號了
mtchang@mt ~ $ sudo docker login
Username: mtchang
Password: oooxxx
Email: mtchang.tw@gmail.com
Login Succeeded
# 檢查一下最後要提交的 images
mtchang@mt ~ $ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mtchang/lamp latest cfa9495f5d8f 43 minutes ago 248.9 MB
# docker push 提交 mtchang/lamp ,系統會檢查 hash code 如果影像檔有提交過了,會跳過不重複提交。基本上影像檔都是由很多小的影像檔組合成的。
mtchang@mt ~ $ sudo docker push mtchang/lamp
The push refers to a repository [mtchang/lamp] (len: 1)
Sending image list
Pushing repository mtchang/lamp (1 tags)
511136ea3c5a: Image already pushed, skipping
27d47432a69b: Image already pushed, skipping
5f92234dcf1e: Image already pushed, skipping
51a9c7c1f8bb: Image already pushed, skipping
5ba9dab47459: Image already pushed, skipping
cfa9495f5d8f: Image successfully pushed
Pushing tag for rev [cfa9495f5d8f] on {https://cdn-registry-1.docker.io/v1/repositories/mtchang/lamp/tags/latest}
(5) 其他 Docker 主題
(5.1)讓 Docker 程式可以持續工作
當我們要啟動一個 container 後,並且讓它執行一些服務又要可以讓服務成為背景以服務的型態工作,這時候需要透過 supervisord 當成 startup 的啟動程式,呼叫啟動我們需要的 service,並且讓他在系統中可以持續的工作。
說明文件:
https://docs.docker.com/articles/using_supervisord/ Using Supervisor with Docker
http://supervisord.org/ Supervisord
(5.2) Docker API
應用案例:
https://github.com/crosbymichael/dockerui
官方API文件:
https://docs.docker.com/reference/api/docker_remote_api/
(6) 使用現成的 docker images ,以 mtchang/lamp 為例
如何使用 mtchang/lamp 這個 docker images
https://registry.hub.docker.com/u/mtchang/lamp/
1. 使用這個 docker images
# 從 docker hub 抓取這個版本的 lamp
$ sudo docker pull mtchang/lamp
# 看看本地端的 images 是否抓好了
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mtchang/lamp latest 59480b898c91 7 minutes ago 578.1 MB
...(skip)...
# 以 mtchang/lamp 的 images 啟動一個 container ,動作是本地端的 tcp 8080:對應到 container 中的 tcp 80 port
# 將本地端指定的目錄 對應到 伺服器端目錄 ,並且啟動 /usr/bin/supervisord 讓 container 可以停在系統內
# sudo docker run -d -p 8080:80 -v 本地端目錄:伺服器端目錄 mtchang/lamp /usr/bin/supervisord
# example:
$ sudo docker run -d -p 8080:80 -v /home/mtchang/app:/var/www/html/test mtchang/lamp /usr/bin/supervisord
# 觀看是否常駐
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0b65d5ceae03 mtchang/lamp:latest "/usr/bin/supervisor About a minute ago Up About a minute 0.0.0.0:8080->80/tcp jolly_brattain
2. LAMP 功能測試:
(1) http://<your host>:8080/
LAMP server
https://registry.hub.docker.com/u/mtchang/lamp/
by mtchang.tw@gmail.com
(2) http://<your host>:8080/test/
會出現對應到本地端目錄 /home/mtchang/app 目錄的內容
(3)phpmyadmin http://192.168.123.59:8080/phpmyadmin/
mysql root password is "dockermysql"
(4)sqlbuddy http://192.168.123.59:8080/sqlbuddy
3. 結束這個 container 的程式
# 使用 docker attach 進入 container 的 console 使用 ctrl + c 中斷程式。
$ docker attach 0b65d5ceae03
^C2015-03-07 15:33:10,571 WARN received SIGINT indicating exit request
(7) 使用 dockerfile 建立 images:
透過用 dockerfile 配置可以快速生成 docker image 並實現 container 部署 。
ref: http://dockerone.com/article/101
範例:
https://registry.hub.docker.com/u/tutum/lamp/dockerfile/
官方說明文件:
https://docs.docker.com/articles/dockerfile_best-practices/
7.1 本機 dockerfile 建立
# 在本地端的目錄下,建立一個檔案名稱為 Dockerfile
#
# FROM:你的 base image 為基底
# MAINTAINER:維護 images 的人
# RUN:在 images 建立過程執行的指令
# ADD:將本機的檔案或遠端的檔案加入到 image 內的目錄
# 語法請參考:https://docs.docker.com/reference/builder/
# 底下 Dockerfile 參考 https://registry.hub.docker.com/u/tutum/lamp/dockerfile/
mtchang@mt ~/SCM_code/docker/apdemo $ vim Dockerfile
FROM ubuntu:latest
MAINTAINER mtchang <mtchang.tw@gmail.com>
# Install packages
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
apt-get -y install supervisor git apache2 libapache2-mod-php5 mysql-server php5-mysql pwgen php-apc php5-mcrypt && \
echo "ServerName localhost" >> /etc/apache2/apache2.conf
#Enviornment variables to configure php
ENV PHP_UPLOAD_MAX_FILESIZE 10M
ENV PHP_POST_MAX_SIZE 10M
# 執行 docker build 會直接依據 dockerfile 內容編譯 image
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker build -t mtchang/apdemo . (<-- 點)
# 注意每個過程都會有各 hash code
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:latest
---> 5ba9dab47459
Step 1 : MAINTAINER mtchang <mtchang.tw@gmail.com>
---> Running in 584aa4bb3e1c
---> 6c304964c942
Removing intermediate container 584aa4bb3e1c
Step 2 : ENV DEBIAN_FRONTEND noninteractive
---> Running in 9522aec6d092
---> 4eb8188f88d7
Removing intermediate container 9522aec6d092
Step 3 : RUN apt-get update && apt-get -y install supervisor git apache2 libapache2-mod-php5 mysql-server php5-mysql pwgen php-apc php5-mcrypt && echo "ServerName localhost" >> /etc/apache2/apache2.conf
---> Running in b7c3e263758c
...(省略數百行)...
Removing intermediate container cd49243be07b
Step 6 : EXPOSE 8080
---> Running in a4843a5a0c8e
---> c31129378fe8
Removing intermediate container a4843a5a0c8e
Successfully built c31129378fe8
# 第二次編譯速度會比較快,因為使用了 cache
mtchang@mt ~/SCM_code/docker/apdemo $ vim Dockerfile
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker build -t mtchang/apdemo .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:latest
---> 5ba9dab47459
Step 1 : MAINTAINER mtchang <mtchang.tw@gmail.com>
---> Using cache
---> 6c304964c942
Step 2 : ENV DEBIAN_FRONTEND noninteractive
---> Using cache
---> 4eb8188f88d7
Step 3 : RUN apt-get update && apt-get -y install supervisor git apache2 libapache2-mod-php5 mysql-server php5-mysql pwgen php-apc php5-mcrypt && echo "ServerName localhost" >> /etc/apache2/apache2.conf
---> Using cache
---> b0d088b36fe3
Step 4 : ENV PHP_UPLOAD_MAX_FILESIZE 10M
---> Using cache
---> 61e966ed8a2d
Step 5 : ENV PHP_POST_MAX_SIZE 10M
---> Using cache
---> 431d2a1cc310
Successfully built 431d2a1cc310
# 建立的影像檔案 mtchang/apdemo
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mtchang/apdemo latest 431d2a1cc310 14 minutes ago 426 MB
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker login
Username (mtchang):
Login Succeeded
# 可以單獨將這個檔案 push 到 docker hub 上面
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker push mtchang/apdemo
The push refers to a repository [mtchang/apdemo] (len: 1)
Sending image list
Pushing repository mtchang/apdemo (1 tags)
511136ea3c5a: Image already pushed, skipping
27d47432a69b: Image already pushed, skipping
5f92234dcf1e: Image already pushed, skipping
51a9c7c1f8bb: Image already pushed, skipping
5ba9dab47459: Image already pushed, skipping
6c304964c942: Image already pushed, skipping
4eb8188f88d7: Image already pushed, skipping
b0d088b36fe3: Image already pushed, skipping
61e966ed8a2d: Image already pushed, skipping
431d2a1cc310: Image already pushed, skipping
Pushing tag for rev [431d2a1cc310] on {https://cdn-registry-1.docker.io/v1/repositories/mtchang/apdemo/tags/latest}
# 以上為依據 dockerfile 的建立方法,但是產生的檔案只有本機可以使用。 push 到 docker hub 仍是影像檔案型態,使用者看不到你的 dockerfile 。
7.2 配合 github 的 dockerfile 建立
Docker hub 可以從 github 的儲存庫中,依據 Dockerfile 的內容自動建立影像檔案。
所以請先在 github 中建立一個 Dockerfile 檔案, README 有則是最好。
在 Docker HUB 內建立一個 REPOS 選擇 Github 的儲存庫。
在 docker hub 內選擇 automated Build 選項。
把 Active 打勾,並確認路徑是否正確。
按下 save and trigger build 就會自動建立 dockerfile 檔案了。
7.3 使用及測試
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker pull mtchang/apdemo
Pulling repository mtchang/apdemo
d0611a67283c: Download complete
d0611a67283c: Pulling image (latest) from mtchang/apdemo
fa4fd76b09ce: Download complete
1c8294cc5160: Download complete
117ee323aaa9: Download complete
2d24f826cb16: Download complete
d5f32e0f2638: Download complete
f6b232724428: Download complete
a392b7a15278: Download complete
ad48e990d540: Download complete
Status: Downloaded newer image for mtchang/apdemo:latest
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mtchang/apdemo latest d0611a67283c 17 minutes ago 425.9 MB
mtchang@mt ~/SCM_code/docker/apdemo $ sudo docker run -i -t -p 8080:80 mtchang/apdemo /bin/bash
root@c88dac59dbab:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:08
inet addr:172.17.0.8 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:8/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@c88dac59dbab:/# /etc/init.d/apache2 restart
* Restarting web server apache2
# Docker HOST 上面看到的 iptables 狀況
mt ~ # iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.8 172.17.0.8 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.8:80
# 測試網頁
http://<Docker HOST IP>:8080/
(8) QA討論:
1. DockerFile 類似 Redhat 上面的 kickstart 功能,可以預先指定所需安裝設定的資訊。但這樣兩者只差別在於 docker images 下載並產生 container 和 OS 安裝速度的差別。
Docker 的特色 佈署快 、版本控制、Isolation。但我用 kickstart 自動化安裝一個精簡版的 Linux 也很快,只比 Docker 慢一點點而已。所以他的特點到底適合哪種應用?
(9) Learn More: