1. 程式人生 > >Docker入門實戰

Docker入門實戰

基本概念

Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上。

Docker是一個重新定義了程式開發測試、交付和部署過程的開放平臺,Docker則可以稱為構建一次,到處執行,這就是docker提出的“Build once,Run anywhere”

備註:java提出的是” compile OnceRun 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’:在容器內執行的命令

該命令執行過程

如果本地有ubuntu這個image就從它建立容器,否則從公有倉庫下載

image建立容器

分配一個檔案系統,並在只讀的image層外面掛載一層可讀寫的層

從宿主主機配置的網橋介面中橋接一個虛擬介面到容器中去

從地址池配置1ip地址給容器

執行你指定的程式,在這裡啟動一個/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_clientIP、域名

172.17.0.25     db               #docker生成的mysql_serverIP、域名

總結:可以發現dockermysql_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 taghttps錯誤問題解決:

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