Docker是PaaS 提供商 dotCloud 開源的一個基於 LXC 的高級容器引擎,源代碼托管在 Github 上, 基於go語言並遵從Apache2.0協議開源。Docker是通過內核虛擬化技術(namespace以及cgroups等)來提供容器的資源隔離與安全保障。由於Docker通過操作系統層的虛擬化實現隔離,所以Docker容器在運行時,不需要類似虛擬機( VM)額外的操作系統開銷,提高資源利用率。
Docker是使用Go語言編寫的一個程序運行、測試、交付的開放平台,Docker被設計為能夠使你快速地交付應用。在Docker中,你可以將你的程序分為不同的基礎部分,對於每一個基礎部分都可以當做一個應用程序來管理。Docker能夠幫助你快速地測試、快速地編碼、快速地交付,並且縮短你從編碼到運行應用的周期。Docker使用輕量級的容器虛擬化平台,並且結合工作流和工具,來幫助你管理、部署你的應用程序。Docker在其核心,Docker實現了讓幾乎任何程序都可以在一個安全、隔離的容器中運行。安全和隔離可以使你可以同時在機器上運行多個容器。Docker容器輕量級的特性,意味着可以得到更多的硬件性能。
Docker原理:建立-->傳送-->運行
通過Docker Hub或者自己的Docker倉庫分享Docker鏡像, 從Docker鏡像創建Docker容器, 在容器里運行應用程序。
Docker鏡像是如何工作的?
Docker鏡像是Docker容器運行時的只讀模板,每一個鏡像由一系列的層(layers)組成;Docker使用UnionFS(聯合文件系統)來將這些層聯合到一二鏡像中,UnionFS文件系統允許獨立文件系統中的文件和文件夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的文件系統。
正因為有了這些層(layers)的存在,Docker才會如此的輕量。當你改變了一個Docker鏡像,比如升級到某個程序到新的版本,一個新的層會被創建。因此,不用替換整個原先的鏡像或者重新建立(在使用虛擬機的時候你可能會這么做),只是一個新的層被添加或升級了。所以你不用重新發布整個鏡像,只需要升級。層使得分發Docker鏡像變得簡單和快速。
每個鏡像都是從一個基礎的鏡像開始的,比如ubuntu,一個基礎的Ubuntu鏡像,或者是Centos,一個基礎的Centos鏡像。你可以使用你自己的鏡像作為新鏡像的基礎,例如你有一個基礎的安裝了Nginx的鏡像,你可以使用該鏡像來建立你的Web應用程序鏡像。(Docker通常從Docker Hub獲取基礎鏡像)
Docker鏡像從這些基礎的鏡像創建,通過一種簡單、具有描述性的步驟,我們稱之為 指令(instructions)。每一個指令會在鏡像中創建一個新的層,指令可以包含這些動作:
-> 運行一個命令。
-> 增加文件或者文件夾。
-> 創建一個環境變量。
-> 當運行容器的時候哪些程序會運行。
這些指令存儲在Dockerfile文件中。當你需要建立鏡像的時候,Docker可以從Dockerfile中讀取這些指令並且運行,然后返回一個最終的鏡像。
Docker倉庫的用處?
Docker倉庫是Docker鏡像的存儲倉庫。可以推送鏡像到Docker倉庫中,然后在Docker客戶端,可以從Docker倉庫中搜索和拉取鏡像。
Docker容器是如何工作的?
一個Docker容器包含了一個操作系統、用戶添加的文件和元數據(meta-data)。每個容器都是從鏡像建立的,鏡像告訴Docker容器內包含了什么,當容器啟動時運行什么程序,還有許多配置數據。Docker鏡像是只讀的,當Docker運行一個從鏡像建立的容器,它會在鏡像頂部添加一個可讀寫的層,應用程序可以在這里運行。
Docker容器運行時會做哪些事情?
使用docker命令時,Docker客戶端都告訴Docker守護進程運行一個容器。
# docker run -i -t ubuntu /bin/bash
可以來分析這個命令,Docker客戶端使用docker命令來運行,run參數表明客戶端要運行一個新的容器。
Docker客戶端要運行一個容器需要告訴Docker守護進程的最小參數信息是:
-> 這個容器從哪個鏡像創建,這里是ubuntu,基礎的Ubuntu鏡像。
-> 在容器中要運行的命令,這里是/bin/bash,在容器中運行Bash shell。
那么運行這個命令之后在底層發生了什么呢?按照順序,Docker做了這些事情:
-> 拉取ubuntu鏡像:Docker檢查ubuntu鏡像是否存在,如果在本地沒有該鏡像,Docker會從Docker Hub下載。如果鏡像已經存在,Docker會使用它來創建新的容器。
-> 創建新的容器:當Docker有了這個鏡像之后,Docker會用它來創建一個新的容器。
-> 分配文件系統並且掛載一個可讀寫的層:容器會在這個文件系統中創建,並且一個可讀寫的層被添加到鏡像中。
-> 分配網絡/橋接接口:創建一個允許容器與本地主機通信的網絡接口。
-> 設置一個IP地址:從池中尋找一個可用的IP地址並且服加到容器上。
-> 運行你指定的程序:運行指定的程序。
-> 捕獲並且提供應用輸出:連接並且記錄標准輸出、輸入和錯誤讓你可以看到你的程序是如何運行的。
由此就可以擁有一個運行着的Docker容器了!從這里開始你可以管理你的容器,與應用交互,應用完成之后,可以停止或者刪除你的容器。
Docker與VM的區別:
docker與Openstack的對比
Docker用途:簡單配置、代碼流水線管理、開發效率、應用隔離、服務器整合、調試能力、多租戶、快速部署
Docker可以快速交付應用程序
Docker可以為你的開發過程提供完美的幫助。Docker允許開發者在本地包含了應用程序和服務的容器進行開發,之后可以集成到連續的一體化和部署工作流中。舉個例子,開發者們在本地編寫代碼並且使用Docker和同事分享其開發棧。當開發者們准備好了之后,他們可以將代碼和開發棧推送到測試環境中,在該環境進行一切所需要的測試。從測試環境中,你可以將Docker鏡像推送到服務器上進行部署。
Docker可以讓開發和拓展更加簡單
Docker的以容器為基礎的平台允許高度可移植的工作。Docker容器可以在開發者機器上運行,也可以在實體或者虛擬機上運行,也可以在雲平台上運行。Docker的可移植、輕量特性同樣讓動態地管理負載更加簡單。你可以用Docker快速地增加應用規模或者關閉應用程序和服務。Docker的快速意味着變動幾乎是實時的。
Docker可以達到高密度和更多負載
Docker輕巧快速,它提供了一個可行的、符合成本效益的替代基於虛擬機管理程序的虛擬機。這在高密度的環境下尤其有用。例如,構建你自己的雲平台或者PaaS,在中小的部署環境下同樣可以獲取到更多的資源性能。
Docker改變了什么?
-> 面向產品:產品交付
-> 面向開發:簡化環境配置
-> 面向測試:多版本測試
-> 面向運維:環境一致性
-> 面向架構:自動化擴容
Docker組件:鏡像(Image)、容器(Container)、倉庫(Repository)
Docker 架構:C/S架構
-> Docker使用客戶端-服務器(client-server)架構模式。
-> Docker 客戶端會與Docker守護進程進行通信。Docker 守護進程會處理復雜繁重的任務,例如建立、運行、發布你的 Docker 容器。
-> Docker 客戶端和守護進程可以運行在同一個系統上,當然也可以使用Docker客戶端去連接一個遠程的 Docker 守護進程。
-> Docker 客戶端和守護進程之間通過socket或者RESTful API進行通信。
Docker守護進程
如上圖所示,Docker守護進程運行在一台主機上。用戶並不直接和守護進程進行交互,而是通過 Docker 客戶端間接和其通信。
Docker 客戶端
Docker 客戶端,實際上是 docker 的二進制程序,是主要的用戶與 Docker 交互方式。它接收用戶指令並且與背后的 Docker 守護進程通信,如此來回往復。
Docker 內部
要理解Docker內部構建,需要理解以下三種部件:
Docker 鏡像 - Docker Images
Docker 倉庫 - Docker Registry
Docker 容器 - Docker Containers
Docker鏡像是Docker容器運行時的只讀模板,每一個鏡像由一系列的層 (layers) 組成。Docker 使用 UnionFS 來將這些層聯合到單獨的鏡像中。UnionFS 允許獨立文件系統中的文件和文件夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的文件系統。正因為有了這些層的存在,Docker 是如此的輕量。當你改變了一個 Docker 鏡像,比如升級到某個程序到新的版本,一個新的層會被創建。因此,不用替換整個原先的鏡像或者重新建立(在使用虛擬機的時候你可能會這么做),只是一個新 的層被添加或升級了。現在你不用重新發布整個鏡像,只需要升級,層使得分發 Docker 鏡像變得簡單和快速。
Docker倉庫用來保存鏡像,可以理解為代碼控制中的代碼倉庫。同樣的,Docker 倉庫也有公有和私有的概念。公有的 Docker 倉庫名字是 Docker Hub。Docker Hub 提供了龐大的鏡像集合供使用。這些鏡像可以是自己創建,或者在別人的鏡像基礎上創建。Docker 倉庫是 Docker 的分發部分。
Docker容器和文件夾很類似,一個Docker容器包含了所有的某個應用運行所需要的環境。每一個 Docker 容器都是從 Docker 鏡像創建的。Docker 容器可以運行、開始、停止、移動和刪除。每一個 Docker 容器都是獨立和安全的應用平台,Docker 容器是 Docker 的運行部分。
libcontainer
Docker 從 0.9 版本開始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系統的交互圖如下:
下面說下Docker容器的底層技術:Namesapce(資源隔離)和 Cgroup(資源限制)
命名空間 [Namespaces]
=> pid namespace:使用在進程隔離(Process ID)
不同用戶的進程就是通過pid namespace隔離開的,且不同 namespace 中可以有相同 PID。
具有以下特征:
-> 每個namespace中的pid是有自己的pid=1的進程(類似 /sbin/init 進程)
-> 每個 namespace 中的進程只能影響自己的同一個 namespace 或子 namespace 中的進程
-> 因為 /proc 包含正在運行的進程,因此在 container 中的 pseudo-filesystem 的 /proc 目錄只能看到自己namespace 中的進程
-> 因為 namespace 允許嵌套,父 namespace 可以影響子 namespace 的進程,所以子 namespace 的進程可以在父namespace中看到,但是具有不同的 pid
=> mnt namespace:使用在管理掛載點(Mount)
類似 chroot,將一個進程放到一個特定的目錄執行。mnt namespace 允許不同namespace的進程看到的文件結構不同,這樣每個namespace 中的進程所看到的文件目錄就被隔離開了。同 chroot 不同,每個 namespace 中的 container 在 /proc/mounts 的信息只包含所在namespace的mount point。
=> net namespace:使用在進程網絡接口(Networking)
網絡隔離是通過 net namespace 實現的, 每個 net namespace 有獨立的 network devices, IP addresses, IP routing tables, /proc/net 目錄。這樣每個 container 的網絡就能隔離開來。 docker 默認采用 veth 的方式將 container 中的虛擬網卡同 host 上的一個 docker bridge 連接在一起。
=> uts namespace:使用在隔離內核和版本標識 (Unix Timesharing System)
UTS ("UNIX Time-sharing System") namespace 允許每個 container 擁有獨立的 hostname 和 domain name, 使其在網絡上可以被視作一個獨立的節點而非 Host 上的一個進程。
=> ipc namespace:使用在管理進程間通信資源 (InterProcess Communication)
container 中進程交互還是采用 Linux 常見的進程間交互方法 (interprocess communication - IPC), 包括常見的信號量、消息隊列和共享內存。然而同 VM 不同,container 的進程間交互實際上還是 host 上具有相同 pid namespace 中的進程間交互,因此需要在IPC資源申請時加入 namespace 信息 - 每個 IPC 資源有一個唯一的 32bit ID。
=> user namespace:使用在管理空戶空間
每個 container 可以有不同的 user 和 group id, 也就是說可以以 container 內部的用戶在 container 內部執行程序而非 Host 上的用戶。
有了以上6種namespace從進程、網絡、IPC、文件系統、UTS 和用戶角度的隔離,一個 container 就可以對外展現出一個獨立計算機的能力,並且不同container從OS層面實現了隔離。然而不同 namespace 之間資源還是相互競爭的,仍然需要類似ulimit 來管理每個container所能使用的資源。
資源配額 [cgroups]
Docker還使用到了cgroups技術來管理群組。使應用隔離運行的關鍵是讓它們只使用你想要的資源。這樣可以確保在機器上運行的容器都是良民(good multi-tenant citizens)。群組控制允許Docker分享或者限制容器使用硬件資源。例如,限制指定的容器的內容使用。
cgroups實現了對資源的配額和度量。 cgroups 的使用非常簡單,提供類似文件的接口,在 /cgroup 目錄下新建一個文件夾即可新建一個 group,在此文件夾中新建 task 文件,並將 pid 寫入該文件,即可實現對該進程的資源控制。具體的資源配置選項可以在該文件夾中新建子 subsystem ,{子系統前綴}.{資源項} 是典型的配置方法, 如 memory.usageinbytes 就定義了該 group 在 subsystem memory 中的一個內存限制選項。另外,cgroups 中的 subsystem 可以隨意組合,一個 subsystem 可以在不同的 group 中,也可以一個 group 包含多個 subsystem - 也就是說一個 subsystem。
=> memory
內存相關的限制
=> cpu
在 cgroup 中,並不能像硬件虛擬化方案一樣能夠定義 CPU 能力,但是能夠定義 CPU 輪轉的優先級,因此具有較高 CPU 優先級的進程會更可能得到 CPU 運算。 通過將參數寫入 cpu.shares ,即可定義改 cgroup 的 CPU 優先級 - 這里是一個相對權重,而非絕對值
=> blkio
block IO 相關的統計和限制,byte/operation 統計和限制 (IOPS 等),讀寫速度限制等,但是這里主要統計的都是同步 IO
=> devices
設備權限限制
Docker 聯合文件系統
聯合文件系統(UnionFS)是用來操作創建層的,使它們輕巧快速。Docker使用UnionFS提供容器的構造塊。Docker可以使用很多種類的UnionFS包括AUFS, btrfs, vfs, and DeviceMapper。
Docker 容器格式
Docker連接這些組建到一個包裝中,稱為一個 container format(容器格式)。默認的容器格式是libcontainer。Docker同樣支持傳統的Linux容器使用LXC。在未來,Docker也許會支持其它的容器格式,例如與BSD Jails 或 Solaris Zone集成。
======================== Docker環境的安裝部署 ==========================
環境准備(centos7)
# yum install -y docker # systemctl start docker # systemctl enable docker
鏡像的查看(docker images信息結果包括:鏡像倉庫、標簽、鏡像ID、創建時間、鏡像大小 )
[root@linux-node2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE docker.io/centos latest 60e65a8e4030 36 hours ago 196.6 MB docker.io/nginx latest 813e3731b203 9 days ago 133.8 MB docker.io/registry latest a8706c2bfd21 2 weeks ago 422.8 MB
鏡像的導出、導入和下載(可以將本機下載的鏡像導出,然后將導出文件上傳到別的機器上,在別的機器上進行鏡像導入)
[root@linux-node2 ~]# docker pull centos [root@linux-node2 ~]# docker save centos > /opt/centos.tar.gz 將linux-node2的鏡像導出文件上傳到linux-node1機器上,然后在linux-node1機器上導入 [root@linux-node1 ~]# docker load < /opt/centos.tar.gz
鏡像的刪除(rmi后面可以跟多個id,用空格隔開)
docker rmi container_id
[root@linux-node2 ~]# docker rmi 813e3731b203
Docker重命名鏡像名稱和TAG
# docker tag IMAGEID(鏡像id) REPOSITORY:TAG(倉庫:標簽)
[root@docker-test2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE <none> <none> 93ec41b5ed04 About an hour ago 435.9 MB [root@docker-test2 ~]# docker tag 93ec41b5ed04 kevin/nginx:v1 [root@docker-test2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE kevin/nginx v1 93ec41b5ed04 About an hour ago 435.9 MB
首次創建一個簡單的容器
[root@linux-node2 ~]# docker run centos /bin/echo "hehe" hehe
查看容器狀態
可以使用docker ps只能看見存活的容器,docker ps -a 查看全部的容器,結果信息表示:
容器ID、使用的鏡像、執行的命令、創建的時間、狀態、端口、名稱(如果不指定,自動生成)
[root@linux-node2 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES daeb4d7f7aab centos "/bin/echo hehe" About a minute ago Exited (0) About a minute ago insane_einstein
創建容器
--name:指定容器名稱
-t :分配一個tty終端
-i :容器的標准輸保持打開的狀態
[root@linux-node2 ~]# docker run --name mydocker -t -i centos /bin/bash [root@94ab7a046f7c /]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 11772 1872 ? Ss 03:42 0:00 /bin/bash root 14 0.0 0.0 35888 1472 ? R+ 03:43 0:00 ps aux
這種方式創建自動進入容器,開啟的容器只執行/bin/bash;
在容器中查看主機名
[root@94ab7a046f7c /]# hostname 94ab7a046f7c [root@94ab7a046f7c /]# exit
啟動、停止容器
# docker stop ID # docker start ID
進入容器
[root@linux-node2 ~]# docker attach 94ab7a046f7c [root@94ab7a046f7c /]#
刪除容器
[root@linux-node2 ~]# docker rm ID/名稱 加-f 強制刪除,包括正在運行中的容器
映射
隨機映射 (端口的映射是系統自動分配的)
[root@linux-node2 ~]# docker run -d -P nginx 90316d97ee975b4e62e1927a9fb31f20703556b1a3ea07880d0c68dcb5bbd3bb [root@linux-node2 ~]# docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 90316d97ee97 nginx "nginx -g 'daemon off" 25 seconds ago Up 23 seconds 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp ecstatic_almeida
指定映射 (如下,指定容器的80端口映射到主機的81端口上)
[root@linux-node2 ~]# docker run -d -p 81:80 nginx 0294a8f5b4fc81ba31383a8eb98ec62b136826eba92360c84afd87bf1bf819fc [root@linux-node2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0294a8f5b4fc nginx "nginx -g 'daemon off" 11 seconds ago Up 10 seconds 443/tcp, 0.0.0.0:81->80/tcp admiring_ramanujan
查看日志
命令為"docker logs +ID"
數據管理
數據卷
默認掛載目錄
創建一個數據卷,名稱是volume-test1,掛載到data下默認掛載目錄
[root@linux-node2 ~]# docker run -it --name volume-test1 -v /data centos [root@1768d6414cfc /]# ls -l /data/ total 0
列出容器的所有信息,查看mounts模塊
[root@linux-node2 ~]# docker inspect 1768d6414cfc "Mounts": [ { "Name": "55c97df0276bb8879398b4e7286fc41f9872e9203267da7e23060e24ba06d167", "Source": "/var/lib/docker/volumes/55c97df0276bb8879398b4e7286fc41f9872e9203267da7e23060e24ba06d167/_data", "Destination": "/data", "Driver": "local", "Mode": "", "RW": true } ],
查找掛載點並進入
[root@linux-node2 ~]# ll /var/lib/docker/volumes/55c97df0276bb8879398b4e7286fc41f9872e9203267da7e23060e24ba06d167/_data 總用量 0 [root@linux-node2 ~]# cd /var/lib/docker/volumes/55c97df0276bb8879398b4e7286fc41f9872e9203267da7e23060e24ba06d167/_data
創建一個cgt測試,並重新回到容器中查看
[root@linux-node2 _data]# mkdir cgt 去容器中查看 [root@1768d6414cfc /]# ls -l /data/ total 4 drwxr-xr-x 2 root root 4096 Jan 4 14:04 cgt
指定掛載目錄。 將容器的/opt映射到主機的/opt目錄下(下面命令中前一個是主機路徑,后一個是容器路徑)
[root@linux-node2 ~]# docker run -it --name volume-test1 -v /opt:/opt centos
指定權限
只需要在掛載后面加上權限即可。rw為讀寫,ro為只讀
[root@linux-node2 ~]# docker run -it --name volume-test1 -v /opt:/opt:rw centos
掛載單個文件
記錄歷史記錄
[root@linux-node2 ~]# docker run -it -v ~/.bash_history:/.bash_history centos
數據卷容器
讓一個容器可以訪問另一個容器的數據卷。啟動兩個容器
啟動nfs容器,掛在一個卷,使用-d直接在后台執行 [root@linux-node2 ~]# docker run -d --name nfs -v /data centos 209bc89b365ad6bc1eeae693ada01c04c2d08e9ee2b8816e624882944c116126 啟動test1容器,掛載到nfs的數據卷容器上, [root@linux-node2 ~]# docker run -it --name test1 --volumes-from nfs centos [root@5e399198d6a8 /]# ls /data/ 查看沒內容
找到nfs容器的掛載點(可以使用名稱,不僅僅是ID)
找到nfs容器的ID [root@linux-node2 opt]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 209bc89b365a centos "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago nfs 找到nfs容器的掛載點 [root@linux-node2 _data]# docker inspect nfs [root@linux-node2 opt]# cd /var/lib/docker/volumes/3938c9b1143d41340e148a4c7bc12d13b53966b15380c5b958a9e035897450d5/_data [root@linux-node2 _data]# touch cgt
在test1上查看
[root@5e399198d6a8 /]# ls /data/ cgt
注意:數據卷容器不論停止還是開啟,不影響其他容器掛載使用
如何制作鏡像
方式一:手動構建容器
1)創建一個容器mynginx,使用centos鏡像
[root@linux-node2 ~]# docker run --name mynginx -it centos [root@f9c7dfb6f552 /]# rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm [root@f9c7dfb6f552 /]# yum -y install nginx [root@f9c7dfb6f552 /]# exit exit
2)基於mynginx容器做一個鏡像mynginx:v1
[root@linux-node2 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f9c7dfb6f552 centos "/bin/bash" 3 minutes ago Exited (0) 15 seconds ago mynginx 基於mynginx這個容器做一個鏡像 [root@linux-node2 ~]# docker commit -m "my nginx" f9c7dfb6f552 cgt/mynginx:v1 3f3adc859b77b2b47c3631229761bee6c7066f1c708bc01c5173c2ef5c0adce8 提交鏡像,同時打一個標簽叫mynginx:v1,cgt相當於你向github上提交的用戶名 查看鏡像 [root@linux-node2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE cgt/mynginx v1 3f3adc859b77 About a minute ago 326.4 MB
3)基於mynginx:v1創建一個容器mynginxv1,目的是修改nginx不讓其在后台運行
[root@linux-node2 ~]# docker run -it --name nginxv1 cgt/mynginx:v1 [root@ea64c5855006 /]# vi /etc/nginx/nginx.conf daemon off; # 不再后台運行 [root@ea64c5855006 /]# exit exit [root@linux-node2 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ea64c5855006 cgt/mynginx:v1 "/bin/bash" 2 minutes ago Exited (0) 42 seconds ago nginxv1
4)基於mynginxv1提交mynginxv2版本
重新提交V2版本 [root@linux-node2 ~]# docker commit -m "my nginx" ea64c5855006 cgt/mynginx:v2 a480cdf9055ec4e640c65df6404c6ba42903ea77198a26cec75eef0e4965fe67 查看V2鏡像 [root@linux-node2 ~]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE cgt/mynginx v2 a480cdf9055e 25 seconds ago
5)基於mynginxv2鏡像,創建mynginxv2容器
啟動容器,-d后台運行,-p指定端口 在后面是鏡像,最后是命令(因為是yum安裝的,可以直接寫nginx,如果不是yum,那要寫絕對路徑) [root@linux-node2 ~]# docker run -d -p 82:80 cgt/mynginx:v2 nginx 4eaf8a19034a673100f9355504628fad45e6ecbab91615afd6cb4e7a18b82171 [root@linux-node2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4eaf8a19034a cgt/mynginx:v2 "nginx" 15 seconds ago Up 14 seconds 0.0.0.0:82->80/tcp elegant_leakey 可以在瀏覽器訪問82端口
方式二:Dockerfile
1)Dockerfile包含的信息
- 基礎鏡像信息
- 維護者信息
- 鏡像操作指令
- 容器啟動時執行指令
2)文件的編寫
[root@linux-node2 ~]# mkdir /opt/dockerfile/nginx/ -p [root@linux-node2 ~]# cd /opt/dockerfile/nginx/ 將index.html上傳到此處 [root@linux-node2 nginx]# vim Dockerfile # This is docker file # version v1 # Author wangshibo # Base image(基礎鏡像) FROM centos # Maintainer(維護者信息) MAINTAINER wangshibo 2134728394@qq.com # Commands(執行命令) RUN rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm RUN yum -y install nginx # Add(添加文件) ADD index.html /usr/share/nginx/html/index.html # index.html是自己編寫的文件,放在后面的目錄中,因為yum安裝后Documentroot是在這里 RUN echo "daemon off;" >>/etc/nginx/nginx.conf EXPOSE 80 # 對外的端口 CMD ['nginx'] # 執行的命令
3)構建容器,並運行。 建立newnginx容器,-t:標簽,執行/opt/dockerfile/nginx/下面的默認的Dockerfile文件
[root@linux-node2 nginx]# docker build -t cgt/mynginx:v3 /opt/dockerfile/nginx/ [root@linux-node2 nginx]# docker run -d -p 83:80 cgt/mynginx:v3
Docker是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然后發布到任何流行的Linux機器上,也可以實現虛擬化。當你真正投入容器Docker的懷抱,不但可以發現它能解決很多問題,而且還具有眾多的優點:
-> 它是不可變的-操作系統,庫版本,配置,文件夾和應用都是一樣的。您可以使用通過相同QA測試的鏡像,使產品具有相同的表現。
-> 它是輕量級的-容器的內存占用非常小。不需要幾百幾千MB,它只要對主進程分配內存再加上幾十MB。
-> 它很快速-啟動一個容器與啟動一個單進程一樣快。不需要幾分鍾,您可以在幾秒鍾內啟動一個全新的容器。
許多用戶依然像對待典型的虛擬機那樣對待容器,似乎都忘記了除了與虛擬機相似的部分,容器還有一個很大的優點:它是一次性的。這個"特性"本身促使用戶改變他們關於使用和管理容器的習慣;下面將會說明下在容器中不應該做這些事,以確保最大地發揮容器的作用。
-> 不要在容器中存儲數據 – 容器可能被停止,銷毀,或替換。一個運行在容器中的程序版本1.0,應該很容易被1.1的版本替換且不影響或損失數據。有鑒於此,如果你需要存儲數據,請存在卷中,並且注意如果兩個容器在同一個卷上寫數據會導致崩潰。確保你的應用被設計成在共享數據存儲上寫入。
-> 不要將你的應用發布兩份 – 一些人將容器視為虛擬機。他們中的大多數傾向於認為他們應該在現有的運行容器里發布自己的應用。在開發階段這樣是對的,此時你需要不斷地部署與調試;但對於質量保證與生產中的一個連續部署的管道,你的應用本該成為鏡像的一部分。記住:容器應該保持不變。
-> 不要創建超大鏡像 – 一個超大鏡像只會難以分發。確保你僅有運行你應用/進程的必需的文件和庫。不要安裝不必要的包或在創建中運行更新(yum更新)。
-> 不要使用單層鏡像 – 要對分層文件系統有更合理的使用,始終為你的操作系統創建你自己的基礎鏡像層,另外一層為安全和用戶定義,一層為庫的安裝,一層為配置,最后一層為應用。這將易於重建和管理一個鏡像,也易於分發。
-> 不要為運行中的容器創建鏡像 – 換言之,不要使用"docker commit"命令來創建鏡像。這種創建鏡像的方法是不可重現的也不能版本化,應該徹底避免。始終使用Dockerfile或任何其他的可完全重現的S2I(源至鏡像)方法。
-> 不要只使用"最新"標簽 – 最新標簽就像Maven用戶的"快照"。標簽是被鼓勵使用的,尤其是當你有一個分層的文件系統。你總不希望當你2個月之后創建鏡像時,驚訝地發現你的應用無法運行,因為最頂的分層被非向后兼容的新版本替換,或者創建緩存中有一個錯誤的"最新"版本。在生產中部署容器時應避免使用最新。
-> 不要在單一容器中運行超過一個進程-容器能完美地運行單個進程(http守護進程,應用服務器,數據庫),但如果運行多個進程,管理、獲取日志、獨立更新都會遇到麻煩。
-> 不要在鏡像中存儲憑據。使用環境變量 –不要將鏡像中的任何用戶名/密碼寫死。使用環境變量來從容器外部獲取此信息。
-> 使用非root用戶運行進程 – "docker容器默認以root運行。(…)隨着docker的成熟,更多的安全默認選項變得可用。現如今,請求root對於其他人是危險的,可能無法在所有環境中可用。你的鏡像應該使用USER指令來指令容器的一個非root用戶來運行。"
-> 不要依賴IP地址 – 每個容器都有自己的內部IP地址,如果你啟動並停止它地址可能會變化。如果你的應用或微服務需要與其他容器通訊,使用任何命名與(或者)環境變量來從一個容器傳遞合適信息到另一個。