Docker入門實戰
基本概念
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上。
Docker是一個重新定義了程式開發測試、交付和部署過程的開放平臺,Docker則可以稱為構建一次,到處執行,這就是docker提出的“Build once,Run anywhere”
備註:java提出的是” compile Once,Run Anywhere”
Docker與linux核心的關係
docker與linux核心的關係
Cgroup: 對資源進行限制(如對物理資源CPU、記憶體、I/O的限制)
Namespace:對程序進行隔離
Chroot: 能改變當前執行的程序和子程序的根目錄
AUFS:聯合檔案系統,Docker利用AUFS將不同的Layer結合到1個image中去
Docker架構
Docker採用C/S架構,客戶端與伺服器端不一定要在一起。客戶端可以執行在windows、linux等機器上,然後伺服器端必須執行在linux 64bit的作業系統上。
Docker“元件間”關係
ü 主機:執行容器的機器
ü 映象:檔案的層次結構,以及包含如何執行容器的元資料, Dockerfile中的每條命令都會在檔案系統中建立一個新的層次結構,檔案系統在這些層次上構建起來,映象就構建於這些聯合的檔案系統之上
ü 容器:一個從映象中啟動,包含正在執行的程式的程序
ü Registry(映象倉庫):存放映象的地方,如Docker Hub
ü Volumn(卷):將物理機的資料夾掛載到容器內部.與openstack的volumn不一樣,openstack中的卷是塊儲存,不能共享。而這裡的volumn可以共享。
ü Dockerfile:用於建立映象的指令碼
Docker應用場景
面向開發人員:快速開發、交付應用程式
主要體現在三個方面:
ü 程式碼一致:
在沒有docker之前,開發、測試、生成環境可能不一樣,如釋出某個服務的埠時,開發是1000,而生產是2000,這就導致配置檔案不一致。然而使用docker後,我在容器內的埠都是一樣的,而容器對外暴露的埠可能不一樣。
ü 開發環境與生產環境的一致性
我們知道,在生產環境的部署比較複雜,服務非常繁多。通過docker,我們可以單機版上通過容器來模擬生產環境的分散式環境。從而讓開發人員的開發更有效率。
ü 快速部署
可以將docker理解為輕量級的虛擬機器,啟動docker容器速度很快,啟動虛擬機器很慢。
面向運維人員:降低運維成本
ü 節約安裝各種軟體的時間。
在沒有docker之前,在部署程式之前,勢必要搭建環境,而搭建環境很花費時間,還要解決環境的各種依賴,而docker通過映象機制,將你的程式碼和執行環境直接打包成映象,扔到容器啟動即可。
ü 降低運維成本。
在沒有docker之前,由於技術不斷髮展,運維也要不停的學習各種軟體的使用技能,如Node.js、redis等。有了docker,根本不用關係這些技術(或者少關心),只需要關注容器就可以了,能夠正常的釋出容器,停止容器、刪除容器、遷移容器就可以了。
面向企業: Paas層的實現
Coding.net、Oschina這些程式碼託管平臺,有個功能即提供給使用者程式的演示環境,我不知道他們底層到底採用的什麼技術,但是如果Iaas層的openstack,給使用者直接提供虛擬機器,先得太“笨重”,因為虛擬機器本身對物理機的開銷就比較大,如果採用Docker,我1臺物理機可以部署多個容器,可以降低企業的採購物理機的費用,而且執行效率上應該比採用Iaas層的方案快。
Docker基本命令
Docker安裝相關命令
這裡以在unbuntu14.04上安裝為例:
Ø 建立docker使用者並將其納入docker這個使用者組
#useradd docker -g docker
Ø 更新源
#sudo apt-get update
Ø 安裝依賴包
#sudo apt-getinstall linux-image-generic-lts-trusty
Ø 重啟
#sudo reboot
Ø 安裝docker
#sudo apt-getinstall wget // 可以通過命令which wget是否已安裝
#wget -qO-https://get.docker.com/ | sh //獲取最新版本
Ø 驗證安裝是否成功
#sudo docker runhello-world
Docker服務相關命令
Docker服務啟動|重啟|停止
#service docker start //啟動
#service docker restart //重啟
#service docker stop //停止
Docker服務對應的版本檢視
# sudo docker version
Docker環境檢視
#sudo docker info
Containers: 5
Images: 129
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 139
Execution Driver: native-0.2
Kernel Version:3.13.0-32-generic
Operating System: Ubuntu14.04.1 LTS
CPUs: 2
Total Memory: 3.673 GiB
Name: docker
ID: OWRW:DDDW:MQZD:CCKM:JDKM:5ZEP:LTBB:YG3H:QI7G:EMDE:MSMR:XDFK
Username: ningyougang
Registry:[https://index.docker.io/v1/]
WARNING: No swap limit support
Docker命令幫助
#sudo docker //檢視docker的所有命令
#sudo docker command --help //檢視單個docker命令的幫助,如docker ru--help
Docker容器相關命令
啟動一次性執行的容器
入門級例子:從ubuntu:14.04映象啟動一個容器,成功後在容器內部執行/bin/echo ‘hello world’命令,如果當前物理機沒有該映象,則執行docker pull從Docker Hub獲取映象,執行成功後,容器立馬停止
#sudo docker runubuntu:14.04 /bin/echo 'Hello world'
引數解釋
dockerrun:docker中的啟動容器命令
Ubuntu:映象名稱
14:04:映象TAG,如果不指定TAG,docker使用最新的發行版TAG:latest
/bin/echo ‘Helloworld’:在容器內執行的命令
該命令執行過程
l 如果本地有ubuntu這個image就從它建立容器,否則從公有倉庫下載
l 從image建立容器
l 分配一個檔案系統,並在只讀的image層外面掛載一層可讀寫的層
l 從宿主主機配置的網橋介面中橋接一個虛擬介面到容器中去
l 從地址池配置1個ip地址給容器
l 執行你指定的程式,在這裡啟動一個/bin/bash
啟動互動模式容器
以互動模式啟動一個容器(具體引數意義請執行dockerrun --help)
$ sudo docker run -t-i ubuntu:14.04 /bin/bash
引數解釋
-t:開啟一個終端
-i:以互動模式執行
啟動後臺模式容器
以後臺模式執行一個容器
#sudo docker run -dubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1;done"
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147
引數解釋
-d:以後臺Daemon方式執行,執行成功後會返回一個該容器的ID
以對映埠方式啟動一個Web容器
# sudo docker run -d -P training/webapp python app.py
引數解釋
-d:以後臺Daemon方式執行,執行成功後會返回一個該容器的ID
-P:埠對映,外部埠到容器埠的對映規則由docker負責
-p:自己指定埠對映規則,格式為:-p 外部埠:容器埠
通過docker ps -l,可以檢視到其PORTS列的埠對映規則
當然你也可以,手工指定埠對映規則來啟動Web容器
#sudo docker run -d -p 5000:5000 training/webapp pythonapp.py
備註:-p 完整的引數為:-p ip:hostport:port,將當前物理機的ip的埠對映到容器的埠
如果你想通過很快捷的方式檢視容器的埠
#sudo docker port 容器ID或容器名稱
檢視容器的具體資訊
以JSON的格式返回容器的具體資訊
#sudo docker inspect容器ID或容器名稱
進入容器執行命令
#sudo docker exec -it 容器ID /bin/bash
備註:一般對執行著的後臺容器,執行該命令。檢視其容器內部的情況。
檢視容器的日誌
$sudo docker logs 容器ID或容器名稱
引數解釋
-f:以滾動的形式檢視日誌,類似於linux的tail -f XXX.log
退出當前容器
$sudo exit //在容器內部執行該命令(或crtl+D),一般在互動模式下退出當前容器
備註:容器仍然執行著
建立容器
# sudo docker create--name ubuntContainer ubuntu:14.04 /bin/echo 'Hello world'
重啟容器
#sudo docker restart 容器ID
暫停容器
#sudo docker pause 容器ID //暫停
#sudo docker unpause 容器ID //解除暫停
停止容器
$sudo docker stop 容器ID或容器名稱
#docker stop $(docker ps -q -a) //一次性停止所有容器,慎用
殺死容器
$sudo docker kill 容器ID或容器名稱
刪除容器
$sudo docker rm 容器ID或容器名稱 //刪除容器,正在執行的容器不能刪除
#sudo docker rm $(docker ps -q -a) //一次性刪除所有容器,慎用
單個主機間的容器訪問
下面我們通過mysql_server容器與mysql_client容器的互聯來了解link
Ø 建立mysql_server映象,並生成一個容器
#cd /
#mkdir mysql_server
#vi Dockerfile
FROM centos:centos6
MAINTAINER ningyougang "[email protected]"
RUN yum install -y mysql-server mysql
RUN /etc/init.d/mysqld start &&\
mysql -e"grant all privileges on *.* to 'root'@'%' identified by'mysql';"&&\
mysql -e"grant all privileges on *.* to 'root'@'localhost' identified by'mysql';"&&\
mysql -u root-pmysql -e "show databases;"
EXPOSE 3306
CMD ["/usr/bin/mysqld_safe"]
# sudo docker build -t ningyougang/mysql_server . //生成映象
#sudo docker run --name=mysql_server -d -Pningyougang/mysql_server //生成mysql_server容器
Ø 建立mysql_client映象,並生成一個link到mysql_server的client容器
#cd /
#mkdir mysql_client
#vi Dockerfile
FROM centos:centos6
MAINTAINER ningyougang "[email protected]"
RUN yum install -y mysql
#sudo docker build -t ningyougang/mysql_client . //生成映象
#sudo dockerrun --name=mysql_client1 --link=mysql_server:db -t -i ningyougang/mysql_client/usr/bin/mysql -h db -u root -pmysq //生成mysql_client容器
引數解釋
--link:<name or id>:alias
通過上面的命令,link中的別名(alias)db即是mysql_client連線mysql_server的連線串
Ø 進入mysql_client研究其link的實現細節
#sudo docker exec-it bfc6cb037165 /bin/bash //以互動模式進入mysql_client容器內部
[[email protected]/]# env | grep DB //檢視與DB(也就是alias)相關的環境變數
DB_NAME=/mysql_client2/db
DB_PORT=tcp://172.17.0.25:3306
DB_PORT_3306_TCP_PORT=3306
DB_PORT_3306_TCP_PROTO=tcp
DB_PORT_3306_TCP_ADDR=172.17.0.25
DB_PORT_3306_TCP=tcp://172.17.0.25:3306
[[email protected] /]#vi /etc/hosts
172.17.0.27 bfc6cb037165 #docker生成的mysql_client的IP、域名
172.17.0.25 db #docker生成的mysql_server的IP、域名
總結:可以發現docker在mysql_client內通過生成別名的環境變數和profile相關的主機和域名的配置,打通了客戶端到伺服器端的tcp連線通道,而對於上層的應用,不需要關注IP、埠這些細節,只需要通過別名來訪問即可
Docker網路
跨主機間的容器訪問
Ø 使用自定義網橋連線跨主機容器
N/A,待寫
Ø 使用Ambassador實現跨主機容器
N/A, 待寫
Ø kubernetes
N/A, 待寫
資料管理
Ø 把物理機的目錄掛載到容器裡
以互動模式啟動一個容器,將物理機的/src/webapp掛載到/opt/webapp下
#sudodocker run -t -i -v /src/webapp:/opt/webappubuntu:14.04 /bin/bash
引數解釋
-v 物理機目錄:容器目錄:讀寫許可權
其中預設的許可權為可讀寫, ro:只讀
Ø 把物理機的檔案掛載到容器裡
#sudo dockerrun -t -i -v/src/webapp/test.html:/opt/webapp/test.html ubuntu:14.04 /bin/bash
Ø 把容器掛載到另外一個容器
#sudo docker create -v /dbdata --name dbdata ubuntu:14.04 //建立容器
#sudodocker run -it --volumes-from dbdata ubuntu:12.04 /bin/bash //啟動容器捲來自dbdata
引數解釋
-volumn-from:捲來自哪個容器
Ø 把容器掛載作為資料備份
#sudo docker run --volumes-from dbdata -v $(pwd):/backup--name worker ubuntu tar cvf /backup/backup.tar /dbdata
命令解釋
首先利用ubuntu映象建立一個容器worker.使用—volumes-from dbdata引數來讓容器掛載dbdata容器的資料卷;使用 –v $(pwd):/backup引數來掛載本機的當前目錄到worker容器的/backup目錄
Woker容器啟動後,執行tar命令將/dbdata壓縮到/backup/backup.tar,這樣就到物理機的當前目錄了
Ø 把容器掛載作為資料遷移
#sudo docker run -v/dbdata --name dbdata2 ubuntu /bin/bash
#sudo docker run--volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/.tar
掛載到某個容器
#sudo docker attach 容器ID
顯示執行容器的程序資訊
#sudo docker top 容器ID
從容器內部拷貝檔案到物理機
#sudo docker cp cd0f61fb8256:/opt/a.html /
列出容器裡被改變的資料夾或檔案
#sudo docker diff 容器ID
列表解釋
list列表會顯示出三種事件,A 增加的,D 刪除的,C 被改變的
Docker映象相關命令
映象檢視
#sudo docker images //在本機進行映象檢視
#sudo docker inspect 映象ID //檢視單個映象的具體資訊,以JSON格式返回
獲取映象
# sudo docker pull centos //從DockerHub獲取映象
查詢映象
#sudo docker search 映象名稱 //從DockerHub按照映象名稱模擬查詢映象
製作映象
ü 通過Dockerfile構建映象
#sudo cd / //來到根“/”下
#sudo mkdir redis //建立redis資料夾
#touch Dockerfile //建立Dockerfile檔案,檔案內容見如下灰色部分
FROM ubuntu:14.04
RUN apt-get update && apt-getinstall -y redis-server
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
#sudo docker build -t ningyougang/redis . //通過dockerbuild製作映象
引數解釋
-t:tag名稱
.:當前Dockerfile的路徑,在此處表示當前資料夾下
ü 對執行著的容器commit映象
# sudo docker commit -m "Added json gem" -a"Kate Smith" 0b2616b0e5a8 ouruser/sinatra:v2
引數解釋
-m:提交註釋,如此處你加了什麼特別的功能
-a:作者
0b2616b0e5a8:執行著的容器ID
ouruser/sinatra:v2:給當前提交的映象起名字並打標籤
備註:從上面可以看出,我們可以通過dockercommit來建立映象,但是這種方式有點凌亂而且很難複製,更好的方式是通過Dockerfile來構建映象,因為它步驟清晰並且容易複製
給映象打標籤
#sudo docker tag 5db5f8471261 ouruser/sinatra:devel //當commit or build後,對映象打標籤
引數解釋
5db5f8471261:此處的id為映象ID
備註:向私有倉庫push映象也要打標籤
推送映象到公共庫DockerHub
#sudo docker push ouruser/sinatra
下面介紹下DockerHub
DockerHub是存放映象的遠端倉庫,這裡簡單介紹下,如何使用
Ø 註冊
Ø 登入
除了通過登入頁面,您也可以通過命令列,通過指令sudo docker login登入
Ø 查詢映象
點選“Browse Repos”(或輸入https://registry.hub.docker.com/),進入映象查詢頁面
在此頁面,您可以錄入你感興趣的映象名稱,進行模糊查詢
當然你也可以通過docker search XXX進行映象查詢
Ø 使用Docker帳號繫結GitHub帳號,進行自動化構建
需要細化,沒有來得及研究
推送映象到私有庫
ü 下載私有倉庫映象
# docker pull registry #從DockerHub下載registry映象,裡面含私庫的執行環境,#當然你也可以自己下載原始碼包,自己安裝
ü 推送之前打tag
# docker tag 704ca5ad68c5 192.168.202.213:5000/newtouch/activemq #打標籤(必須先打標籤,#在推送)
該命令格式為:docker tag $ID $IP:$port/$name。push到私庫上必須先打個tag,而tag名稱的格式為:$IP:$port/$name, 個人感覺此處設計不太好或我自己沒有找到更好的辦法。如果設計良好應該可以直接push,不用打標籤.
ü Push tag到映象
#docker push 192.168.202.213:5000/newtouch/activemq #將此tag推送到私有庫
ü Push到倉庫後,遠端檢視
ü 在另外一個docker客戶端,從私有倉庫下載
#docker pull 192.168.202.213:5000/newtouch/activemq
Docker tag報https錯誤問題解決:
vi /etc/default/docker #紅色部分是新增的部分,重啟docker服務
# Docker Upstart and SysVinitconfiguration file
# Customize location of Dockerbinary (especially for development testing).
#DOCKER="/usr/local/bin/docker"
# Use DOCKER_OPTS to modify thedaemon startup options.
#DOCKER_OPTS="--dns8.8.8.8 --dns 8.8.4.4"
DOCKER_OPTS="--insecure-registry 192.168.202.213:5000"
# If you need Docker to use anHTTP proxy, it can also be specified here.
#exporthttp_proxy="http://127.0.0.1:3128/"
# This is also a handy place totweak where Docker's temporary files go.
#exportTMPDIR="/mnt/bigdrive/docker-tmp"
刪除映象
#sudo docker rmi 映象ID
列出映象的變更歷史
# docker history
Docker運維相關命令
在物理機下檢視有哪些容器
$ sudo docker ps //檢視有那些正在執行著的容器
引數解釋
-l:最近的一個容器,有可能沒有執行
-a:檢視所有的容器,包含執行和沒有執行的容器
實時列印所有容器的系統事件
#sudo docker events