1、概述html
1.1 基本概念:java
Docker 是一個開源的應用容器引擎,基於 Go 語言 並聽從Apache2.0協議開源。Docker 可讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,而後發佈到任何流行的 Linux 機器上,也能夠實現虛擬化。容器是徹底使用沙箱機制,相互之間不會有任何接口(相似 iPhone 的 app),更重要的是容器性能開銷極低。mysql
1.2 優點:nginx
簡化程序:
Docker 讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的 Linux 機器上,即可以實現虛擬化。Docker改變了虛擬化的方式,使開發者能夠直接將本身的成果放入Docker中進行管理。方便快捷已是 Docker的最大優點,過去須要用數天乃至數週的 任務,在Docker容器的處理下,只須要數秒就能完成。web
節省開支:
一方面,雲計算時代到來,使開發者沒必要爲了追求效果而配置高額的硬件,Docker 改變了高性能必然高價格的思惟定勢。Docker 與雲的結合,讓雲空間獲得更充分的利用。不只解決了硬件管理的問題,也改變了虛擬化的方式。sql
1.3 與傳統VM特性對比:docker
做爲一種輕量級的虛擬化方式,Docker在運行應用上跟傳統的虛擬機方式相比具備顯著優點:shell
Docker容器很快,啓動和中止能夠在秒級實現,這相比傳統的虛擬機方式要快得多。數據庫
Docker容器對系統資源需求不多,一臺主機上能夠同時運行數千個Docker容器。apache
Docker經過相似Git的操做來方便用戶獲取、分發和更新應用鏡像,指令簡明,學習成本較低。
Docker經過Dockerfile配置文件來支持靈活的自動化建立和部署機制,提升工做效率。
Docker容器除了運行其中的應用以外,基本不消耗額外的系統資源,保證應用性能的同時,儘可能減少系統開銷。
Docker利用Linux系統上的多種防禦機制實現了嚴格可靠的隔離。從1.3版本開始,Docker引入了安全選項和鏡像簽名機制,極大地提升了使用Docker的安全性。
特性 | 容器 | 虛擬機 |
啓動速度 | 秒級 | 分鐘級 |
硬盤使用 | 通常爲MB | 通常爲GB |
性能 | 接近原生 | 弱於原生 |
系統支持量 | 單機支持上千個容器 | 通常幾十個 |
隔離性 | 安全隔離 | 徹底隔離 |
1.4 基礎架構
Docker 使用客戶端-服務器 (C/S) 架構模式,使用遠程API來管理和建立Docker容器。
Docker 容器經過 Docker 鏡像來建立。
容器與鏡像的關係相似於面向對象編程中的對象與類。
Docker | 面向對象 |
---|---|
容器 | 對象 |
鏡像 | 類 |
1.5 Docker技術的基礎:
namespace,容器隔離的基礎,保證A容器看不到B容器. 6個名空間:User,Mnt,Network,UTS,IPC,Pid
cgroups,容器資源統計和隔離。主要用到的cgroups子系統:cpu,blkio,device,freezer,memory
unionfs,典型:aufs/overlayfs,分層鏡像實現的基礎
1.6 Docker組件:
docker Client客戶端————>向docker服務器進程發起請求,如:建立、中止、銷燬容器等操做
docker Server服務器進程—–>處理全部docker的請求,管理全部容器
docker Registry鏡像倉庫——>鏡像存放的中央倉庫,可看做是存放二進制的scm
2、安裝部署
2.1 準備條件
目前,CentOS 僅發行版本中的內核支持 Docker。
Docker 運行在 CentOS 7 上,要求系統爲64位、系統內核版本爲 3.10 以上。
Docker 運行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系統爲64位、系統內核版本2.6.32-431 或者更高版本。
2.2 安裝docker
yum install docker -y #安裝 systemctl start docker #啓動 systemctl enable docker #設置開機自啓動
2.3 基本命令
docker search centos #搜索鏡像
默認從國外拉去,速度很慢,可使用daocloud配置加速
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://d6f11267.m.daocloud.io 腳本是寫入 echo "{\"registry-mirrors\": [\"http://d6f11267.m.daocloud.io\"]}"> /etc/docker/daemon.json systemctl restart docker #重啓失效
根據需求拉取鏡像:
docker pull docker.io/ansible/centos7-ansible
拉去search到的所有鏡像:
for i in `docker search centos|awk '!/NAME/{print $2}'`;do docker pull $i;done
查看本地鏡像:
docker images
2.4 命令整理:
容器操做:
docker create # 建立一個容器可是不啓動它 docker run # 建立並啓動一個容器 docker stop # 中止容器運行,發送信號SIGTERM docker start # 啓動一箇中止狀態的容器 docker restart # 重啓一個容器 docker rm # 刪除一個容器 docker kill # 發送信號給容器,默認SIGKILL docker attach # 鏈接(進入)到一個正在運行的容器 docker wait # 阻塞一個容器,直到容器中止運行
獲取容器信息:
docker ps # 顯示狀態爲運行(Up)的容器 docker ps -a # 顯示全部容器,包括運行中(Up)的和退出的(Exited) docker inspect # 深刻容器內部獲取容器全部信息 docker logs # 查看容器的日誌(stdout/stderr) docker events # 獲得docker服務器的實時的事件 docker port # 顯示容器的端口映射 docker top # 顯示容器的進程信息 docker diff # 顯示容器文件系統的先後變化
導出容器:
docker cp # 從容器裏向外拷貝文件或目錄 docker export # 將容器整個文件系統導出爲一個tar包,不帶layers、tag等信息
執行:
docker exec # 在容器裏執行一個命令,能夠執行bash進入交互式
鏡像操做:
docker images # 顯示本地全部的鏡像列表 docker import # 從一個tar包建立一個鏡像,每每和export結合使用 docker build # 使用Dockerfile建立鏡像(推薦) docker commit # 從容器建立鏡像 docker rmi # 刪除一個鏡像 docker load # 從一個tar包建立一個鏡像,和save配合使用 docker save # 將一個鏡像保存爲一個tar包,帶layers和tag信息 docker history # 顯示生成一個鏡像的歷史命令 docker tag # 爲鏡像起一個別名
鏡像倉庫(registry)操做:
docker login # 登陸到一個registry docker search # 從registry倉庫搜索鏡像 docker pull # 從倉庫下載鏡像到本地 docker push # 將一個鏡像push到registry倉庫中
2.5 簡單實踐操做
運行並進入容器操做:
docker run -i -t docker.io/1832990/centos6.5 /bin/bash
-t 表示在新容器內指定一個僞終端或終端;
-i表示容許咱們對容器內的 (STDIN) 進行交互;
-d表示將容器在後臺運行;
/bin/bash 。這將在容器內啓動 bash shell;
因此當容器(container)啓動以後,咱們會獲取到一個命令提示符:
在容器內咱們安裝mysql並設置開機自啓動,將修改後的鏡像提交:
docker ps -l 查詢容器ID docker commit -m "功能" -a "用戶信息" ID tag 提交修改後的鏡像
docker inspect ID 查看詳細信息 docker push ID 上傳docker鏡像
利用DockerFile建立鏡像
使用命令 docker build , 須要建立一個 Dockerfile 文件,其中包含一組指令來告訴 Docker 如何構建鏡像。
mkdir DockerFile cd DockerFile cat > Dockerfile <<EOF FROM 603dd3515fcc MAINTAINER Docker xuel RUN yum install mysql mysql-server -y RUN mddir /etc/sysconfig/network RUN /etc/init.d/mysqld start EOF
docker build -t "centos6.8:mysqld" .
-t 制定repository 與tag
. 指定Dockerfile的路徑
注意一個鏡像不能超過 127 層
此外,還能夠利用 ADD 命令複製本地文件到鏡像;
用 EXPOSE 命令來向外部開放端口;
用 CMD 命令來描述容器啓動後運行的程序等。
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
2.6 Dockerfile詳解
Dockerfile的指令是忽略大小寫的,建議使用大寫,使用 # 做爲註釋,每一行只支持一條指令,每條指令能夠攜帶多個參數。
Dockerfile的指令根據做用能夠分爲兩種,構建指令和設置指令。
構建指令:用於構建image,其指定的操做不會在運行image的容器上執行;
設置指令:用於設置image的屬性,其指定的操做將在運行image的容器中執行。
FROM(指定基礎image)
構建指令,必須指定且須要在Dockerfile其餘指令的前面。後續的指令都依賴於該指令指定的image。FROM指令指定的基礎image能夠是官方遠程倉庫中的,也能夠位於本地倉庫。
該指令有兩種格式:
FROM <image> #指定基礎image爲該image的最後修改的版本 FROM <image>:<tag> #指定基礎image爲該image的一個tag版本。
MAINTAINER(用來指定鏡像建立者信息)
構建指令,用於將image的製做者相關的信息寫入到image中。當咱們對該image執行docker inspect命令時,輸出中有相應的字段記錄該信息。
MAINTAINER <name>
RUN(安裝軟件用)
構建指令,RUN能夠運行任何被基礎image支持的命令。如基礎image選擇了ubuntu,那麼軟件管理部分只能使用ubuntu的命令。
RUN <command> (the command is run in a shell - `/bin/sh -c`) RUN ["executable", "param1", "param2" ... ] (exec form)
CMD(設置container啓動時執行的操做)
設置指令,用於container啓動時指定的操做。該操做能夠是執行自定義腳本,也能夠是執行系統命令。該指令只能在文件中存在一次,若是有多個,則只執行最後一條。
CMD ["executable","param1","param2"] (like an exec, this is the preferred form) CMD command param1 param2 (as a shell)
ENTRYPOINT指定的是一個可執行的腳本或者程序的路徑,該指定的腳本或者程序將會以param1和param2做爲參數執行。因此若是CMD指令使用上面的形式,那麼Dockerfile中必需要有配套的ENTRYPOINT。當Dockerfile指定了ENTRYPOINT,那麼使用下面的格式:
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
ENTRYPOINT(設置container啓動時執行的操做)
設置指令,指定容器啓動時執行的命令,能夠屢次設置,可是隻有最後一個有效。
ENTRYPOINT ["executable", "param1", "param2"] (like an exec, the preferred form) ENTRYPOINT command param1 param2 (as a shell)
該指令的使用分爲兩種狀況,一種是獨自使用,另外一種和CMD指令配合使用。
當獨自使用時,若是你還使用了CMD命令且CMD是一個完整的可執行的命令,那麼CMD指令和ENTRYPOINT會互相覆蓋只有最後一個CMD或者ENTRYPOINT有效。
# CMD指令將不會被執行,只有ENTRYPOINT指令被執行 CMD echo 「Hello, World!」 ENTRYPOINT ls -l
另外一種用法和CMD指令配合使用來指定ENTRYPOINT的默認參數,這時CMD指令不是一個完整的可執行命令,僅僅是參數部分;ENTRYPOINT指令只能使用JSON方式指定執行命令,而不能指定參數。
FROM ubuntu CMD ["-l"] ENTRYPOINT ["/usr/bin/ls"]
USER(設置container容器的用戶)
設置指令,設置啓動容器的用戶,默認是root用戶
# 指定memcached的運行用戶 ENTRYPOINT ["memcached"] USER daemon 或 ENTRYPOINT ["memcached", "-u", "daemon"]
EXPOSE(指定容器須要映射到宿主機器的端口)
設置指令,該指令會將容器中的端口映射成宿主機器中的某個端口。當你須要訪問容器的時候,能夠不是用容器的IP地址而是使用宿主機器的IP地址和映射後的端口。要完成整個操做須要兩個步驟,首先在Dockerfile使用EXPOSE設置須要映射的容器端口,而後在運行容器的時候指定-p選項加上EXPOSE設置的端口,這樣EXPOSE設置的端口號會被隨機映射成宿主機器中的一個端口號。也能夠指定須要映射到宿主機器的那個端口,這時要確保宿主機器上的端口號沒有被使用。EXPOSE指令能夠一次設置多個端口號,相應的運行容器的時候,能夠配套的屢次使用-p選項。
# 映射一個端口 EXPOSE port1 # 相應的運行容器使用的命令 (主機(宿主)端口:容器端口) docker run -p port1 image # 映射多個端口 EXPOSE port1 port2 port3 # 相應的運行容器使用的命令 docker run -p port1 -p port2 -p port3 image # 還能夠指定須要映射到宿主機器上的某個端口號 docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image
端口映射是docker比較重要的一個功能,緣由在於咱們每次運行容器的時候容器的IP地址不能指定而是在橋接網卡的地址範圍內隨機生成的。宿主機器的IP地址是固定的,咱們能夠將容器的端口的映射到宿主機器上的一個端口,免去每次訪問容器中的某個服務時都要查看容器的IP的地址。對於一個運行的容器,可使用docker port加上容器中須要映射的端口和容器的ID來查看該端口號在宿主機器上的映射端口。
ENV(用於設置環境變量)
構建指令,在image中設置一個環境變量。
ENV <key> <value>
設置了後,後續的RUN命令均可以使用,container啓動後,能夠經過docker inspect查看這個環境變量,也能夠經過在docker run --env key=value時設置或修改環境變量。
假如你安裝了JAVA程序,須要設置JAVA_HOME,那麼能夠在Dockerfile中這樣寫:
ENV JAVA_HOME /path/to/java/dirent
ADD(從src複製文件到container的dest路徑)
構建指令,全部拷貝到container中的文件和文件夾權限爲0755,uid和gid爲0;若是是一個目錄,那麼會將該目錄下的全部文件添加到container中,不包括目錄;若是文件是可識別的壓縮格式,則docker會幫忙解壓縮(注意壓縮格式);若是<src>是文件且<dest>中不使用斜槓結束,則會將<dest>視爲文件,<src>的內容會寫入<dest>;若是<src>是文件且<dest>中使用斜槓結束,則會<src>文件拷貝到<dest>目錄下。
ADD <src> <dest>
<src> 是相對被構建的源目錄的相對路徑,能夠是文件或目錄的路徑,也能夠是一個遠程的文件url;
<dest> 是container中的絕對路徑
VOLUME(指定掛載點)
設置指令,使容器中的一個目錄具備持久化存儲數據的功能,該目錄能夠被容器自己使用,也能夠共享給其餘容器使用。咱們知道容器使用的是AUFS,這種文件系統不能持久化數據,當容器關閉後,全部的更改都會丟失。當容器中的應用有持久化數據的需求時能夠在Dockerfile中使用該指令。
FROM base VOLUME ["/tmp/data"]
WORKDIR(切換目錄)
設置指令,能夠屢次切換(至關於cd命令),對RUN,CMD,ENTRYPOINT生效。
# 在 /p1/p2 下執行 vim a.txt WORKDIR /p1 WORKDIR p2 RUN vim a.txt
2.7 鏡像導入導出
導出鏡像到本地:
docker save -o centos6.5.tar centos6.5 或 docker export f9c99092063c >centos6.5.tar
從本地將鏡像導入:
docker load --input centos6.5.tar 或 docker load < centos6.5.tar
docker rm刪除已經終止的容器 docker -f rm 能夠刪除正在運行的容器
修改已經運行的後臺容器:
docker exec -it CONTAINER ID /bin/bash
3、存儲
3.1數據盤
docker的鏡像使用一層一層文件組成的,docker的一些存儲引擎能夠處理怎麼樣存儲這些文件。
docker inspect centos #查看容器詳細信息
信息下方的Layers,就是centos的文件,這些東西都是隻讀的不能去修改,咱們基於這個鏡像去建立的鏡像和容器也會共享這些文件層,而docker會在這些層上面去添加一個可讀寫的文件層。若是須要修改一些文件層裏面的東西的話,docker會複製一份到這個可讀寫的文件層裏面,若是刪除容器的話,那麼也會刪除它對應的可讀寫的文件層的文件。
若是有些數據你想一直保存的話,好比:web服務器上面的日誌,數據庫管理系統裏面的數據,那麼咱們能夠把這些數據放到data volumes數據盤裏面。它上面的數據,即便把容器刪掉,也仍是會永久保留。建立容器的時候,咱們能夠去指定數據盤。其實就是去指定一個特定的目錄。
docker run -i -t -v /mnt --name nginx docker.io/nginx /bin/bash
-v:制定掛載到容器內的目錄
使用docker inspect 容器ID能夠查看掛載目錄對應於宿主機的物理文件路徑
一樣,咱們可使用將制定物理宿主機的目錄掛載到容器的制定目錄下:
將宿主機目錄掛載到容器內:
docker run -d -p 80:80 --name nginx -v /webdata/wordpress:/usr/share/nginx/html docker.io/sergeyzh/centos6-nginx
-d 後臺運行
--name 給運行的容器命名
-v 宿主機目錄:容器目錄 將宿主機目錄掛載在容器內
-p 宿主機端口:容器監聽端口 將容器內應用監聽端口映射到物理宿主機的特定端口上
映射多個物理目錄:(多寫幾個-v便可)
3.2 數據容器:
能夠建立一個數據容器,也就是再建立容器是指定這個容器的數據盤,而後讓其餘容器可使用這個容器做爲他們的數據盤,有點像繼承了這個數據容器指定的數據盤做爲數據盤。
首先建立一個數據容器命名爲newnginx
docker create -v /mnt -it --name newnginx docker.io/nginx /bin/bash
利用此數據容器容器運行一個容器nginx1,在數據目錄/mnt 下建立一個文件
docker run --volumes-from newnginx --name nginx1 -it docker.io/nginx /bin/bash
利用數據容器在建立一個容器nginx2,查看數據目錄下容器nginx1建立的文件依舊存在,同理在nginx2的/mnt下建立文件,其餘基於數據容器運行的新容器也能夠看到文件
3.3 數據盤管理:
在刪除容器時,docker默認不會刪除其數據盤。
docker volume ls #查看數據盤 docker volume ls -f dangling=true #查看未被容器使用的數據盤 docker volume rm VOLUME NAME #刪除數據盤
若是想要刪除容器時,同時刪除掉其數據盤,那麼可使用-v
參數。
docker rm -v newnginx
4、網絡
docker提供幾種網絡,它決定容器之間和外界和容器之間如何去相互通訊。
docker network ls #查看網絡
當Docker進程啓動時,會在主機上建立一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器會鏈接到這個虛擬網橋上。虛擬網橋的工做方式和物理交換機相似,這樣主機上的全部容器就經過交換機連在了一個二層網絡中。從docker0子網中分配一個IP給容器使用,並設置docker0的IP地址爲容器的默認網關。在主機上建立一對虛擬網卡veth pair設備,Docker將veth pair設備的一端放在新建立的容器中,並命名爲eth0(容器的網卡),另外一端放在主機中,以vethxxx這樣相似的名字命名,並將這個網絡設備加入到docker0網橋中。
4.1 bridge橋接網絡
除非建立容器的時候指定網絡,否則容器就會默認的使用橋接網絡。屬於這個網絡的容器之間能夠相互通訊,不過外界想要訪問到這個網絡的容器呢,需使用橋接網絡,有點像主機和容器之間的一座橋,對容器有一點隔離做用。實際是在iptables作了DNAT規則,實現端口轉發功能。可使用iptables -t nat -vnL查看。
4.2 host主機網絡
若是啓動容器的時候使用host模式,那麼這個容器將不會得到一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出本身的網卡,配置本身的IP等,而是使用宿主機的IP和端口。可是,容器的其餘方面,如文件系統、進程列表等仍是和宿主機隔離的。只用這種網絡的容器會使用主機的網絡,這種網絡對外界是徹底開放的,可以訪問到主機,就能訪問到容器。
4.3 使用none模式
Docker容器擁有本身的Network Namespace,可是,並不爲Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等信息。須要咱們本身爲Docker容器添加網卡、配置IP等。使用此種網絡的容器會徹底隔離。
4.4 簡單演示:
啓動兩個容器,查看其容器內部IP地址
for i in `docker ps |grep -v "CONTAINER"|awk '{print $1}'`;do docker inspect $i|grep 'IPAddress';done
查看橋接模式下主機內部容器之間和容器與宿主機直接都可正常通信
docker inspect 容器ID
查看host建立的容器內部沒有IP地址,它使用的爲宿主機的地址
docker run -d --net host docker.io/sergeyzh/centos6-nginx
查看host建立的容器內部沒有IP地址,它使用的爲宿主機的地址
docker run -d --net none docker.io/sergeyzh/centos6-nginx
4.5 容器端口:
若是想讓外界能夠訪問到,基於bridge網絡建立的容器提供的服務,那你能夠告訴Docker你要使用哪些接口。若是想查看鏡像會使用哪些端口,ExposedPorts,能夠獲悉鏡像使用哪些端口。
docker run -d -p 80 docker.io/sergeyzh/centos6-nginx docker port 09648b2ff7f6
-p 參數會在宿主機隨機映射一個高端口到容器內的指定端口
docker run -d -p 80:80 docker.io/sergeyzh/centos6-nginx #將宿主機的80端口映射到容器的80端口