這裏引用維基百科php
Docker是一個開放源代碼軟件項目,讓應用程序部署在軟件貨櫃下的工做能夠自動化進行,藉此在Linux操做系統上,提供一個額外的軟件抽象層,以及操做系統層虛擬化的自動管理機制html
依據行業分析公司「451研究」:「Dockers是有能力打包應用程序及其虛擬容器,能夠在任何Linux服務器上運行的依賴性工具,這有助於實現靈活性和便攜性,應用程序在任何地方均可以運行,不管是公有云、私有云、單機等。」java
中文官網地址mysql
簡單來講,Docker 經過對應用組件的封裝、分發、部署、運行等生命週期的管理,使用戶的APP(能夠是一個WEB應用或數據庫應用等等)及其運行環境可以作到「一次封裝,處處運行」。linux
一款產品從開發到上線,從操做系統,到運行環境,再到應用配置。做爲開發+運維之間的協做咱們須要關心不少東西,這也是不少互聯網公司都不得不面對的問題,特別是各類版本的迭代以後,不一樣版本環境的兼容,對運維人員都是考驗nginx
Docker之因此發展如此迅速,也是由於它對此給出了一個標準化的解決方案。git
環境配置如此麻煩,換一臺機器,就要重來一次,費力費時。不少人想到,能不能從根本上解決問題,軟件能夠帶環境安裝?也就是說,安裝的時候,把原始環境如出一轍地複製過來。開發人員利用 Docker 能夠消除協做編碼時「在個人機器上可正常工做」的問題。web
以前在服務器配置一個應用的運行環境,要安裝各類軟件,隨便拿一個 Java 項目來講,Java/Tomcat/MySQL/JDBC驅動包基本是必不可少的。安裝和配置這些東西有多麻煩就不說了,它還不能跨平臺。假如咱們是在 Windows 上安裝的這些環境,到了 Linux 又得從新裝。何況就算不跨操做系統,換另外一臺一樣操做系統的服務器,要移植應用也是很是麻煩的。redis
傳統上認爲,軟件編碼開發/測試結束後,所產出的成果便是程序或是可以編譯執行的二進制字節碼等(java爲例)。而爲了讓這些程序能夠順利執行,開發團隊也得準備完整的部署文件,讓維運團隊得以部署應用程式,開發須要清楚的告訴運維部署團隊,用的所有配置文件+全部軟件環境。不過,即使如此,仍然經常發生部署失敗的情況。sql
Docker鏡像的設計,使得Docker得以打破過去「程序即應用」的觀念。透過鏡像(images)將做業系統核心除外,運做應用程式所須要的系統環境,由下而上打包,達到應用程式跨平臺間的無縫接軌運做。
Docker是基於Go語言實現的雲開源項目。
Docker的主要目標是「Build,Ship and Run Any App,Anywhere」,也就是經過對應用組件的封裝、分發、部署、運行等生命週期的管理,使用戶的APP(能夠是一個WEB應用或數據庫應用等等)及其運行環境可以作到「一次封裝,處處運行」。
Linux 容器技術的出現就解決了這樣一個問題,而 Docker 就是在它的基礎上發展過來的。將應用運行在 Docker 容器上面,而 Docker 容器在任何操做系統上都是一致的,這就實現了跨平臺、跨服務器
。只須要一次配置好環境,換到別的機子上就能夠一鍵部署好,大大簡化了操做(能夠參考一下 Java 的一次編譯,到處運行特性)
簡單來講,Docker 的出現解決了運行環境和配置問題軟件容器,方便作持續集成並有助於總體發佈的容器虛擬化技術
首先咱們簡單瞭解一下 Docker 的實現原理
虛擬機技術
虛擬機(virtual machine)就是帶環境安裝的一種解決方案。 它能夠在一種操做系統裏面運行另外一種操做系統,好比在Windows 系統裏面運行Linux 系統。應用程序對此毫無感知,由於虛擬機看上去跟真實系統如出一轍,而對於底層系統來講,虛擬機就是一個普通文件,不須要了就刪掉,對其餘部分毫無影響。這類虛擬機完美的運行了另外一套系統,可以使應用程序,操做系統和硬件三者之間的邏輯不變。
虛擬機的缺點:
容器虛擬化技術
因爲前面虛擬機存在這些缺點,Linux 發展出了另外一種虛擬化技術:Linux 容器(Linux Containers,縮寫爲 LXC)。 Linux 容器不是模擬一個完整的操做系統,而是對進程進行隔離。有了容器,就能夠將軟件運行所需的全部資源打包到一個隔離的容器中。容器與虛擬機不一樣,不須要捆綁一整套操做系統,只須要軟件工做所需的庫資源和設置。系統所以而變得高效輕量並保證部署在任何環境中的軟件都能始終如一地運行。
比較 Docker 和傳統虛擬化方式的不一樣之處:
經過 Docker 一次構建,到處運行的特性, DevOps 獲得了極大的發展, 關於 DevOps,能夠參考知乎的這個問答
或者這個系列的文章
我的理解: DevOps 是一種優化軟件開發和運營部署之間理念,經過自動化的工具協做和溝通來完成軟件的生命週期管理,從而更快、更頻繁地交付更穩定的軟件
更快速的應用交付和部署
傳統的應用開發完成後,須要提供一堆安裝程序和配置說明文檔,安裝部署後需根據配置文檔進行繁雜的配置才能正常運行。Docker化以後只須要交付少許容器鏡像文件,在正式生產環境加載鏡像並運行便可,應用安裝配置在鏡像裏已經內置好,大大節省部署配置和測試驗證時間。
更便捷的升級和擴縮容
隨着微服務架構和Docker的發展,大量的應用會經過微服務方式架構,應用的開發構建將變成搭樂高積木同樣,每一個Docker容器將變成一塊「積木」,應用的升級將變得很是容易。當現有的容器不足以支撐業務處理時,可經過鏡像運行新的容器進行快速擴容,使應用系統的擴容從原先的天級變成分鐘級甚至秒級。
更簡單的系統運維
應用容器化運行後,生產環境運行的應用可與開發、測試環境的應用高度一致,容器會將應用程序相關的環境和狀態徹底封裝起來,不會由於底層基礎架構和操做系統的不一致性給應用帶來影響,產生新的BUG。當出現程序異常時,也能夠經過測試環境的相同容器進行快速定位和修復。
更高效的計算資源利用
Docker是內核級虛擬化,其不像傳統的虛擬化技術同樣須要額外的Hypervisor支持,因此在一臺物理機上能夠運行不少個容器實例,可大大提高物理服務器的CPU和內存的利用率。
美團
微博
蘑菇街
ps: 若是軟件開發人員對自動化運維一樣熟悉,那麼不只能夠大大下降開發和運維之間的扯皮
,還能夠提升開發人員的議價能力
docker官網:www.docker.com
docker中文網站:www.docker-cn.com/
Docker Hub官網: hub.docker.com/
以 Java 爲例,之前開發人員只須要將開發好的代碼交給運維部署便可,可是隨着敏捷開發等開發模式的流行以及愈來愈高速化的軟件開發-測試-交付-部署等流程,爲了減低運維壓力,調和開發人員和運維人員之間的關係,容器虛擬化技術(Docker)的應運而生
之前咱們僅僅是是將 Java 代碼進行交付,如今咱們是將開發環境整套進行交付.經過對開發環境(例如 Redis, MySQL 以及各類配置等)和開發代碼打包,不只更加快速,便捷,也很容易的對應用部署進行彈性擴容,也大大減小了運維壓力
相似於搬家,爲了營造一個和以前同樣的生活環境,的咱們還須要將舊家的東西搬運到新家去,假若有一天,你頗有錢,能夠將舊家所在的整棟樓搬運到新家所在地;或者說你有了超能力,能夠將舊家的環境直接複製到新家.那麼比起之前累死累活的搬運東西這種方式,哪一個更方便不就是一目瞭然的事情了~~~
當前 Docker 基本都裝在 Linux 環境下,以 CentOS 爲例,建議 CentOS6.5 以上版本,目前主流 CentOS6.8 和 CentOS7.x 都支持
Cris 的 Linux 環境以下
鏡像(Image)
Docker 鏡像(Image)就是一個只讀的模板。鏡像能夠用來建立 Docker 容器,一個鏡像能夠建立不少容器。
容器(Container)
Docker 利用容器(Container)獨立運行一個或一組應用。容器是用鏡像建立的運行實例。
它能夠被啓動、開始、中止、刪除。每一個容器都是相互隔離的、保證安全的平臺。
能夠把容器看作是一個簡易版的 Linux 環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。
容器的定義和鏡像幾乎如出一轍,也是一堆層的統一視角,惟一區別在於容器的最上面那一層是可讀可寫的。
倉庫(Repository)
倉庫(Repository)是集中存放鏡像文件的場所。
倉庫(Repository)和倉庫註冊服務器(Registry)是有區別的。倉庫註冊服務器上每每存放着多個倉庫,每一個倉庫中又包含了多個鏡像,每一個鏡像有不一樣的標籤(tag)。
倉庫分爲公開倉庫(Public)和私有倉庫(Private)兩種形式。 最大的公開倉庫是 Docker Hub(hub.docker.com/), 存放了數量龐大的鏡像供用戶下載。國內的公開倉庫包括阿里雲 、網易雲等
須要正確的理解倉儲/鏡像/容器這幾個概念:
Docker 自己是一個容器運行載體或稱之爲管理引擎。咱們把應用程序和配置依賴打包好造成一個可交付的運行環境,這個打包好的運行環境就是 image鏡像文件。只有經過這個鏡像文件才能生成容器。image 文件能夠看做是容器的模板。Docker 根據 image 文件生成容器的實例。同一個 image 文件,能夠生成多個同時運行的容器實例。
image 文件生成容器實例,稱爲鏡像文件。
一個容器運行一種服務,當咱們須要的時候,就能夠經過docker客戶端建立一個對應的運行實例,也就是咱們的容器
至於倉儲,就是放了一堆鏡像的地方,咱們能夠把鏡像發佈到倉儲中,須要的時候從倉儲中拉下來就能夠了。
Docker 簡易流程圖
以 Cris 的CentOS6.8 爲例
Docker使用EPEL發佈,RHEL系的OS首先要確保已經持有EPEL倉庫,不然先檢查OS的版本,而後安裝相應的EPEL包。
[cris@hadoop104 ~]$ sudo yum install -y epel-release
複製代碼
而後執行 Docker 安裝命令
當前在 CentOS6.8 版本若是直接執行如下命令,極可能沒法安裝 Docker
[cris@hadoop104 ~]$ sudo yum install -y docker-io
複製代碼
因此須要執行另外的命令
[root@hadoop104 cris]# yum install https://get.docker.com/rpm/1.7.1/centos-6/RPMS/x86_64/docker-engine-1.7.1-1.el6.x86_64.rpm
複製代碼
安裝後的配置文件:/etc/sysconfig/docker
Docker 版本
啓動 Docker
ps: 若是要在 CentOS7.x 上安裝 Docker, 請直接參考官網文檔便可
以阿里云爲例,首先註冊一個阿里雲帳號,而後進入鏡像加速頁面
配置本機的 Docker 文件
[cris@hadoop104 ~]$ sudo vim /etc/sysconfig/docker
複製代碼
重啓 Docker 服務
[cris@hadoop104 ~]$ sudo service docker restart
中止 docker: [肯定]
Starting docker: [肯定]
複製代碼
而後檢測 Docker 鏡像加速地址是不是咱們的阿里雲鏡像地址
ps: 若是是 CentOS7.x 版本,直接參考上面的阿里雲操做文檔
網易雲鏡像加速這裏直接略過~~~:cowboy_hat_face:
直接經過 docker run hello-world
命令,咱們能夠直接從阿里雲拉取 hello-world 鏡像並建立容器自動運行(在本地沒有找到 hello-world 的鏡像時)
docker run 命令運行流程圖
Docker 工做原理
Docker是一個Client-Server結構的系統,Docker守護進程運行在主機上,而後經過Socket鏈接從客戶端訪問,守護進程從客戶端接受命令並管理運行在主機上的容器。容器,是一個運行時環境,就是咱們前面說到的集裝箱。
例以下面 Docker 圖標(一隻鯨魚背上拖着不少個集裝箱, 鯨魚相似於 Docker,一個個的集裝箱就是軟件開發環境中的各類軟件)
如下爲 Docker 運行架構圖
爲何 Docker 運行速度遠大於 VM?
(1)Docker有着比虛擬機更少的抽象層。因爲docker不須要Hypervisor實現硬件資源虛擬化,運行在docker容器上的程序直接使用的都是實際物理機的硬件資源。所以在CPU、內存利用率上docker將會在效率上有明顯優點。
(2)Docker利用的是宿主機的內核,而不須要CentOS。所以,當新建一個容器時,docker不須要和虛擬機同樣從新加載一個操做系統內核。從而避免加載操做系統內核這個比較費時費資源的過程,當新建一個虛擬機時,虛擬機軟件須要加載CentOS,整個新建過程是分鐘級別的。而docker因爲直接利用宿主機的操做系統,所以新建一個docker容器只須要幾秒鐘。
Docker 和 VM 對比圖
docker version
docker info
docker --help(-h)
列出本地主機上的鏡像
同一倉庫源能夠有多個 TAG,表明這個倉庫源的不一樣個版本,咱們使用 REPOSITORY:TAG 來定義不一樣的鏡像。 若是你不指定一個鏡像的版本標籤,例如你只使用 ubuntu,docker 將默認使用 ubuntu:latest 鏡像
images 命令 的 option 參數
-a:列出本地全部的鏡像(含中間映像層)
-q :只顯示鏡像ID
--digests :顯示鏡像的摘要信息
--no-trunc :顯示完整的鏡像信息
從 Docker hub 官網搜索鏡像
官網地址: hub.docker.com
以 tomcat 爲例
和在官網搜索的結果如出一轍
參數說明
-s : 列出收藏數不小於指定值的鏡像
只搜索點贊數大於30的鏡像
--no-trunc : 顯示完整的鏡像描述
--automated : 只列出 automated build類型的鏡像
docker pull 鏡像名:tag
拉取鏡像(從前面咱們已經設置的阿里雲的鏡像加速地址)
若是 docker pull 鏡像名
後面不加參數,默認下載最新版本
即 docker pull tomcat 等價於 docker pull tomcat:latest
[cris@hadoop104 ~]$ sudo docker pull tomcat
複製代碼
docker rmi 鏡像名/鏡像id
刪除 Docker 鏡像
ps: docker rmi 鏡像名
默認會刪除標籤爲 :latest 的鏡像,若是要刪除指定標籤的鏡像,在鏡像名後面指定 tag 便可
若是沒法刪除,出現如上提示,表示咱們的鏡像正在使用中,可使用 -f 強制刪除
若是想要刪除多個鏡像
docker rmi -f 鏡像名1:tag 鏡像名2:tag
sudo docker rmi -f hello-world tomcat
複製代碼
刪除所有鏡像
sudo docker rmi -f $(docker images -qa)
複製代碼
結合 git 知識,想一想 Docker 是否有 docker pull 和 docker commit 命令?
以 CentOS 爲例,這裏 Cris 從阿里雲下載一個 CentOS 的鏡像
新建並啓動容器(以 Docker 裏面的 CentOS 鏡像爲例)
docker run [options] image [command] [arg...]
options 這裏經常使用的有:
--name="容器新名字": 爲容器指定一個名稱; -d: 後臺運行容器,並返回容器ID,也即啓動守護式容器; -i:以交互模式運行容器,一般與 -t 同時使用; -t:爲容器從新分配一個僞輸入終端,一般與 -i 同時使用; -P: 隨機端口映射; -p: 指定端口映射,有如下四種格式 ip:hostPort:containerPort ip::containerPort hostPort:containerPort containerPort
咱們使用 -it 參數來啓動 CentOS 容器
root@ 後面跟着的就是該容器的 id
查看全部運行的容器命令
docker ps [options]
參數說明:
-a :列出當前全部正在運行的容器+歷史上運行過的容器 -l :顯示最近運行的容器。 -n number:顯示最近 number 個建立的容器。 -q :靜默模式,只顯示容器編號。 --no-trunc :不截斷輸出。
退出容器
exit: 容器中止並退出
ctrl+p+q: 容器不中止退出
啓動已經建立的容器
docker start 容器id/容器名
重啓容器
docker restart 容器id/容器名
中止容器
docker stop 容器id/容器名
強制關閉容器
docker kill 容器id/容器名
刪除已中止的容器
docker rm 容器id/容器名
一次性刪除多個已經中止的容器
docker rm -f $(docker ps -qa) 或者 docker ps -a -q | xargs docker rm
交互式容器和守護式容器
前面啓動 CentOS 容器使用的 -it 參數就是表示交互式命令,經過終端來保持和容器的交互
若是要啓動守護式容器,那麼須要加上 -d 參數
可是此時查詢正在運行的容器
沒有發現之後臺模式運行的 Docker 容器
發現該容器已經自動退出了
問題:docker ps -a 進行查看, 會發現容器已經退出 很重要的一點: Docker容器後臺運行,就必須有一個前臺進程. 容器運行的命令若是不是那些一直掛起的命令(好比運行top,tail),是會自動退出的。
這個是docker的機制問題,好比你的web容器,咱們以nginx爲例,正常狀況下,咱們配置啓動服務只須要啓動響應的service便可。例如 service nginx start 可是,這樣作,nginx爲後臺進程模式運行,就致使docker前臺沒有運行的應用, 這樣的容器後臺啓動後,會當即自殺由於他以爲他沒事可作了. 因此,最佳的解決方案是,將你要運行的程序之前臺進程的形式運行
容器日誌
對於後臺運行的容器,能夠如下面的方式來啓動
[cris@hadoop104 ~]$ sudo docker run -d --name centos004 centos /bin/sh -c "while true;do echo hello zzyy;sleep 2;done"
複製代碼
查看 Docker 容器
即使是後臺啓動,可是由於前臺一直打印日誌,Docker 容器也不會自動關閉
若是此時咱們想去查看 Docker 容器的日誌,能夠經過如下命令
docker logs -f -t --tail 容器ID
查看容器內運行的進程
docker top 容器ID
查看容器內部細節
docker inspect 容器ID
進入正在運行的容器並以命令行交互
從新進入正在運行的容器
docker attach 容器ID
還有一種方式是
docker exec -it 容器ID bashShell(功能更增強大,能夠直接返回結果到客戶端)
區別在於:
attach 命令直接進入容器啓動命令的終端,不會啓動新的進程
exec 命令是在容器中打開新的終端,而且能夠啓動新的進程
從容器內拷貝文件到主機上
docker cp 容器ID:容器內路徑 目的主機路徑
示例以下
attach Attach to a running container # 當前 shell 下 attach 鏈接指定運行鏡像
build Build an image from a Dockerfile # 經過 Dockerfile 定製鏡像
commit Create a new image from a container changes # 提交當前容器爲新的鏡像
cp Copy files/folders from the containers filesystem to the host path #從容器中拷貝指定文件或者目錄到宿主機中
create Create a new container # 建立一個新的容器,同 run,但不啓動容器
diff Inspect changes on a container's filesystem # 查看 docker 容器變化 events Get real time events from the server # 從 docker 服務獲取容器實時事件 exec Run a command in an existing container # 在已存在的容器上運行命令 export Stream the contents of a container as a tar archive # 導出容器的內容流做爲一個 tar 歸檔文件[對應 import ] history Show the history of an image # 展現一個鏡像造成歷史 images List images # 列出系統當前鏡像 import Create a new filesystem image from the contents of a tarball # 從tar包中的內容建立一個新的文件系統映像[對應export] info Display system-wide information # 顯示系統相關信息 inspect Return low-level information on a container # 查看容器詳細信息 kill Kill a running container # kill 指定 docker 容器 load Load an image from a tar archive # 從一個 tar 包中加載一個鏡像[對應 save] login Register or Login to the docker registry server # 註冊或者登錄一個 docker 源服務器 logout Log out from a Docker registry server # 從當前 Docker registry 退出 logs Fetch the logs of a container # 輸出當前容器日誌信息 port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口對應的容器內部源端口 pause Pause all processes within a container # 暫停容器 ps List containers # 列出容器列表 pull Pull an image or a repository from the docker registry server # 從docker鏡像源服務器拉取指定鏡像或者庫鏡像 push Push an image or a repository to the docker registry server # 推送指定鏡像或者庫鏡像至docker源服務器 restart Restart a running container # 重啓運行的容器 rm Remove one or more containers # 移除一個或者多個容器 rmi Remove one or more images # 移除一個或多個鏡像[無容器使用該鏡像纔可刪除,不然需刪除相關容器纔可繼續或 -f 強制刪除] run Run a command in a new container # 建立一個新的容器並運行一個命令 save Save an image to a tar archive # 保存一個鏡像爲一個 tar 包[對應 load] search Search for an image on the Docker Hub # 在 docker hub 中搜索鏡像 start Start a stopped containers # 啓動容器 stop Stop a running containers # 中止容器 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 # 查看 docker 版本號 wait Block until a container stops, then print its exit code # 截取容器中止時的退出狀態值 複製代碼
鏡像是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基於運行環境開發,它包含運行某個軟件所需的全部內容,包括代碼、運行時、庫、環境變量和配置文件。
而 Docker 鏡像的底層實現原理是 UnionFS 聯合文件系統
UnionFS(聯合文件系統):Union文件系統(UnionFS)是一種分層、輕量級而且高性能的文件系統,它支持對文件系統的修改做爲一次提交來一層層的疊加,同時能夠將不一樣目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。Union 文件系統是 Docker 鏡像的基礎。鏡像能夠經過分層來進行繼承,基於基礎鏡像(沒有父鏡像),能夠製做各類具體的應用鏡像。
相似於花捲這種常見的早餐,文件系統能夠經過一層一層的嵌套,對外暴露統一的"表面層"來供使用者操做
特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件系統疊加起來,這樣最終的文件系統會包含全部底層的文件和目錄
docker的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引導加載kernel, Linux剛啓動時會加載bootfs文件系統,在Docker鏡像的最底層是bootfs。這一層與咱們典型的Linux/Unix系統是同樣的,包含boot加載器和內核。當boot加載完成以後整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs。
rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系統中的 /dev, /proc, /bin, /etc 等標準目錄和文件。rootfs就是各類不一樣的操做系統發行版,好比Ubuntu,Centos等等。
平時咱們安裝進虛擬機的CentOS都是好幾個G,爲何docker這裏才200M??
對於一個精簡的OS,rootfs能夠很小,只須要包括最基本的命令、工具和程序庫就能夠了,由於底層直接用Host的kernel,本身只須要提供 rootfs 就好了。因而可知對於不一樣的linux發行版, bootfs基本是一致的, rootfs會有差異, 所以不一樣的發行版能夠公用bootfs。
經過 docker pull 命令再來感覺一下鏡像分層
因此在下載的過程當中咱們能夠看到docker的鏡像好像是在一層一層的在下載
爲何 Docker 鏡像要採用這種分層結構呢?
最大的一個好處就是 - 共享資源
好比:有多個鏡像都從相同的 base 鏡像構建而來,那麼宿主機只需在磁盤上保存一份base鏡像, 同時內存中也只需加載一份 base 鏡像,就能夠爲全部容器服務了。並且鏡像的每一層均可以被共享。
因此,Docker鏡像都是隻讀的,當容器啓動時,一個新的可寫層被加載到鏡像的頂部。這一層一般被稱做「容器層」,「容器層」之下的都叫「鏡像層」。
基礎命令
docker commit 用於提交容器副本使之成爲一個新的鏡像
完整格式以下
docker commit -m=「提交的描述信息」 -a=「做者」 容器ID 要建立的目標鏡像名:[標籤名]
以 Tomcat 爲例
[cris@hadoop104 ~]$ sudo docker exec -it 8db42f30a60a /bin/bash
root@8db42f30a60a:/usr/local/tomcat#
複製代碼
咱們刪除掉 tomcat 下的 doc 文檔
也即當前的tomcat運行實例是一個沒有文檔內容的容器,以它爲模板commit一個沒有doc的tomcat新鏡像 cris/tomcat
至此,新的沒有 doc 的 Tomcat 鏡像已經生成好了
運行基於新鏡像的 Tomcat 容器
[cris@hadoop104 ~]$ sudo docker run -it -p 8118:8080 cris/tomcat:1.1
複製代碼
能夠發現是沒有 doc 文檔的
ps: 以上都是之前臺方式啓動 Tomcat 容器(不斷打印日誌),若是想要之後臺守護方式啓動,直接加上 -d 參數便可
控制檯也就沒有日誌打印了
需求:
Docker容器產生的數據,若是不經過docker commit生成新的鏡像,使得數據作爲鏡像的一部分保存下來, 那麼當容器刪除後,數據天然也就沒有了。
爲了能保存數據在docker中咱們使用數據卷。
相似 Redis裏面的rdb和aof文件或者咱們平時使用的移動硬盤
數據卷就是目錄或文件,存在於一個或多個容器中,由docker掛載到容器,但不屬於聯合文件系統,所以可以繞過Union File System提供一些用於持續存儲或共享數據的特性:
數據卷的設計目的就是數據的持久化,徹底獨立於容器的生存週期,所以Docker不會在容器刪除時刪除其掛載的數據卷
特色:
docker run -it -v /宿主機絕對路徑目錄:/容器內目錄 鏡像名
驗證數據卷是否掛載成功
[cris@hadoop104 ~]$ sudo docker inspect 4b02b2727058
複製代碼
宿主機和容器之間的數據交互
同理, 容器能夠對數據進行修改並同步到宿主機
容器中止退出後,主機修改後數據是否同步
經過 exit 命令中止容器並退出終端
而後在宿主機對數據進行修改
[cris@hadoop104 hostDataVolume]$ sudo vim dog.txt
複製代碼
從新開啓容器
能夠發現,即使是容器關閉,宿主機依然能夠對數據捲進行數據操做,當容器從新開啓時,數據卷會自動進行同步
若是想要設置權限,例如容器只能對數據捲進行讀和同步,宿主機能夠操做數據卷,那麼只須要添加一個參數便可
docker run -it -v /宿主機絕對路徑目錄:/容器內目錄:ro 鏡像名
ro
就表示 read-only 權限(針對容器)
DockerFile 簡單來講,就是描述 Docker 鏡像的描述文件
流程簡單梳理以下
宿主機新建一個 DockerFile
可在Dockerfile中使用VOLUME指令來給鏡像添加一個或多個數據卷
ps: 出於可移植和分享的考慮,用-v 主機目錄:容器目錄這種方法不可以直接在Dockerfile中實現。 因爲宿主機目錄是依賴於特定宿主機的,並不可以保證在全部的宿主機上都存在這樣的特定目錄。
build 構建鏡像
根據鏡像運行容器
測試數據卷
根據 inspect 命令查看對應的宿主機數據卷目錄
[cris@hadoop104 ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd98e9b2c94b cris/centos "/bin/sh -c /bin/bas 2 minutes ago Up 2 minutes jovial_goodall
[cris@hadoop104 ~]$ sudo docker inspect cd98e9b2c94b
複製代碼
默認宿主機掛載地址須要經過 inspect 命令查看
主要用於容器和容器之間的數據共享
命令: --volumes-from
示例以下:
啓動一個父容器
啓動後咱們在指定目錄下建立一個文件
新建兩個子容器,繼承自父容器
能夠發現成功同步了父容器的數據
同時修改任意一個子容器的數據卷數據,都會同步到其餘容器
即使是刪除任意一個容器,數據卷的數據同步不會中止
結論
容器之間共享數據的傳遞,數據卷的生命週期一直持續到沒有容器使用它爲止
Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本。
一般使用 DockerFile 的三個步驟都是:
以 CentOS 爲例, Docker Hub 上的 CentOS 的 DockerFile 文件以下
以上面的 CentOS DockerFile 文件爲例
總結:
從應用軟件的角度來看,Dockerfile、Docker鏡像與Docker容器分別表明軟件的三個不一樣階段,
Dockerfile,須要定義一個Dockerfile,Dockerfile定義了進程須要的一切東西。Dockerfile涉及的內容包括執行代碼或者是文件、環境變量、依賴包、運行時環境、動態連接庫、操做系統的發行版、服務進程和內核進程(當應用進程須要和系統服務和內核進程打交道,這時須要考慮如何設計namespace的權限控制)等等;
Docker鏡像,在用Dockerfile定義一個文件以後,docker build時會產生一個Docker鏡像,當運行 Docker鏡像時,會真正開始提供服務;
Docker容器,直接提供服務.
FROM : 基礎鏡像,當前新鏡像是基於哪一個鏡像的
MAINTAINER : 鏡像維護者的姓名和郵箱地址
RUN : 容器構建時須要運行的命令
EXPOSE : 當前容器對外暴露出的端口
WORKDIR : 指定在建立容器後,終端默認登錄的進來工做目錄,一個落腳點
ENV : 用來在構建鏡像過程當中設置環境變量
ENV MY_PATH /usr/mytest 這個環境變量能夠在後續的任何RUN指令中使用,這就如同在命令前面指定了環境變量前綴同樣; 也能夠在其它指令中直接使用這些環境變量,
好比:WORKDIR $MY_PATH
ADD : 將宿主機目錄下的文件拷貝進鏡像且ADD命令會自動處理URL和解壓tar壓縮包
COPY : 相似ADD,拷貝文件和目錄到鏡像中。 將從構建上下文目錄中 <源路徑> 的文件/目錄複製到新的一層的鏡像內的 <目標路徑> 位置
VOLUME : 容器數據卷,用於數據保存和持久化工做
CMD : 指定一個容器啓動時要運行的命令
注意: Dockerfile 中能夠有多個 CMD 指令,但只有最後一個生效,CMD 會被 docker run 以後的參數替換
ENTRYPOINT : 指定一個容器啓動時要運行的命令;ENTRYPOINT 的目的和 CMD 同樣,都是在指定容器啓動程序及參數,可是不會被 docker run 後面的參數替換,而是追加
ONBUILD : 當構建一個被繼承的Dockerfile時運行命令,父鏡像在被子繼承後父鏡像的onbuild被觸發
總結:
首先,咱們須要知道Docker Hub 中 99% 的鏡像都是經過在 base 鏡像中安裝和配置須要的軟件構建出來的
而這個 base 鏡像就是scratch 鏡像
首先中止全部正在運行的 Docker 容器
而後看看從阿里雲下載的基礎版 CentOS 缺失了哪些功能
如今咱們的目標就是經過編寫 DockerFile 爲基礎版本的 CentOS 鏡像加上這些缺失的功能
DockerFile 以下
FROM centos
MAINTAINER cris<cris163@111.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
複製代碼
開始構建
[cris@hadoop104 dockerFile]$ sudo docker build -f centosDockerFile -t cris/centos:1.2 .
複製代碼
構建成功,開始運行容器
除此以外,還能夠查看 Docker 鏡像的修改歷史
CMD 示例:
Dockerfile 中能夠有多個 CMD 指令,但只有最後一個生效,CMD 會被 docker run 以後的參數替換
以 Tomcat 爲例
緣由就在於咱們的 ls -l 參數替換掉了原來的啓動參數,以下
至關於在這行參數後面又添加了 CMD ls -l
那麼容器啓動時就會執行最後的 ls -l 命令
若是是 ENTRYPOINT
docker run 以後的參數會被當作參數傳遞給 ENTRYPOINT,以後造成新的命令組合
示例以下
編寫 DockerFile
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
複製代碼
而後構建
[cris@hadoop104 dockerFile]$ sudo docker build -f centosDockerFile2 -t cris/ipcentos .
複製代碼
以添加參數的形式啓動容器
若是咱們把上面 DockerFile 文件中的 ENTRYPOINT 改成 CMD 並從新編譯鏡像
那麼一樣的命令啓動容器,會出現如下報錯
ONBUILD 示例
相似於觸發器,在鏡像編譯以及子鏡像編譯的時候觸發
新建一個 DockerFile , centosDockerFileFather
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
ONBUILD RUN echo "father is building -------------->"
複製代碼
進行編譯後,又新建一個子 DockerFile, centosDockerFileSon
FROM cris/ipcentos_father
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
複製代碼
cris/ipcentos_father 就是上面編譯完成的父鏡像
當咱們開始編譯子鏡像時,就會觸發 ONBUILD 操做
在新建目錄,而且添加如下文件
Dockerfile 內容以下
FROM centos
MAINTAINER cris<cris@1222.com>
#把宿主機當前上下文的c.txt拷貝到容器/usr/local/路徑下
COPY copy.txt /usr/local/cincontainer.txt
#把java與tomcat添加到容器中
ADD jdk-8u172-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.19.tar.gz /usr/local/
#安裝vim編輯器
RUN yum -y install vim
#設置工做訪問時候的WORKDIR路徑,登陸落腳點
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java與tomcat環境變量
ENV JAVA_HOME /usr/local/jdk1.8.0_172
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.19
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.19
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器運行時監聽的端口
EXPOSE 8080
#啓動時運行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"]
CMD /usr/local/apache-tomcat-9.0.19/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.19/bin/logs/catalina.out
複製代碼
而後開始編譯
[cris@hadoop104 mytomcat]$ sudo docker build -t cris_tomcat9 .
複製代碼
若是不加 -f 參數,默認從當前目錄下的 Dockerfile 文件開始編譯
編譯成功後,直接運行
[cris@hadoop104 mytomcat]$ sudo docker run -d -p 9090:8080 --name cristomcat9 -v /home/cris/dockerFile/mytomcat/test:/usr/local/apache-tomcat-9.0.19/webapps/test -v \
> /home/cris/dockerFile/mytomcat/logs:/usr/local/apache-tomcat-9.0.19/logs --privileged=true cris_tomcat9
複製代碼
查看數據卷對應的目錄
[cris@hadoop104 mytomcat]$ sudo docker inspect cristomcat9
複製代碼
驗證 Tomcat 是否啓動
測試web 工程發佈
咱們在宿主機的目錄上新建一個簡單的 web 工程
test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
-----------welcome------------
<%="i am in docker tomcat self "%>
<br>
<br>
<% System.out.println("=============docker tomcat self");%>
</body>
</html>
複製代碼
而後是 WEB-INF 目錄下的 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>test</display-name>
</web-app>
複製代碼
最後重啓容器
[cris@hadoop104 test]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e39ccfda5b58 cris_tomcat9 "/bin/sh -c '/usr/lo 18 minutes ago Up 18 minutes 0.0.0.0:9090->8080/tcp cristomcat9
[cris@hadoop104 test]$ sudo docker restart cristomcat9
複製代碼
測試
咱們在宿主機修改 jsp
實時反映到 Docker 容器中的 Tomcat
在查看對應的日誌
Docker 安裝常規步驟
docker pull mysql:5.6
驗證
運行容器
[cris@hadoop104 ~]$ sudo docker run -p 12345:3306 --name mysql -v /home/cris/docker_mysql/conf:/etc/mysql/conf.d -v /home/cris/docker_mysql/logs:/logs -v /home/cris/docker_mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
複製代碼
數據卷已創建
[cris@hadoop104 ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
029d8863fb17 mysql:5.6 "docker-entrypoint.s 7 seconds ago Up 6 seconds 0.0.0.0:12345->3306/tcp mysql
複製代碼
容器已經成功跑起來了
宿主機測試是否能夠鏈接
數據備份
docker exec myql服務容器ID sh -c ' exec mysqldump --all-databases -uroot -p"123456" ' > /home/cris/docker_mysql/all-databases.sql
複製代碼
先拉取: docker pull redis:3.2
而後執行如下命令運行容器
[cris@hadoop104 ~]$ sudo docker run -p 6379:6379 -v /home/cris/myredis/data:/data -v /home/cris/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes
複製代碼
若是想要修改 Redis 的配置文件,能夠直接在宿主機上對應目錄修改 Redis 的配置文件便可,自動映射到Docker 容器中的 Redis
測試 redis-cli 鏈接
測試持久化文件生成
首先,咱們知道了 image 的生成方式有兩種,一種是根據 DockerFile 構建;一種是根據容器 commit 新的 image
示例
首先運行一個 Docker 容器
$ sudo docker run -it cris/centos:1.2
複製代碼
而後提交一個新的 image
$ sudo docker commit -a cris -m "new centos image by cris with vim and ifconfig features" 3325338e5c43 cris/centos:1.3
複製代碼
登陸阿里雲,進行測試
建立鏡像倉庫
而後根據指示推送本地 image 到阿里雲的 repository
$ sudo docker login --username=990435014@qq.com registry.cn-hangzhou.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/cris_cool/mycentos:[鏡像版本號]
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/cris_cool/mycentos:[鏡像版本號]
複製代碼
ps: 這裏 Cris 從本機登陸阿里雲倉庫的時候一直沒法登陸,顯示以下錯誤
Error response from daemon: no successful auth challenge for https://registry.cn-hangzhou.aliyuncs.com/v2/ - errors: [token auth attempt for registry https://registry.cn-hangzhou.aliyuncs.com/v2/: https://dockerauth.cn-hangzhou.aliyuncs.com/auth?account=990435014%40qq.com&service=registry.aliyuncs.com%3Acn-hangzhou%3A26842 request failed with status: 401 Unauthorized]
複製代碼
網上搜索了後發現登陸密碼不對,不是登陸阿里雲帳號的密碼,須要從新設置登陸 repository 的密碼
而後開始推送
想要拉取也很簡單
[cris@hadoop104 data]$ sudo docker pull registry.cn-hangzhou.aliyuncs.com/cris_cool/mycentos:1.3
複製代碼
參考 Docker 官網便可