基本概念
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安裝相關命令
參考: https://docs.docker.com/installation/ubuntulinux/
這里以在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 "xxxx@qq.com"
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 "xxxx@qq.com"
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容器內部
[root@bfc6cb037165/]# 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
[root@bfc6cb037165 /]#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網絡
參考: http://www.open-open.com/doc/view/f720084681bb434bbed132d2bc1493ac
跨主機間的容器訪問
Ø 使用自定義網橋連接跨主機容器
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是存放鏡像的遠程倉庫,這里簡單介紹下,如何使用
Ø 注冊
首先在https://hub.docker.com/account/signup/完成帳號注冊
Ø 登錄
帳號注冊成功后,在https://hub.docker.com/account/login/,即可登錄
除了通過登錄頁面,您也可以通過命令行,通過指令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到倉庫后,遠程查看
#curl http://192.168.202.213:5000/v1/search #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