Docker容器基礎介紹

 

Docker是PaaS 提供商 dotCloud 開源的一個基於 LXC 的高級容器引擎,源代碼託管在 Github 上, 基於go語言並聽從Apache2.0協議開源。Docker是經過內核虛擬化技術(namespace以及cgroups等)來提供容器的資源隔離與安全保障。因爲Docker經過操做系統層的虛擬化實現隔離,因此Docker容器在運行時,不須要相似虛擬機( VM)額外的操做系統開銷,提升資源利用率。html

Docker是使用Go語言編寫的一個程序運行、測試、交付的開放平臺,Docker被設計爲可以使你快速地交付應用。在Docker中,你能夠將你的程序分爲不一樣的基礎部分,對於每個基礎部分均可以當作一個應用程序來管理。Docker可以幫助你快速地測試、快速地編碼、快速地交付,而且縮短你從編碼到運行應用的週期。Docker使用輕量級的容器虛擬化平臺,而且結合工做流和工具,來幫助你管理、部署你的應用程序。Docker在其核心,Docker實現了讓幾乎任何程序均可以在一個安全、隔離的容器中運行。安全和隔離可使你能夠同時在機器上運行多個容器。Docker容器輕量級的特性,意味着能夠獲得更多的硬件性能。node

Docker原理創建-->傳送-->運行linux

image

經過Docker Hub或者本身的Docker倉庫分享Docker鏡像, 從Docker鏡像建立Docker容器, 在容器裏運行應用程序。nginx

Docker鏡像是如何工做的?
Docker鏡像是Docker容器運行時的只讀模板,每個鏡像由一系列的層(layers)組成;Docker使用UnionFS(聯合文件系統)來將這些層聯合到一二鏡像中,UnionFS文件系統容許獨立文件系統中的文件和文件夾(稱之爲分支)被透明覆蓋,造成一個單獨連貫的文件系統。git

正由於有了這些層(layers)的存在,Docker纔會如此的輕量。當你改變了一個Docker鏡像,好比升級到某個程序到新的版本,一個新的層會被建立。所以,不用替換整個原先的鏡像或者從新創建(在使用虛擬機的時候你可能會這麼作),只是一個新的層被添加或升級了。因此你不用從新發布整個鏡像,只須要升級。層使得分發Docker鏡像變得簡單和快速。github

每一個鏡像都是從一個基礎的鏡像開始的,好比ubuntu,一個基礎的Ubuntu鏡像,或者是Centos,一個基礎的Centos鏡像。你可使用你本身的鏡像做爲新鏡像的基礎,例如你有一個基礎的安裝了Nginx的鏡像,你可使用該鏡像來創建你的Web應用程序鏡像。(Docker一般從Docker Hub獲取基礎鏡像)docker

Docker鏡像從這些基礎的鏡像建立,經過一種簡單、具備描述性的步驟,咱們稱之爲 指令(instructions)。每個指令會在鏡像中建立一個新的層,指令能夠包含這些動做:
->  運行一個命令。
->  增長文件或者文件夾。
->  建立一個環境變量。
->  當運行容器的時候哪些程序會運行。
這些指令存儲在Dockerfile文件中。當你須要創建鏡像的時候,Docker能夠從Dockerfile中讀取這些指令而且運行,而後返回一個最終的鏡像。shell

Docker倉庫的用處?
Docker倉庫是Docker鏡像的存儲倉庫。能夠推送鏡像到Docker倉庫中,而後在Docker客戶端,能夠從Docker倉庫中搜索和拉取鏡像。數據庫

Docker容器是如何工做的?
一個Docker容器包含了一個操做系統、用戶添加的文件和元數據(meta-data)。每一個容器都是從鏡像創建的,鏡像告訴Docker容器內包含了什麼,當容器啓動時運行什麼程序,還有許多配置數據。Docker鏡像是隻讀的,當Docker運行一個從鏡像創建的容器,它會在鏡像頂部添加一個可讀寫的層,應用程序能夠在這裏運行。ubuntu

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的區別:

image

docker與Openstack的對比

image

Docker用途簡單配置、代碼流水線管理、開發效率、應用隔離、服務器整合、調試能力、多租戶、快速部署

image

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 強制刪除,包括正在運行中的容器

映射

image

隨機映射 (端口的映射是系統自動分配的)

[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"

數據管理

image

數據卷
默認掛載目錄
建立一個數據卷,名稱是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地址,若是你啓動並中止它地址可能會變化。若是你的應用或微服務須要與其餘容器通信,使用任何命名與(或者)環境變量來從一個容器傳遞合適信息到另外一個。

相關文章
相關標籤/搜索