mirror of
https://github.com/yeasy/docker_practice.git
synced 2024-12-26 15:06:18 +00:00
修正多個用詞
This commit is contained in:
parent
4789287f30
commit
9d0330915d
26
README.md
26
README.md
@ -5,19 +5,19 @@ v0.2.9
|
||||
|
||||
[Docker](docker.com) 是個偉大的項目,它徹底釋放了虛擬化的,讓應用程式的分派、部署和管理都變得前所未有的高效和輕鬆!
|
||||
|
||||
本書既適用於具備基礎 Linux 知識的 Docker 初學者,也可供希望理解原理和實現的進階用戶參考。同時,書中給出的實踐案例,可供在進行實際部署時借鑒。
|
||||
本書既適用於具備基礎 Linux 知識的 Docker 初學者,也可供希望理解原理和實做的進階使用者參考。同時,書中給出的實踐案例,可供在進行實際部署時借鑒。
|
||||
|
||||
本書源於 [WaitFish](github.com/qcpm1983) 的《[Docker 學習手冊 v1.0](https://github.com/yeasy/docker_practice/raw/master/_local/docker_manual_waitfish.pdf)》內容。後來,[yeasy](github.com/yeasy)
|
||||
根據最新 Docker 版本對內容進行了修訂和重寫,並增加內容;經協商將所有內容開源,採用互聯網合作的方式進行維護。
|
||||
根據最新 Docker 版本對內容進行了修訂和重寫,並增加內容;經協商將所有內容開源,採用網路合作的方式進行維護。
|
||||
|
||||
前六章為基礎內容,供使用者理解 Docker 的基本概念和操作;7 ~ 9 章介紹一些高級操作;第 10 章給出典型的應用場景和實踐案例;11 ~ 13 章介紹關於 Docker 實現的相關技術。
|
||||
前六章為基礎內容,供使用者理解 Docker 的基本概念和操作;7 ~ 9 章介紹一些進階操作;第 10 章給出典型的應用場景和實踐案例;11 ~ 13 章介紹關於 Docker 實做的相關技術。
|
||||
|
||||
最新版本線上閱讀:[繁體版](https://www.gitbook.io/book/philipzheng/docker_practice)、[簡體版](https://www.gitbook.io/book/yeasy/docker_practice) 或 [DockerPool](http://dockerpool.com/static/books/docker_practice/index.html)。
|
||||
最新版本線上閱讀:[正體版](https://www.gitbook.io/book/philipzheng/docker_practice)、[簡體版](https://www.gitbook.io/book/yeasy/docker_practice) 或 [DockerPool](http://dockerpool.com/static/books/docker_practice/index.html)。
|
||||
|
||||
另外,歡迎加入 [Docker.Taipei](https://www.facebook.com/groups/docker.taipei/) 和 [Meetup](http://www.meetup.com/Docker-Taipei/) ,分享 Docker 資源,交流 Docker 技術。
|
||||
|
||||
|
||||
本書源碼在 Github 上維護,歡迎參與: [https://github.com/philipz/docker_practice](https://github.com/philipz/docker_practice)。
|
||||
本書原始碼在 Github 上維護,歡迎參與: [https://github.com/philipz/docker_practice](https://github.com/philipz/docker_practice)。
|
||||
|
||||
感謝所有的 [貢獻者](https://github.com/philipz/docker_practice/graphs/contributors)。
|
||||
|
||||
@ -25,17 +25,17 @@ v0.2.9
|
||||
* 0.3: 2014-10-TODO
|
||||
* 完成倉庫章節;
|
||||
* 重寫安全章節;
|
||||
* 修正底層實現章節的架構、名字空間、控制組、檔案系統、容器格式等內容;
|
||||
* 添加對常見倉庫和鏡像的介紹;
|
||||
* 添加 Dockerfile 的介紹;
|
||||
* 修正底層實做章節的架構、名字空間、控制組、檔案系統、容器格式等內容;
|
||||
* 新增對常見倉庫和鏡像的介紹;
|
||||
* 新增 Dockerfile 的介紹;
|
||||
* 重新校訂中英文混排格式。
|
||||
* 0.2: 2014-09-18
|
||||
* 對照官方文檔重寫介紹、基本概念、安裝、鏡像、容器、倉庫、資料管理、網路等章節;
|
||||
* 添加底層實現章節;
|
||||
* 添加命令查詢和資源連結章節;
|
||||
* 新增底層實做章節;
|
||||
* 新增命令查詢和資源連結章節;
|
||||
* 其它修正。
|
||||
* 0.1: 2014-09-05
|
||||
* 添加基本內容;
|
||||
* 新增基本內容;
|
||||
* 修正錯別字和表達不通順的地方。
|
||||
|
||||
## 貢獻力量
|
||||
@ -77,9 +77,9 @@ v0.2.9
|
||||
|
||||
1. 首先 fork 我的項目
|
||||
2. 把 fork 過去的項目也就是你的項目 clone 到你的本地
|
||||
3. 在命令行執行 `git branch develop` 來創建一個新分支
|
||||
3. 在命令行執行 `git branch develop` 來建立一個新分支
|
||||
4. 執行 `git checkout develop` 來切換到新分支
|
||||
5. 執行 `git remote add upstream https://github.com/philipz/docker_practice` 把我的庫添加為遠端庫
|
||||
5. 執行 `git remote add upstream https://github.com/philipz/docker_practice` 把我的庫新增為遠端庫
|
||||
6. 執行 `git remote update`更新
|
||||
7. 執行 `git fetch upstream master` 拉取我的庫的更新到本地
|
||||
8. 執行 `git rebase upstream/master` 將我的更新合並到你的分支
|
||||
|
12
SUMMARY.md
12
SUMMARY.md
@ -14,10 +14,10 @@
|
||||
* [映像檔](image/README.md)
|
||||
* [獲取映像檔](image/pull.md)
|
||||
* [列出](image/list.md)
|
||||
* [創建](image/create.md)
|
||||
* [建立](image/create.md)
|
||||
* [存出和載入](image/save_load.md)
|
||||
* [移除](image/rmi.md)
|
||||
* [實現原理](image/internal.md)
|
||||
* [實做原理](image/internal.md)
|
||||
* [容器](container/README.md)
|
||||
* [啟動](container/run.md)
|
||||
* [守護態執行](container/daemon.md)
|
||||
@ -36,11 +36,11 @@
|
||||
* [使用網路](network/README.md)
|
||||
* [外部訪問容器](network/port_mapping.md)
|
||||
* [容器互連](network/linking.md)
|
||||
* [高級網路配置](advanced_network/README.md)
|
||||
* [進階網路配置](advanced_network/README.md)
|
||||
* [快速配置指南](advanced_network/quick_guide.md)
|
||||
* [配置 DNS](advanced_network/dns.md)
|
||||
* [容器訪問控制](advanced_network/access_control.md)
|
||||
* [端口映射實現](advanced_network/port_mapping.md)
|
||||
* [端口映射實做](advanced_network/port_mapping.md)
|
||||
* [配置 docker0 網橋](advanced_network/docker0.md)
|
||||
* [自定義網橋](advanced_network/bridge.md)
|
||||
* [工具與範例](advanced_network/example.md)
|
||||
@ -48,7 +48,7 @@
|
||||
* [實例:創造一個點對點連接](advanced_network/ptp.md)
|
||||
* [實戰案例](cases/README.md)
|
||||
* [使用 Supervisor 來管理程序](cases/supervisor.md)
|
||||
* [創建 tomcat/weblogic 集群](cases/tomcat.md)
|
||||
* [建立 tomcat/weblogic 集群](cases/tomcat.md)
|
||||
* [多台實體主機之間的容器互連](cases/container_connect.md)
|
||||
* [標準化開發測試和生產環境](cases/environment.md)
|
||||
* [安全](security/README.md)
|
||||
@ -62,7 +62,7 @@
|
||||
* [基本結構](dockerfile/basic_structure.md)
|
||||
* [指令](dockerfile/instructions.md)
|
||||
* [建立映像檔](dockerfile/build_image.md)
|
||||
* [底層實現](underly/README.md)
|
||||
* [底層實做](underly/README.md)
|
||||
* [基本架構](underly/arch.md)
|
||||
* [命名空間](underly/namespace.md)
|
||||
* [控制組](underly/cgroups.md)
|
||||
|
@ -1,12 +1,12 @@
|
||||
# 高級網路配置
|
||||
本章將介紹 Docker 的一些高級網路配置和選項。
|
||||
# 進階網路配置
|
||||
本章將介紹 Docker 的一些進階網路配置和選項。
|
||||
|
||||
當 Docker 啟動時,會自動在主機上創建一個 `docker0` 虛擬橋接器,實際上是 Linux 的一個 bridge,可以理解為一個軟體交換機。它會在掛載到它的網卡之間進行轉發。
|
||||
當 Docker 啟動時,會自動在主機上建立一個 `docker0` 虛擬橋接器,實際上是 Linux 的一個 bridge,可以理解為一個軟體交換機。它會在掛載到它的網卡之間進行轉發。
|
||||
|
||||
同時,Docker 隨機分配一個本地未占用的私有網段(在 [RFC1918](http://tools.ietf.org/html/rfc1918) 中定義)中的一個地址給 `docker0` 接口。比如典型的 `172.17.42.1`,網路遮罩為 `255.255.0.0`。此後啟動的容器內的網卡也會自動分配一個同一網段(`172.17.0.0/16`)的網址。
|
||||
|
||||
當創建一個 Docker 容器的時候,同時會創建了一對 `veth pair` 接口(當數據包發送到一個接口時,另外一個接口也可以收到相同的數據包)。這對接口一端在容器內,即 `eth0`;另一端在本地並被掛載到 `docker0` 網橋,名稱以 `veth` 開頭(例如 `vethAQI2QT`)。通過這種方式,主機可以跟容器通信,容器之間也可以相互通信。Docker 就創建了在主機和所有容器之間一個虛擬共享網路。
|
||||
當建立一個 Docker 容器的時候,同時會建立了一對 `veth pair` 接口(當數據包發送到一個接口時,另外一個接口也可以收到相同的數據包)。這對接口一端在容器內,即 `eth0`;另一端在本地並被掛載到 `docker0` 網橋,名稱以 `veth` 開頭(例如 `vethAQI2QT`)。透過這種方式,主機可以跟容器通信,容器之間也可以相互通信。Docker 就建立了在主機和所有容器之間一個虛擬共享網路。
|
||||
|
||||
![Docker 網路](../_images/network.png)
|
||||
|
||||
接下來的部分將介紹在一些場景中,Docker 所有的網路自訂配置。以及通過 Linux 命令來調整、補充、甚至替換 Docker 預設的網路配置。
|
||||
接下來的部分將介紹在一些場景中,Docker 所有的網路自訂配置。以及透過 Linux 命令來調整、補充、甚至替換 Docker 預設的網路配置。
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 容器訪問控制
|
||||
容器的訪問控制,主要通過 Linux 上的 `iptables` 防火墻來進行管理和實現。`iptables` 是 Linux 上默認的防火墻軟件,在大部分發行版中都自帶。
|
||||
容器的訪問控制,主要透過 Linux 上的 `iptables` 防火墻來進行管理和實做。`iptables` 是 Linux 上默認的防火墻軟件,在大部分發行版中都自帶。
|
||||
|
||||
### 容器訪問外部網路
|
||||
容器要想訪問外部網路,需要本地系統的轉發支持。在Linux 系統中,檢查轉發是否打開。
|
||||
@ -17,15 +17,15 @@ $sysctl -w net.ipv4.ip_forward=1
|
||||
### 容器之間訪問
|
||||
容器之間相互訪問,需要兩方面的支持。
|
||||
* 容器的網路拓撲是否已經互聯。默認情況下,所有容器都會被連接到 `docker0` 網橋上。
|
||||
* 本地系統的防火墻軟件 -- `iptables` 是否允許通過。
|
||||
* 本地系統的防火墻軟件 -- `iptables` 是否允許透過。
|
||||
|
||||
#### 訪問所有端口
|
||||
當啟動 Docker 服務時候,默認會添加一條轉發策略到 iptables 的 FORWARD 鏈上。策略為通過(`ACCEPT`)還是禁止(`DROP`)取決於配置`--icc=true`(缺省值)還是 `--icc=false`。當然,如果手動指定 `--iptables=false` 則不會添加 `iptables` 規則。
|
||||
當啟動 Docker 服務時候,默認會新增一條轉發策略到 iptables 的 FORWARD 鏈上。策略為透過(`ACCEPT`)還是禁止(`DROP`)取決於配置`--icc=true`(缺省值)還是 `--icc=false`。當然,如果手動指定 `--iptables=false` 則不會新增 `iptables` 規則。
|
||||
|
||||
可見,默認情況下,不同容器之間是允許網路互通的。如果為了安全考慮,可以在 `/etc/default/docker` 文件中配置 `DOCKER_OPTS=--icc=false` 來禁止它。
|
||||
|
||||
#### 訪問指定端口
|
||||
在通過 `-icc=false` 關閉網路訪問後,還可以通過 `--link=CONTAINER_NAME:ALIAS` 選項來訪問容器的開放端口。
|
||||
在透過 `-icc=false` 關閉網路訪問後,還可以透過 `--link=CONTAINER_NAME:ALIAS` 選項來訪問容器的開放端口。
|
||||
|
||||
例如,在啟動 Docker 服務時,可以同時使用 `icc=false --iptables=true` 參數來關閉允許相互的網路訪問,並讓 Docker 可以修改系統中的 `iptables` 規則。
|
||||
|
||||
@ -39,9 +39,9 @@ DROP all -- 0.0.0.0/0 0.0.0.0/0
|
||||
...
|
||||
```
|
||||
|
||||
之後,啟動容器(`docker run`)時使用 `--link=CONTAINER_NAME:ALIAS` 選項。Docker 會在 `iptable` 中為 兩個容器分別添加一條 `ACCEPT` 規則,允許相互訪問開放的端口(取決於 Dockerfile 中的 EXPOSE 行)。
|
||||
之後,啟動容器(`docker run`)時使用 `--link=CONTAINER_NAME:ALIAS` 選項。Docker 會在 `iptable` 中為 兩個容器分別新增一條 `ACCEPT` 規則,允許相互訪問開放的端口(取決於 Dockerfile 中的 EXPOSE 行)。
|
||||
|
||||
當添加了 `--link=CONTAINER_NAME:ALIAS` 選項後,添加了 `iptables` 規則。
|
||||
當新增了 `--link=CONTAINER_NAME:ALIAS` 選項後,新增了 `iptables` 規則。
|
||||
```
|
||||
$ sudo iptables -nL
|
||||
...
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 自定義網橋
|
||||
除了默認的 `docker0` 網橋,用戶也可以指定網橋來連接各個容器。
|
||||
除了默認的 `docker0` 網橋,使用者也可以指定網橋來連接各個容器。
|
||||
|
||||
在啟動 Docker 服務的時候,使用 `-b BRIDGE`或`--bridge=BRIDGE` 來指定使用的網橋。
|
||||
|
||||
@ -9,13 +9,13 @@ $ sudo service docker stop
|
||||
$ sudo ip link set dev docker0 down
|
||||
$ sudo brctl delbr docker0
|
||||
```
|
||||
然後創建一個網橋 `bridge0`。
|
||||
然後建立一個網橋 `bridge0`。
|
||||
```
|
||||
$ sudo brctl addbr bridge0
|
||||
$ sudo ip addr add 192.168.5.1/24 dev bridge0
|
||||
$ sudo ip link set dev bridge0 up
|
||||
```
|
||||
查看確認網橋創建並啟動。
|
||||
查看確認網橋建立並啟動。
|
||||
```
|
||||
$ ip addr show bridge0
|
||||
4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default
|
||||
@ -23,7 +23,7 @@ $ ip addr show bridge0
|
||||
inet 192.168.5.1/24 scope global bridge0
|
||||
valid_lft forever preferred_lft forever
|
||||
```
|
||||
配置 Docker 服務,默認橋接到創建的網橋上。
|
||||
配置 Docker 服務,默認橋接到建立的網橋上。
|
||||
```
|
||||
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
|
||||
$ sudo service docker start
|
||||
|
@ -11,18 +11,18 @@ $ mount
|
||||
tmpfs on /etc/resolv.conf type tmpfs ...
|
||||
...
|
||||
```
|
||||
這種機制可以讓宿主主機 DNS 信息發生更新後,所有 Docker 容器的 dns 配置通過 `/etc/resolv.conf` 文件立刻得到更新。
|
||||
這種機制可以讓宿主主機 DNS 信息發生更新後,所有 Docker 容器的 dns 配置透過 `/etc/resolv.conf` 文件立刻得到更新。
|
||||
|
||||
如果用戶想要手動指定容器的配置,可以利用下面的選項。
|
||||
如果使用者想要手動指定容器的配置,可以利用下面的選項。
|
||||
|
||||
`-h HOSTNAME or --hostname=HOSTNAME`
|
||||
設定容器的主機名,它會被寫到容器內的 `/etc/hostname` 和 `/etc/hosts`。但它在容器外部看不到,既不會在 `docker ps` 中顯示,也不會在其他的容器的 `/etc/hosts` 看到。
|
||||
|
||||
`--link=CONTAINER_NAME:ALIAS`
|
||||
選項會在創建容器的時候,添加一個其他容器的主機名到 `/etc/hosts` 文件中,讓新容器的程序可以使用主機名 ALIAS 就可以連接它。
|
||||
選項會在建立容器的時候,新增一個其他容器的主機名到 `/etc/hosts` 文件中,讓新容器的程序可以使用主機名 ALIAS 就可以連接它。
|
||||
|
||||
`--dns=IP_ADDRESS`
|
||||
添加 DNS 服務器到容器的 `/etc/resolv.conf` 中,讓容器用這個服務器來解析所有不在 `/etc/hosts` 中的主機名。
|
||||
新增 DNS 服務器到容器的 `/etc/resolv.conf` 中,讓容器用這個服務器來解析所有不在 `/etc/hosts` 中的主機名。
|
||||
|
||||
`--dns-search=DOMAIN`
|
||||
設定容器的搜索域,當設定搜索域為 `.example.com` 時,在搜索一個名為 host 的主機時,DNS 不僅搜索host,還會搜索 `host.example.com`。
|
||||
|
@ -1,12 +1,12 @@
|
||||
## 配置 docker0 網橋
|
||||
Docker 服務默認會創建一個 `docker0` 網橋(其上有一個 `docker0` 內部接口),它在內核層連通了其他的物理或虛擬網卡,這就將所有容器和本地主機都放到同一個物理網路。
|
||||
Docker 服務默認會建立一個 `docker0` 網橋(其上有一個 `docker0` 內部接口),它在內核層連通了其他的物理或虛擬網卡,這就將所有容器和本地主機都放到同一個物理網路。
|
||||
|
||||
Docker 默認指定了 `docker0` 接口 的 IP 地址和子網掩碼,讓主機和容器之間可以通過網橋相互通信,它還給出了 MTU(接口允許接收的最大傳輸單元),通常是 1500 Bytes,或宿主主機網路路由上支持的默認值。這些值都可以在服務啟動的時候進行配置。
|
||||
Docker 默認指定了 `docker0` 接口 的 IP 地址和子網掩碼,讓主機和容器之間可以透過網橋相互通信,它還給出了 MTU(接口允許接收的最大傳輸單元),通常是 1500 Bytes,或宿主主機網路路由上支持的默認值。這些值都可以在服務啟動的時候進行配置。
|
||||
* `--bip=CIDR` -- IP 地址加掩碼格式,例如 192.168.1.5/24
|
||||
* `--mtu=BYTES` -- 覆蓋默認的 Docker mtu 配置
|
||||
|
||||
也可以在配置文件中配置 DOCKER_OPTS,然後重啟服務。
|
||||
由於目前 Docker 網橋是 Linux 網橋,用戶可以使用 `brctl show` 來查看網橋和端口連接信息。
|
||||
由於目前 Docker 網橋是 Linux 網橋,使用者可以使用 `brctl show` 來查看網橋和端口連接信息。
|
||||
```
|
||||
$ sudo brctl show
|
||||
bridge name bridge id STP enabled interfaces
|
||||
@ -16,7 +16,7 @@ docker0 8000.3a1d7362b4ee no veth65f9
|
||||
*註:`brctl` 命令在 Debian、Ubuntu 中可以使用 `sudo apt-get install bridge-utils` 來安裝。
|
||||
|
||||
|
||||
每次創建一個新容器的時候,Docker 從可用的地址段中選擇一個空閑的 IP 地址分配給容器的 eth0 端口。使用本地主機上 `docker0` 接口的 IP 作為所有容器的默認網關。
|
||||
每次建立一個新容器的時候,Docker 從可用的地址段中選擇一個空閑的 IP 地址分配給容器的 eth0 端口。使用本地主機上 `docker0` 接口的 IP 作為所有容器的默認網關。
|
||||
```
|
||||
$ sudo docker run -i -t --rm base /bin/bash
|
||||
$ ip addr show eth0
|
||||
|
@ -2,7 +2,7 @@
|
||||
在介紹自定義網路拓撲之前,你可能會對一些外部工具和例子感興趣:
|
||||
|
||||
### pipework
|
||||
Jérôme Petazzoni 編寫了一個叫 [pipework](https://github.com/jpetazzo/pipework) 的 shell 腳本,可以幫助用戶在比較復雜的場景中完成容器的連接。
|
||||
Jérôme Petazzoni 編寫了一個叫 [pipework](https://github.com/jpetazzo/pipework) 的 shell 腳本,可以幫助使用者在比較復雜的場景中完成容器的連接。
|
||||
|
||||
### playground
|
||||
Brandon Rhodes 創建了一個提供完整的 Docker 容器網路拓撲管理的 [Python庫](https://github.com/brandon-rhodes/fopnp/tree/m/playground),包括路由、NAT 防火墻;以及一些提供 HTTP, SMTP, POP, IMAP, Telnet, SSH, FTP 的服務器。
|
||||
Brandon Rhodes 建立了一個提供完整的 Docker 容器網路拓撲管理的 [Python庫](https://github.com/brandon-rhodes/fopnp/tree/m/playground),包括路由、NAT 防火墻;以及一些提供 HTTP, SMTP, POP, IMAP, Telnet, SSH, FTP 的服務器。
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 映射容器端口到宿主主機的實現
|
||||
## 映射容器端口到宿主主機的實做
|
||||
|
||||
默認情況下,容器可以主動訪問到外部網路的連接,但是外部網路無法訪問到容器。
|
||||
### 容器訪問外部實現
|
||||
容器所有到外部網路的連接,源地址都會被NAT成本地系統的IP地址。這是使用 `iptables` 的源地址偽裝操作實現的。
|
||||
### 容器訪問外部實做
|
||||
容器所有到外部網路的連接,源地址都會被NAT成本地系統的IP地址。這是使用 `iptables` 的源地址偽裝操作實做的。
|
||||
|
||||
查看主機的 NAT 規則。
|
||||
```
|
||||
@ -15,11 +15,11 @@ MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16
|
||||
```
|
||||
其中,上述規則將所有源地址在 `172.17.0.0/16` 網段,目標地址為其他網段(外部網路)的流量動態偽裝為從系統網卡發出。MASQUERADE 跟傳統 SNAT 的好處是它能動態從網卡獲取地址。
|
||||
|
||||
### 外部訪問容器實現
|
||||
### 外部訪問容器實做
|
||||
|
||||
容器允許外部訪問,可以在 `docker run` 時候通過 `-p` 或 `-P` 參數來啟用。
|
||||
容器允許外部訪問,可以在 `docker run` 時候透過 `-p` 或 `-P` 參數來啟用。
|
||||
|
||||
不管用那種辦法,其實也是在本地的 `iptable` 的 nat 表中添加相應的規則。
|
||||
不管用那種辦法,其實也是在本地的 `iptable` 的 nat 表中新增相應的規則。
|
||||
|
||||
使用 `-P` 時:
|
||||
```
|
||||
@ -38,6 +38,6 @@ target prot opt source destination
|
||||
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
|
||||
```
|
||||
註意:
|
||||
* 這裏的規則映射了 0.0.0.0,意味著將接受主機來自所有接口的流量。用戶可以通過 `-p IP:host_port:container_port` 或 `-p
|
||||
* 這裏的規則映射了 0.0.0.0,意味著將接受主機來自所有接口的流量。使用者可以透過 `-p IP:host_port:container_port` 或 `-p
|
||||
IP::port` 來指定允許訪問容器的主機上的 IP、接口等,以制定更嚴格的規則。
|
||||
* 如果希望永久綁定到某個固定的 IP 地址,可以在 Docker 配置文件 `/etc/default/docker` 中指定 `DOCKER_OPTS="--ip=IP_ADDRESS"`,之後重啟 Docker 服務即可生效。
|
||||
|
@ -1,9 +1,9 @@
|
||||
## 示例:創建一個點到點連接
|
||||
## 示例:建立一個點到點連接
|
||||
默認情況下,Docker 會將所有容器連接到由 `docker0` 提供的虛擬子網中。
|
||||
|
||||
用戶有時候需要兩個容器之間可以直連通信,而不用通過主機網橋進行橋接。
|
||||
使用者有時候需要兩個容器之間可以直連通信,而不用透過主機網橋進行橋接。
|
||||
|
||||
解決辦法很簡單:創建一對 `peer` 接口,分別放到兩個容器中,配置成點到點鏈路類型即可。
|
||||
解決辦法很簡單:建立一對 `peer` 接口,分別放到兩個容器中,配置成點到點鏈路類型即可。
|
||||
|
||||
首先啟動 2 個容器:
|
||||
```
|
||||
@ -13,7 +13,7 @@ $ sudo docker run -i -t --rm --net=none base /bin/bash
|
||||
root@12e343489d2f:/#
|
||||
```
|
||||
|
||||
找到程序號,然後創建網路名字空間的跟蹤文件。
|
||||
找到程序號,然後建立網路名字空間的跟蹤文件。
|
||||
```
|
||||
$ sudo docker inspect -f '{{.State.Pid}}' 1f1f4c1f931a
|
||||
2989
|
||||
@ -24,7 +24,7 @@ $ sudo ln -s /proc/2989/ns/net /var/run/netns/2989
|
||||
$ sudo ln -s /proc/3004/ns/net /var/run/netns/3004
|
||||
```
|
||||
|
||||
創建一對 `peer` 接口,然後配置路由
|
||||
建立一對 `peer` 接口,然後配置路由
|
||||
```
|
||||
$ sudo ip link add A type veth peer name B
|
||||
|
||||
@ -40,6 +40,6 @@ $ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B
|
||||
```
|
||||
現在這 2 個容器就可以相互 ping 通,並成功建立連接。點到點鏈路不需要子網和子網掩碼。
|
||||
|
||||
此外,也可以不指定 `--net=none` 來創建點到點鏈路。這樣容器還可以通過原先的網路來通信。
|
||||
此外,也可以不指定 `--net=none` 來建立點到點鏈路。這樣容器還可以透過原先的網路來通信。
|
||||
|
||||
利用類似的辦法,可以創建一個只跟主機通信的容器。但是一般情況下,更推薦使用 `--icc=false` 來關閉容器之間的通信。
|
||||
利用類似的辦法,可以建立一個只跟主機通信的容器。但是一般情況下,更推薦使用 `--icc=false` 來關閉容器之間的通信。
|
||||
|
@ -8,7 +8,7 @@
|
||||
* `-H SOCKET... or --host=SOCKET...` --Docker 服務端接收命令的通道
|
||||
* `--icc=true|false` --是否支持容器之間進行通信
|
||||
* `--ip-forward=true|false` --請看下文容器之間的通信
|
||||
* `--iptables=true|false` --禁止 Docker 添加 iptables 規則
|
||||
* `--iptables=true|false` --禁止 Docker 新增 iptables 規則
|
||||
* `--mtu=BYTES` --容器網路中的 MTU
|
||||
|
||||
下面2個命令選項既可以在啟動服務時指定,也可以 Docker 容器啟動(`docker run`)時候指定。在 Docker 服務啟動的時候指定則會成為默認值,後面執行 `docker run` 時可以覆蓋設置的默認值。
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
最後這些選項只有在 `docker run` 執行時使用,因為它是針對容器的特性內容。
|
||||
* `-h HOSTNAME or --hostname=HOSTNAME` --配置容器主機名
|
||||
* `--link=CONTAINER_NAME:ALIAS` --添加到另一個容器的連接
|
||||
* `--link=CONTAINER_NAME:ALIAS` --新增到另一個容器的連接
|
||||
* `--net=bridge|none|container:NAME_or_ID|host` --配置容器的橋接模式
|
||||
* `-p SPEC or --publish=SPEC` --映射容器端口到宿主主機
|
||||
* `-P or --publish-all=true|false` --映射容器所有端口到宿主主機
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
##基本語法
|
||||
docker [OPTIONS] COMMAND [arg...]
|
||||
一般來說,Docker 命令可以用來管理 daemon,或者通過 CLI 命令管理映像檔和容器。可以通過 `man docker` 來查看這些命令。
|
||||
一般來說,Docker 命令可以用來管理 daemon,或者透過 CLI 命令管理映像檔和容器。可以透過 `man docker` 來查看這些命令。
|
||||
|
||||
|
||||
##選項
|
||||
@ -10,7 +10,7 @@
|
||||
使用 debug 模式。預設為 false。
|
||||
|
||||
-H, --host=[unix:///var/run/docker.sock]: tcp://[host:port]來綁定或者 unix://[/path/to/socket] 來使用。
|
||||
在 daemon 模式下綁定的 socket,通過一個或多個 tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd 來指定。
|
||||
在 daemon 模式下綁定的 socket,透過一個或多個 tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd 來指定。
|
||||
|
||||
--api-enable-cors=true|false
|
||||
在遠端 API 中啟用 CORS 頭。預設為 false。
|
||||
@ -19,7 +19,7 @@
|
||||
將容器掛載到一個已存在的網橋上。指定為 'none' 時則禁用容器的網路。
|
||||
|
||||
--bip=""
|
||||
讓動態創建的 docker0 采用指定的 CIDR 地址; 與 -b 選項互斥。
|
||||
讓動態建立的 docker0 采用指定的 CIDR 地址; 與 -b 選項互斥。
|
||||
|
||||
-d=true|false
|
||||
使用 daemon 模式。預設為 false。
|
||||
@ -37,7 +37,7 @@
|
||||
綁定端口時候的預設 IP 地址。預設為 0.0.0.0。
|
||||
|
||||
--iptables=true|false
|
||||
禁止 Docker 添加 iptables 規則。預設為 true。
|
||||
禁止 Docker 新增 iptables 規則。預設為 true。
|
||||
|
||||
--mtu=VALUE
|
||||
指定容器網路的 mtu。預設為 1500。
|
||||
@ -62,10 +62,10 @@ Docker 的命令可以采用 `docker-CMD` 或者 `docker CMD` 的方式執行。
|
||||
依附到一個正在執行的容器中。
|
||||
|
||||
docker-build(1)
|
||||
從一個 Dockerfile 創建一個映像檔
|
||||
從一個 Dockerfile 建立一個映像檔
|
||||
|
||||
docker-commit(1)
|
||||
從一個容器的修改中創建一個新的映像檔
|
||||
從一個容器的修改中建立一個新的映像檔
|
||||
|
||||
docker-cp(1)
|
||||
從容器中複製文件到宿主系統中
|
||||
@ -86,7 +86,7 @@ Docker 的命令可以采用 `docker-CMD` 或者 `docker CMD` 的方式執行。
|
||||
列出存在的映像檔
|
||||
|
||||
docker-import(1)
|
||||
匯入一個文件(典型為 tar 包)路徑或目錄來創建一個映像檔
|
||||
匯入一個文件(典型為 tar 包)路徑或目錄來建立一個映像檔
|
||||
|
||||
docker-info(1)
|
||||
顯示一些相關的系統資訊
|
||||
@ -134,7 +134,7 @@ Docker 的命令可以采用 `docker-CMD` 或者 `docker CMD` 的方式執行。
|
||||
刪除指定的數個映像檔
|
||||
|
||||
docker-run(1)
|
||||
創建一個新容器,並在其中執行指定命令
|
||||
建立一個新容器,並在其中執行指定命令
|
||||
|
||||
docker-save(1)
|
||||
保存一個映像檔為 tar 包文件
|
||||
|
@ -1,7 +1,7 @@
|
||||
## [MongoDB](https://registry.hub.docker.com/_/mongo/)
|
||||
|
||||
### 基本信息
|
||||
[MongoDB](https://en.wikipedia.org/wiki/MongoDB) 是開源的 NoSQL 數據庫實現。
|
||||
[MongoDB](https://en.wikipedia.org/wiki/MongoDB) 是開源的 NoSQL 數據庫實做。
|
||||
該倉庫提供了 MongoDB 2.2 ~ 2.7 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
@ -14,7 +14,7 @@ $ sudo docker run --name some-mongo -d mongo
|
||||
```
|
||||
$ sudo docker run --name some-app --link some-mongo:mongo -d application-that-uses-mongo
|
||||
```
|
||||
或者通過 `mongo`
|
||||
或者透過 `mongo`
|
||||
```
|
||||
$ sudo docker run -it --link some-mongo:mongo --rm mongo sh -c 'exec mongo "$MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test"'
|
||||
```
|
||||
|
@ -1,7 +1,7 @@
|
||||
## [MySQL](https://registry.hub.docker.com/_/mysql/)
|
||||
|
||||
### 基本信息
|
||||
[MySQL](https://en.wikipedia.org/wiki/MySQL) 是開源的關系數據庫實現。
|
||||
[MySQL](https://en.wikipedia.org/wiki/MySQL) 是開源的關系數據庫實做。
|
||||
該倉庫提供了 MySQL 各個版本的鏡像,包括 5.6 系列、5.7 系列等。
|
||||
|
||||
### 使用方法
|
||||
@ -13,7 +13,7 @@ $ sudo docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=mysecretpassword -d m
|
||||
```
|
||||
$ sudo docker run --name some-app --link some-mysql:mysql -d application-that-uses-mysql
|
||||
```
|
||||
或者通過 `mysql`。
|
||||
或者透過 `mysql`。
|
||||
```
|
||||
$ sudo docker run -it --link some-mysql:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'
|
||||
```
|
||||
|
@ -1,7 +1,7 @@
|
||||
## [Nginx](https://registry.hub.docker.com/_/nginx/)
|
||||
|
||||
### 基本信息
|
||||
[Nginx](https://en.wikipedia.org/wiki/Nginx) 是開源的高效的 Web 服務器實現,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等協議。
|
||||
[Nginx](https://en.wikipedia.org/wiki/Nginx) 是開源的高效的 Web 服務器實做,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等協議。
|
||||
該倉庫提供了 Nginx 1.0 ~ 1.7 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
@ -9,7 +9,7 @@
|
||||
```
|
||||
$ sudo docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
|
||||
```
|
||||
用戶也可以不使用這種映射方式,通過利用 Dockerfile 來直接將靜態頁面內容放到鏡像中,內容為
|
||||
使用者也可以不使用這種映射方式,透過利用 Dockerfile 來直接將靜態頁面內容放到鏡像中,內容為
|
||||
```
|
||||
FROM nginx
|
||||
COPY static-html-directory /usr/share/nginx/html
|
||||
@ -24,7 +24,7 @@ $ sudo docker run --name some-nginx -d some-content-nginx
|
||||
sudo docker run --name some-nginx -d -p 8080:80 some-content-nginx
|
||||
```
|
||||
|
||||
Nginx的默認配置文件路徑為 `/etc/nginx/nginx.conf`,可以通過映射它來使用本地的配置文件,例如
|
||||
Nginx的默認配置文件路徑為 `/etc/nginx/nginx.conf`,可以透過映射它來使用本地的配置文件,例如
|
||||
```
|
||||
docker run --name some-nginx -v /some/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx
|
||||
```
|
||||
|
@ -5,13 +5,13 @@
|
||||
該倉庫提供了 Node.js 0.8 ~ 0.11 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
在項目中創建一個 Dockerfile。
|
||||
在項目中建立一個 Dockerfile。
|
||||
```
|
||||
FROM node:0.10-onbuild
|
||||
# replace this with your application's default port
|
||||
EXPOSE 8888
|
||||
```
|
||||
然後創建鏡像,並啟動容器
|
||||
然後建立鏡像,並啟動容器
|
||||
```
|
||||
$ sudo docker build -t my-nodejs-app
|
||||
$ sudo docker run -it --rm --name my-running-app my-nodejs-app
|
||||
|
@ -1,7 +1,7 @@
|
||||
## [Redis](https://registry.hub.docker.com/_/redis/)
|
||||
|
||||
### 基本信息
|
||||
[Redis](https://en.wikipedia.org/wiki/Redis) 是開源的內存 Key-Value 數據庫實現。
|
||||
[Redis](https://en.wikipedia.org/wiki/Redis) 是開源的內存 Key-Value 數據庫實做。
|
||||
該倉庫提供了 Redis 2.6 ~ 2.8.9 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
@ -19,7 +19,7 @@ $ sudo docker run --name some-redis -d redis redis-server --appendonly yes
|
||||
```
|
||||
$ sudo docker run --name some-app --link some-redis:redis -d application-that-uses-redis
|
||||
```
|
||||
或者通過 `redis-cli`
|
||||
或者透過 `redis-cli`
|
||||
```
|
||||
$ sudo docker run -it --link some-redis:redis --rm redis sh -c 'exec redis-cli -h "$REDIS_PORT_6379_TCP_ADDR" -p "$REDIS_PORT_6379_TCP_PORT"'
|
||||
```
|
||||
|
@ -1,8 +1,8 @@
|
||||
## Docker 容器
|
||||
Docker 利用容器來執行應用。
|
||||
|
||||
容器是從映像檔創建的執行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平台。
|
||||
容器是從映像檔建立的執行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平台。
|
||||
|
||||
可以把容器看做是一個簡易版的 Linux 環境(包括root用戶權限、程序空間、用戶空間和網路空間等)和在其中執行的應用程序。
|
||||
可以把容器看做是一個簡易版的 Linux 環境(包括root使用者權限、程序空間、使用者空間和網路空間等)和在其中執行的應用程序。
|
||||
|
||||
*註:映像檔是唯讀的,容器在啟動的時候創建一層可寫層作為最上層。
|
||||
*註:映像檔是唯讀的,容器在啟動的時候建立一層可寫層作為最上層。
|
||||
|
@ -1,8 +1,8 @@
|
||||
## Docker 映像檔
|
||||
Docker 映像檔就是一個唯讀的模板。
|
||||
|
||||
例如:一個映像檔可以包含一個完整的 ubuntu 作業系統環境,裡面僅安裝了 Apache 或用戶需要的其它應用程序。
|
||||
例如:一個映像檔可以包含一個完整的 ubuntu 作業系統環境,裡面僅安裝了 Apache 或使用者需要的其它應用程序。
|
||||
|
||||
映像檔可以用來創建 Docker 容器。
|
||||
映像檔可以用來建立 Docker 容器。
|
||||
|
||||
Docker 提供了一個很簡單的機制來創建映像檔或者更新現有的映像檔,用戶甚至可以直接從其他人那裡下載一個已經做好的映像檔來直接使用。
|
||||
Docker 提供了一個很簡單的機制來建立映像檔或者更新現有的映像檔,使用者甚至可以直接從其他人那裡下載一個已經做好的映像檔來直接使用。
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式。
|
||||
|
||||
最大的公開倉庫是 [Docker Hub](https://hub.docker.com),存放了數量龐大的映像檔供用戶下載。
|
||||
大陸的公開倉庫包括 [Docker Pool](http://www.dockerpool.com) 等,可以提供大陸用戶更穩定快速的訪問。
|
||||
最大的公開倉庫是 [Docker Hub](https://hub.docker.com),存放了數量龐大的映像檔供使用者下載。
|
||||
大陸的公開倉庫包括 [Docker Pool](http://www.dockerpool.com) 等,可以提供大陸使用者更穩定快速的訪問。
|
||||
|
||||
當然,用戶也可以在本地網路內創建一個私有倉庫。
|
||||
當然,使用者也可以在本地網路內建立一個私有倉庫。
|
||||
|
||||
當用戶創建了自己的映像檔之後就可以使用 `push` 命令將它上傳到公有或者私有倉庫,這樣下次在另外一台機器上使用這個映像檔時候,只需要從倉庫上 `pull` 下來就可以了。
|
||||
當使用者建立了自己的映像檔之後就可以使用 `push` 命令將它上傳到公有或者私有倉庫,這樣下次在另外一台機器上使用這個映像檔時候,只需要從倉庫上 `pull` 下來就可以了。
|
||||
|
||||
*註:Docker 倉庫的概念跟 [Git](http://git-scm.com) 類似,註冊服務器可以理解為 GitHub 這樣的託管服務。
|
||||
|
@ -23,7 +23,7 @@ root@ac6474aeb31d:~# ip a
|
||||
inet6 fe80::487d:68ff:feda:9cf/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
```
|
||||
這樣就可以把這個網路看成是一個私有的網路,通過 nat 連接外網,如果要讓外網連接到容器中,就需要做端口映射,即 -p 參數。
|
||||
這樣就可以把這個網路看成是一個私有的網路,透過 nat 連接外網,如果要讓外網連接到容器中,就需要做端口映射,即 -p 參數。
|
||||
|
||||
如果在企業內部應用,或者做多個物理主機的集群,可能需要將多個物理主機的容器組到一個物理網路中來,那麽就需要將這個網橋橋接到我們指定的網卡上。
|
||||
|
||||
@ -32,8 +32,8 @@ root@ac6474aeb31d:~# ip a
|
||||
![物理拓撲圖](../_images/container_connect_topology.png)
|
||||
|
||||
### ubuntu 示例
|
||||
下面以 ubuntu 為例創建多個主機的容器聯網:
|
||||
創建自己的網橋,編輯 /etc/network/interface 文件
|
||||
下面以 ubuntu 為例建立多個主機的容器聯網:
|
||||
建立自己的網橋,編輯 /etc/network/interface 文件
|
||||
```
|
||||
auto br0
|
||||
iface br0 inet static
|
||||
@ -46,7 +46,7 @@ dns-nameservers 8.8.8.8 192.168.6.1
|
||||
```
|
||||
將 Docker 的默認網橋綁定到這個新建的 br0 上面,這樣就將這臺機器上容器綁定到 em1 這個網卡所對應的物理網路上了。
|
||||
|
||||
ubuntu 修改 /etc/default/docker 文件,添加最後一行內容
|
||||
ubuntu 修改 /etc/default/docker 文件,新增最後一行內容
|
||||
|
||||
```
|
||||
# Docker Upstart and SysVinit configuration file
|
||||
@ -75,4 +75,4 @@ bridge name bridge id STP enabled interfaces
|
||||
br0 8000.7e6e617c8d53 no em1
|
||||
vethe6e5
|
||||
```
|
||||
這樣就直接把容器暴露到物理網路上了,多臺物理主機的容器也可以相互聯網了。需要註意的是,這樣就需要自己來保證容器的網路安全了。
|
||||
這樣就直接把容器暴露到物理網路上了,多臺物理主機的容器也可以相網路了。需要註意的是,這樣就需要自己來保證容器的網路安全了。
|
||||
|
@ -7,8 +7,8 @@
|
||||
![企業應用結構](../_images/enterprise_usage.png)
|
||||
|
||||
|
||||
Docker 占用資源小,在一臺 E5 128 G 內存的服務器上部署 100 個容器都綽綽有余,可以單獨抽一個容器或者直接在宿主物理主機上部署 samba,利用 samba 的 home 分享方案將每個用戶的 home 目錄映射到開發中心和測試部門的 Windows 機器上。
|
||||
Docker 占用資源小,在一臺 E5 128 G 內存的服務器上部署 100 個容器都綽綽有余,可以單獨抽一個容器或者直接在宿主物理主機上部署 samba,利用 samba 的 home 分享方案將每個使用者的 home 目錄映射到開發中心和測試部門的 Windows 機器上。
|
||||
|
||||
針對某個項目組,由架構師搭建好一個標準的容器環境供項目組和測試部門使用,每個開發工程師可以擁有自己單獨的容器,通過 `docker run -v` 將用戶的 home 目錄映射到容器中。需要提交測試時,只需要將代碼移交給測試部門,然後分配一個容器使用 `-v` 加載測試部門的 home 目錄啟動即可。這樣,在公司內部的開發、測試基本就統一了,不會出現開發部門提交的代碼,測試部門部署不了的問題。
|
||||
針對某個項目組,由架構師搭建好一個標準的容器環境供項目組和測試部門使用,每個開發工程師可以擁有自己單獨的容器,透過 `docker run -v` 將使用者的 home 目錄映射到容器中。需要提交測試時,只需要將代碼移交給測試部門,然後分配一個容器使用 `-v` 加載測試部門的 home 目錄啟動即可。這樣,在公司內部的開發、測試基本就統一了,不會出現開發部門提交的代碼,測試部門部署不了的問題。
|
||||
|
||||
測試部門發布測試通過的報告後,架構師再一次檢測容器環境,就可以直接交由部署工程師將代碼和容器分別部署到生產環境中了。這種方式的部署橫向性能的擴展性也極好。
|
||||
測試部門發布測試透過的報告後,架構師再一次檢測容器環境,就可以直接交由部署工程師將代碼和容器分別部署到生產環境中了。這種方式的部署橫向性能的擴展性也極好。
|
||||
|
@ -4,7 +4,7 @@ Docker 容器在啟動的時候開啟單個程序,比如,一個 ssh 或者 a
|
||||
本小節將使用程序管理工具 supervisor 來管理容器中的多個程序。使用 Supervisor 可以更好的控制、管理、重啟我們希望執行的程序。在這裏我們演示一下如何同時使用 ssh 和 apache 服務。
|
||||
|
||||
### 配置
|
||||
首先創建一個 Dockerfile,內容和各部分的解釋如下。
|
||||
首先建立一個 Dockerfile,內容和各部分的解釋如下。
|
||||
```
|
||||
FROM ubuntu:13.04
|
||||
MAINTAINER examples@docker.com
|
||||
@ -21,11 +21,11 @@ RUN mkdir -p /var/run/sshd
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
```
|
||||
|
||||
這裏安裝 3 個軟件,還創建了 2 個 ssh 和 supervisor 服務正常執行所需要的目錄。
|
||||
這裏安裝 3 個軟件,還建立了 2 個 ssh 和 supervisor 服務正常執行所需要的目錄。
|
||||
```
|
||||
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
```
|
||||
添加 supervisord 的配置文件,並復制配置文件到對應目錄下面。
|
||||
新增 supervisord 的配置文件,並復制配置文件到對應目錄下面。
|
||||
|
||||
```
|
||||
EXPOSE 22 80
|
||||
@ -47,7 +47,7 @@ command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFO
|
||||
配置文件包含目錄和程序,第一段 supervsord 配置軟件本身,使用 nodaemon 參數來執行。第二段包含要控制的 2 個服務。每一段包含一個服務的目錄和啟動這個服務的命令。
|
||||
|
||||
### 使用方法
|
||||
創建鏡像。
|
||||
建立鏡像。
|
||||
```
|
||||
$ sudo docker build -t test/supervisord .
|
||||
```
|
||||
@ -60,6 +60,6 @@ $ sudo docker run -p 22 -p 80 -t -i test/supervisords
|
||||
2013-11-25 18:53:23,346 INFO spawned: 'sshd' with pid 6
|
||||
2013-11-25 18:53:23,349 INFO spawned: 'apache2' with pid 7
|
||||
```
|
||||
使用 `docker run` 來啟動我們創建的容器。使用多個 `-p` 來映射多個端口,這樣我們就能同時訪問 ssh 和 apache 服務了。
|
||||
使用 `docker run` 來啟動我們建立的容器。使用多個 `-p` 來映射多個端口,這樣我們就能同時訪問 ssh 和 apache 服務了。
|
||||
|
||||
可以使用這個方法創建一個只有 ssh 服務的基礎鏡像,之後創建鏡像可以使用這個鏡像為基礎來創建
|
||||
可以使用這個方法建立一個只有 ssh 服務的基礎鏡像,之後建立鏡像可以使用這個鏡像為基礎來建立
|
||||
|
@ -1,11 +1,11 @@
|
||||
## 創建 tomcat/weblogic 集群
|
||||
## 建立 tomcat/weblogic 集群
|
||||
### 安裝 tomcat 鏡像
|
||||
準備好需要的 jdk、tomcat 等軟件放到 home 目錄下面,啟動一個容器
|
||||
```
|
||||
docker run -t -i -v /home:/opt/data --name mk_tomcat ubuntu /bin/bash
|
||||
```
|
||||
這條命令掛載本地 home 目錄到容器的 /opt/data 目錄,容器內目錄若不存在,則會自動創建。接下來就是 tomcat 的基本配置,jdk 環境變量設置好之後,將 tomcat 程序放到 /opt/apache-tomcat 下面
|
||||
編輯 /etc/supervisor/conf.d/supervisor.conf 文件,添加 tomcat 項
|
||||
這條命令掛載本地 home 目錄到容器的 /opt/data 目錄,容器內目錄若不存在,則會自動建立。接下來就是 tomcat 的基本配置,jdk 環境變量設置好之後,將 tomcat 程序放到 /opt/apache-tomcat 下面
|
||||
編輯 /etc/supervisor/conf.d/supervisor.conf 文件,新增 tomcat 項
|
||||
```
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
@ -24,7 +24,7 @@ FROM mk_tomcat
|
||||
EXPOSE 22 8080
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
```
|
||||
根據 Dockerfile 創建鏡像。
|
||||
根據 Dockerfile 建立鏡像。
|
||||
```
|
||||
docker build tomcat tomcat
|
||||
```
|
||||
@ -56,7 +56,7 @@ CMD ["/usr/bin/supervisord"]
|
||||
|
||||
將本地磁盤映射到容器內部,它在主機和容器之間是實時變化的,所以我們更新程序、上傳代碼只需要更新物理主機的目錄就可以了
|
||||
|
||||
#### tomcat 和 weblogic 集群的實現
|
||||
#### tomcat 和 weblogic 集群的實做
|
||||
tomcat 只要開啟多個容器即可
|
||||
```
|
||||
docker run -d -v -p 204:22 -p 7003:8080 -v /home/data:/opt/data --name tm1 tomcat /usr/bin/supervisord
|
||||
@ -70,7 +70,7 @@ docker run -d -v -p 206:22 -p 7005:8080 -v /home/data:/opt/data --name tm3 tomca
|
||||
|
||||
缺點是:
|
||||
* Docker 配置復雜了
|
||||
* 沒辦法自動擴展集群的計算容量,如需添加節點,需要在 administrator 上先創建節點,然後再配置新的容器 supervisor 啟動腳本,然後再啟動容器
|
||||
* 沒辦法自動擴展集群的計算容量,如需新增節點,需要在 administrator 上先建立節點,然後再配置新的容器 supervisor 啟動腳本,然後再啟動容器
|
||||
另外種方法是將所有的程序都安裝在 adminiserver 上面,需要擴展的時候,啟動多個節點即可,它的優點和缺點和上一種方法恰恰相反。(建議使用這種方式來部署開發和測試環境)
|
||||
```
|
||||
docker run -d -v -p 204:22 -p 7001:7001 -v /home/data:/opt/data --name node1 weblogic /usr/bin/supervisord
|
||||
|
@ -3,4 +3,4 @@
|
||||
|
||||
簡單的說,容器是獨立執行的一個或一組應用,以及它們的執行態環境。換句話說,虛擬機可以理解為模擬執行的一整套作業系統(提供了執行態環境和其他系統環境)和跑在上面的應用。
|
||||
|
||||
本章將具體介紹如何來管理一個容器,包括創建、啟動和停止等。
|
||||
本章將具體介紹如何來管理一個容器,包括建立、啟動和停止等。
|
||||
|
@ -1,6 +1,6 @@
|
||||
##守護態執行
|
||||
|
||||
更多的時候,需要讓 Docker 容器在後臺以守護態(Daemonized)形式執行。此時,可以通過添加 `-d` 參數來實現。
|
||||
更多的時候,需要讓 Docker 容器在後臺以守護態(Daemonized)形式執行。此時,可以透過新增 `-d` 參數來實做。
|
||||
|
||||
例如下面的命令會在後臺執行容器。
|
||||
```
|
||||
@ -8,13 +8,13 @@ $ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; s
|
||||
1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147
|
||||
```
|
||||
|
||||
容器啟動後會返回一個唯一的 id,也可以通過 `docker ps` 命令來查看容器信息。
|
||||
容器啟動後會返回一個唯一的 id,也可以透過 `docker ps` 命令來查看容器信息。
|
||||
```
|
||||
$ sudo docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
1e5535038e28 ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage
|
||||
```
|
||||
要獲取容器的輸出信息,可以通過 `docker logs` 命令。
|
||||
要獲取容器的輸出信息,可以透過 `docker logs` 命令。
|
||||
```
|
||||
$ sudo docker logs insane_babbage
|
||||
hello world
|
||||
|
@ -33,11 +33,11 @@ $ cd util-linux-2.24
|
||||
$ ./configure --without-ncurses && make nsenter
|
||||
$ sudo cp nsenter /usr/local/bin
|
||||
```
|
||||
為了連接到容器,你還需要找到容器的第一個程序的 PID,可以通過下面的命令獲取。
|
||||
為了連接到容器,你還需要找到容器的第一個程序的 PID,可以透過下面的命令獲取。
|
||||
```
|
||||
PID=$(docker inspect --format "{{ .State.Pid }}" <container>)
|
||||
```
|
||||
通過這個 PID,就可以連接到這個容器:
|
||||
透過這個 PID,就可以連接到這個容器:
|
||||
```
|
||||
$ nsenter --target $PID --mount --uts --ipc --net --pid
|
||||
```
|
||||
|
@ -18,11 +18,11 @@ $ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
|
||||
```
|
||||
此外,也可以通過指定 URL 或者某個目錄來導入,例如
|
||||
此外,也可以透過指定 URL 或者某個目錄來導入,例如
|
||||
```
|
||||
$sudo docker import http://example.com/exampleimage.tgz example/imagerepo
|
||||
```
|
||||
|
||||
*註:用戶既可以使用 `docker load` 來導入映像檔儲存文件到本地映像檔庫,也可以使用 `docker import` 來導入一個容器快照到本地映像檔庫。這兩者的區別在於容器快照文件將丟棄所有的歷史記錄和原始數據信息(即僅保存容器當時的快照狀態),而映像檔儲存文件將保存完整記錄,檔案體積也跟著變大。此外,從容器快照文件導入時可以重新指定標簽等原始數據信息。
|
||||
*註:使用者既可以使用 `docker load` 來導入映像檔儲存文件到本地映像檔庫,也可以使用 `docker import` 來導入一個容器快照到本地映像檔庫。這兩者的區別在於容器快照文件將丟棄所有的歷史記錄和原始數據信息(即僅保存容器當時的快照狀態),而映像檔儲存文件將保存完整記錄,檔案體積也跟著變大。此外,從容器快照文件導入時可以重新指定標簽等原始數據信息。
|
||||
|
||||
|
||||
|
@ -5,5 +5,5 @@
|
||||
$sudo docker rm trusting_newton
|
||||
trusting_newton
|
||||
```
|
||||
如果要刪除一個執行中的容器,可以添加 `-f` 參數。Docker 會發送 `SIGKILL` 信號給容器。
|
||||
如果要刪除一個執行中的容器,可以新增 `-f` 參數。Docker 會發送 `SIGKILL` 信號給容器。
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
##啟動容器
|
||||
啟動容器有兩種方式,一種是將映像檔新建一個容器並啟動,另外一個是將終止狀態(stopped)的容器重新啟動。
|
||||
|
||||
因為 Docker 的容器實在太輕量級了,用戶可以隨時刪除和新創建容器。
|
||||
因為 Docker 的容器實在太輕量級了,使用者可以隨時刪除和新建立容器。
|
||||
|
||||
###新建並啟動
|
||||
所需要的命令主要為 `docker run`。
|
||||
@ -13,14 +13,14 @@ Hello world
|
||||
```
|
||||
這跟在本地直接執行 `/bin/echo 'hello world'` 相同, 幾乎感覺不出任何區別。
|
||||
|
||||
下面的命令則啟動一個 bash 終端,允許用戶進行交互。
|
||||
下面的命令則啟動一個 bash 終端,允許使用者進行交互。
|
||||
```
|
||||
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
|
||||
root@af8bae53bdd3:/#
|
||||
```
|
||||
其中,`-t` 選項讓Docker分配一個虛擬終端(pseudo-tty)並綁定到容器的標準輸入上, `-i` 則讓容器的標準輸入保持打開。
|
||||
|
||||
在交互模式下,用戶可以通過所創建的終端來輸入命令,例如
|
||||
在交互模式下,使用者可以透過所建立的終端來輸入命令,例如
|
||||
```
|
||||
root@af8bae53bdd3:/# pwd
|
||||
/
|
||||
@ -28,14 +28,14 @@ root@af8bae53bdd3:/# ls
|
||||
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
|
||||
```
|
||||
|
||||
當利用 `docker run` 來創建容器時,Docker 在後臺執行的標準操作包括:
|
||||
當利用 `docker run` 來建立容器時,Docker 在後臺執行的標準操作包括:
|
||||
|
||||
* 檢查本地是否存在指定的映像檔,不存在就從公有倉庫下載
|
||||
* 利用映像檔創建並啟動一個容器
|
||||
* 利用映像檔建立並啟動一個容器
|
||||
* 分配一個文件系統,並在唯讀的映像檔層外面掛載一層可讀寫層
|
||||
* 從宿主主機配置的網路橋接口中橋接一個虛擬埠到容器中去
|
||||
* 從地址堆中配置一個 ip 地址給容器
|
||||
* 執行用戶指定的應用程序
|
||||
* 執行使用者指定的應用程序
|
||||
* 執行完畢後容器被終止
|
||||
|
||||
###啟動已終止容器
|
||||
@ -48,4 +48,4 @@ root@ba267838cc1b:/# ps
|
||||
1 ? 00:00:00 bash
|
||||
11 ? 00:00:00 ps
|
||||
```
|
||||
可見,容器中僅執行了指定的 bash 應用。這種特點使得 Docker 對資源的利用率極高,是貨真價實的輕量級虛擬化。
|
||||
可見,容器中僅執行了指定的 bash 應用。這種特點使得 Docker 對資源的使用率極高,是貨真價實的輕量級虛擬化。
|
||||
|
@ -2,7 +2,7 @@
|
||||
可以使用 `docker stop` 來終止一個執行中的容器。
|
||||
|
||||
此外,當Docker容器中指定的應用終結時,容器也自動終止。
|
||||
例如對於上一章節中只啟動了一個終端機的容器,用戶通過 `exit` 命令或 `Ctrl+d` 來退出終端時,所創建的容器立刻終止。
|
||||
例如對於上一章節中只啟動了一個終端機的容器,使用者透過 `exit` 命令或 `Ctrl+d` 來退出終端時,所建立的容器立刻終止。
|
||||
|
||||
終止狀態的容器可以用 `docker ps -a` 命令看到。例如
|
||||
```
|
||||
@ -12,6 +12,6 @@ ba267838cc1b ubuntu:14.04 "/bin/bash" 30 minutes a
|
||||
98e5efa7d997 training/webapp:latest "python app.py" About an hour ago Exited (0) 34 minutes ago backstabbing_pike
|
||||
```
|
||||
|
||||
處於終止狀態的容器,可以通過 `docker start` 命令來重新啟動。
|
||||
處於終止狀態的容器,可以透過 `docker start` 命令來重新啟動。
|
||||
|
||||
此外,`docker restart` 命令會將一個執行中的容器終止,然後再重新啟動它。
|
||||
|
@ -1,9 +1,9 @@
|
||||
## 數據卷容器
|
||||
如果你有一些持續更新的數據需要在容器之間共享,最好創建數據卷容器。
|
||||
如果你有一些持續更新的數據需要在容器之間共享,最好建立數據卷容器。
|
||||
|
||||
數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。
|
||||
|
||||
首先,創建一個命名的數據卷容器 dbdata:
|
||||
首先,建立一個命名的數據卷容器 dbdata:
|
||||
```
|
||||
$ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
|
||||
```
|
||||
@ -20,4 +20,4 @@ $ sudo docker run -d --name db3 --volumes-from db1 training/postgres
|
||||
*註意:使用 `--volumes-from` 參數所掛載數據卷的容器自己並不需要保持在執行狀態。
|
||||
|
||||
如果刪除了掛載的容器(包括 dbdata、db1 和 db2),數據卷並不會被自動刪除。如果要刪除一個數據卷,必須在刪除最後一個還掛載著它的容器時使用 `docker rm -v` 命令來指定同時刪除關聯的容器。
|
||||
這可以讓用戶在容器之間升級和移動數據卷。具體的操作將在下一節中進行講解。
|
||||
這可以讓使用者在容器之間升級和移動數據卷。具體的操作將在下一節中進行講解。
|
||||
|
@ -2,7 +2,7 @@
|
||||
可以利用數據卷對其中的數據進行進行備份、恢復和遷移。
|
||||
|
||||
### 備份
|
||||
首先使用 `--volumes-from` 標記來創建一個加載 dbdata 容器卷的容器,並從本地主機掛載當前到容器的 /backup 目錄。命令如下:
|
||||
首先使用 `--volumes-from` 標記來建立一個加載 dbdata 容器卷的容器,並從本地主機掛載當前到容器的 /backup 目錄。命令如下:
|
||||
```
|
||||
$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
|
||||
```
|
||||
@ -10,11 +10,11 @@ $ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup
|
||||
|
||||
|
||||
### 恢復
|
||||
如果要恢復數據到一個容器,首先創建一個帶有數據卷的容器 dbdata2。
|
||||
如果要恢復數據到一個容器,首先建立一個帶有數據卷的容器 dbdata2。
|
||||
```
|
||||
$ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
|
||||
```
|
||||
然後創建另一個容器,掛載 dbdata2 的容器,並使用 `untar` 解壓備份文件到掛載的容器卷中。
|
||||
然後建立另一個容器,掛載 dbdata2 的容器,並使用 `untar` 解壓備份文件到掛載的容器卷中。
|
||||
```
|
||||
$ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf
|
||||
/backup/backup.tar
|
||||
|
@ -8,14 +8,14 @@
|
||||
*數據卷的使用,類似於 Linux 下對目錄或文件進行 mount。
|
||||
|
||||
|
||||
### 創建一個數據卷
|
||||
在用 `docker run` 命令的時候,使用 `-v` 標記來創建一個數據卷並掛載到容器裏。在一次 run 中多次使用可以掛載多個數據卷。
|
||||
### 建立一個數據卷
|
||||
在用 `docker run` 命令的時候,使用 `-v` 標記來建立一個數據卷並掛載到容器裏。在一次 run 中多次使用可以掛載多個數據卷。
|
||||
|
||||
下面創建一個 web 容器,並加載一個數據卷到容器的 `/webapp` 目錄。
|
||||
下面建立一個 web 容器,並加載一個數據卷到容器的 `/webapp` 目錄。
|
||||
```
|
||||
$ sudo docker run -d -P --name web -v /webapp training/webapp python app.py
|
||||
```
|
||||
*註意:也可以在 Dockerfile 中使用 `VOLUME` 來添加一個或者多個新的卷到由該鏡像創建的任意容器。
|
||||
*註意:也可以在 Dockerfile 中使用 `VOLUME` 來新增一個或者多個新的卷到由該鏡像建立的任意容器。
|
||||
|
||||
### 掛載一個主機目錄作為數據卷
|
||||
使用 `-v` 標記也可以指定掛載一個本地主機的目錄到容器中去。
|
||||
@ -23,11 +23,11 @@ $ sudo docker run -d -P --name web -v /webapp training/webapp python app.py
|
||||
$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
|
||||
```
|
||||
上面的命令加載主機的 `/src/webapp` 目錄到容器的 `/opt/webapp`
|
||||
目錄。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你創建它。
|
||||
目錄。這個功能在進行測試的時候十分方便,比如使用者可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你建立它。
|
||||
|
||||
*註意:Dockerfile 中不支持這種用法,這是因為 Dockerfile 是為了移植和分享用的。然而,不同作業系統的路徑格式不一樣,所以目前還不能支持。
|
||||
|
||||
Docker 掛載數據卷的默認權限是讀寫,用戶也可以通過 `:ro` 指定為唯讀。
|
||||
Docker 掛載數據卷的默認權限是讀寫,使用者也可以透過 `:ro` 指定為唯讀。
|
||||
```
|
||||
$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:ro
|
||||
training/webapp python app.py
|
||||
|
@ -1,7 +1,7 @@
|
||||
## 建立映像檔
|
||||
編輯完成 Dockerfile 之後,可以透過 `docker build` 命令建立映像檔。
|
||||
|
||||
基本的格式為 `docekr build [選項] 路徑`,該命令將讀取指定路徑下(包括子目錄)的 Dockerfile,並將該路徑下所有內容發送給 Docker 伺服端,由伺服端來創建鏡像。因此一般會建議放置 Dockerfile 的目錄為空目錄。也可以透過 `.dockerignore` 文件(每一行添加一條排除模式:exclusion patterns)來讓 Docker 忽略路徑下的目錄和文件。
|
||||
基本的格式為 `docekr build [選項] 路徑`,該命令將讀取指定路徑下(包括子目錄)的 Dockerfile,並將該路徑下所有內容發送給 Docker 伺服端,由伺服端來建立鏡像。因此一般會建議放置 Dockerfile 的目錄為空目錄。也可以透過 `.dockerignore` 文件(每一行新增一條排除模式:exclusion patterns)來讓 Docker 忽略路徑下的目錄和文件。
|
||||
|
||||
要指定鏡像的標籤資訊,可以透過 `-t` 選項,例如
|
||||
```
|
||||
|
@ -12,7 +12,7 @@
|
||||
### RUN
|
||||
格式為 `RUN <command>` 或 `RUN ["executable", "param1", "param2"]`。
|
||||
|
||||
前者將在 shell 終端中運行命令,即 `/bin/sh -c`;後者則使用 `exec` 執行。指定使用其它終端可以通過第二種方式實現,例如 `RUN ["/bin/bash", "-c", "echo hello"]`。
|
||||
前者將在 shell 終端中運行命令,即 `/bin/sh -c`;後者則使用 `exec` 執行。指定使用其它終端可以透過第二種方式實做,例如 `RUN ["/bin/bash", "-c", "echo hello"]`。
|
||||
|
||||
每條 `RUN` 指令將在當前映像檔基底上執行指定命令,並產生新的映像檔。當命令較長時可以使用 `\` 來換行。
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
### EXPOSE
|
||||
格式為 `EXPOSE <port> [<port>...]`。
|
||||
|
||||
設定 Docker 伺服器容器對外的埠號,供外界使用。在啟動容器時需要通過 -P,Docker 會自動分配一個埠號轉發到指定的埠號。
|
||||
設定 Docker 伺服器容器對外的埠號,供外界使用。在啟動容器時需要透過 -P,Docker 會自動分配一個埠號轉發到指定的埠號。
|
||||
|
||||
### ENV
|
||||
格式為 `ENV <key> <value>`。
|
||||
@ -76,7 +76,7 @@ ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
|
||||
|
||||
指定運行容器時的使用者名稱或 UID,後續的 `RUN` 也會使用指定使用者。
|
||||
|
||||
當服務不需要管理員權限時,可以通過該命令指定運行使用者。並且可以在之前建立所需要的使用者,例如:`RUN groupadd -r postgres && useradd -r -g postgres postgres`。要臨時獲取管理員權限可以使用 `gosu`,而不推薦 `sudo`。
|
||||
當服務不需要管理員權限時,可以透過該命令指定運行使用者。並且可以在之前建立所需要的使用者,例如:`RUN groupadd -r postgres && useradd -r -g postgres postgres`。要臨時獲取管理員權限可以使用 `gosu`,而不推薦 `sudo`。
|
||||
|
||||
### WORKDIR
|
||||
格式為 `WORKDIR /path/to/workdir`。
|
||||
@ -105,7 +105,7 @@ ONBUILD RUN /usr/local/bin/python-build --dir /app/src
|
||||
[...]
|
||||
```
|
||||
|
||||
如果基於 image-A 建立新的映像檔時,新的 Dockerfile 中使用 `FROM image-A`指定基底映像檔時,會自動執行 `ONBUILD` 指令內容,等於在後面添加了兩條指令。
|
||||
如果基於 image-A 建立新的映像檔時,新的 Dockerfile 中使用 `FROM image-A`指定基底映像檔時,會自動執行 `ONBUILD` 指令內容,等於在後面新增了兩條指令。
|
||||
```
|
||||
FROM image-A
|
||||
|
||||
|
@ -7,4 +7,4 @@ Docker 在執行容器前需要本地存在對應的鏡像,如果鏡像不存
|
||||
本章將介紹更多關於鏡像的內容,包括:
|
||||
* 從倉庫獲取鏡像;
|
||||
* 管理本地主機上的鏡像;
|
||||
* 介紹鏡像實現的基本原理。
|
||||
* 介紹鏡像實做的基本原理。
|
||||
|
@ -1,6 +1,6 @@
|
||||
##創建鏡像
|
||||
##建立鏡像
|
||||
|
||||
創建鏡像有很多方法,用戶可以從 Docker Hub 獲取已有鏡像並更新,也可以利用本地文件系統創建一個。
|
||||
建立鏡像有很多方法,使用者可以從 Docker Hub 獲取已有鏡像並更新,也可以利用本地文件系統建立一個。
|
||||
|
||||
### 修改已有鏡像
|
||||
先使用下載的鏡像啟動容器。
|
||||
@ -10,7 +10,7 @@ root@0b2616b0e5a8:/#
|
||||
```
|
||||
註意:記住容器的 ID,稍後還會用到。
|
||||
|
||||
在容器中添加 json 和 gem 兩個應用。
|
||||
在容器中新增 json 和 gem 兩個應用。
|
||||
```
|
||||
root@0b2616b0e5a8:/# gem install json
|
||||
```
|
||||
@ -19,10 +19,10 @@ root@0b2616b0e5a8:/# gem install json
|
||||
$ sudo docker commit -m "Added json gem" -a "Docker Newbee" 0b2616b0e5a8 ouruser/sinatra:v2
|
||||
4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c
|
||||
```
|
||||
其中,`-m` 來指定提交的說明信息,跟我們使用的版本控制工具一樣;`-a` 可以指定更新的用戶信息;之後是用來創建鏡像的容器的 ID;最後指定目標鏡像的倉庫名和 tag 信息。創建成功後會返回這個鏡像的 ID 信息。
|
||||
其中,`-m` 來指定提交的說明信息,跟我們使用的版本控制工具一樣;`-a` 可以指定更新的使用者信息;之後是用來建立鏡像的容器的 ID;最後指定目標鏡像的倉庫名和 tag 信息。建立成功後會返回這個鏡像的 ID 信息。
|
||||
|
||||
|
||||
使用 `docker images` 來查看新創建的鏡像。
|
||||
使用 `docker images` 來查看新建立的鏡像。
|
||||
```
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
@ -36,8 +36,8 @@ $ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
|
||||
root@78e82f680994:/#
|
||||
```
|
||||
|
||||
###利用 Dockerfile 來創建鏡像
|
||||
使用 `docker commit` 來擴展一個鏡像比較簡單,但是不方便在一個團隊中分享。我們可以使用 `docker build` 來創建一個新的鏡像。為此,首先需要創建一個 Dockerfile,包含一些如何創建鏡像的指令。
|
||||
###利用 Dockerfile 來建立鏡像
|
||||
使用 `docker commit` 來擴展一個鏡像比較簡單,但是不方便在一個團隊中分享。我們可以使用 `docker build` 來建立一個新的鏡像。為此,首先需要建立一個 Dockerfile,包含一些如何建立鏡像的指令。
|
||||
|
||||
新建一個目錄和一個 Dockerfile
|
||||
```
|
||||
@ -45,7 +45,7 @@ $ mkdir sinatra
|
||||
$ cd sinatra
|
||||
$ touch Dockerfile
|
||||
```
|
||||
Dockerfile 中每一條指令都創建鏡像的一層,例如:
|
||||
Dockerfile 中每一條指令都建立鏡像的一層,例如:
|
||||
```
|
||||
# This is a comment
|
||||
FROM ubuntu:14.04
|
||||
@ -58,7 +58,7 @@ Dockerfile 基本的語法是
|
||||
* 使用`#`來註釋
|
||||
* `FROM` 指令告訴 Docker 使用哪個鏡像作為基礎
|
||||
* 接著是維護者的信息
|
||||
* `RUN`開頭的指令會在創建中執行,比如安裝一個軟件包,在這裏使用 apt-get 來安裝了一些軟件
|
||||
* `RUN`開頭的指令會在建立中執行,比如安裝一個軟件包,在這裏使用 apt-get 來安裝了一些軟件
|
||||
|
||||
編寫完成 Dockerfile 後可以使用 `docker build` 來生成鏡像。
|
||||
|
||||
@ -96,11 +96,11 @@ Successfully installed sinatra-1.4.5
|
||||
Removing intermediate container 5e9d0065c1f7
|
||||
Successfully built 324104cde6ad
|
||||
```
|
||||
其中 `-t` 標記來添加 tag,指定新的鏡像的用戶信息。
|
||||
其中 `-t` 標記來新增 tag,指定新的鏡像的使用者信息。
|
||||
“.” 是 Dockerfile 所在的路徑(當前目錄),也可以替換為一個具體的 Dockerfile 的路徑。
|
||||
|
||||
可以看到 build 程序在執行操作。它要做的第一件事情就是上傳這個 Dockerfile 內容,因為所有的操作都要依據 Dockerfile 來進行。
|
||||
然後,Dockfile 中的指令被一條一條的執行。每一步都創建了一個新的容器,在容器中執行指令並提交修改(就跟之前介紹過的 `docker commit` 一樣)。當所有的指令都執行完畢之後,返回了最終的鏡像 id。所有的中間步驟所產生的容器都被刪除和清理了。
|
||||
然後,Dockfile 中的指令被一條一條的執行。每一步都建立了一個新的容器,在容器中執行指令並提交修改(就跟之前介紹過的 `docker commit` 一樣)。當所有的指令都執行完畢之後,返回了最終的鏡像 id。所有的中間步驟所產生的容器都被刪除和清理了。
|
||||
|
||||
*註意一個鏡像不能超過 127 層
|
||||
|
||||
@ -114,7 +114,7 @@ EXPOSE 80
|
||||
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
|
||||
```
|
||||
|
||||
現在可以利用新創建的鏡像來啟動一個容器。
|
||||
現在可以利用新建立的鏡像來啟動一個容器。
|
||||
```
|
||||
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
|
||||
root@8196968dac35:/#
|
||||
@ -132,7 +132,7 @@ ouruser/sinatra v2 5db5f8471261 11 hours ago 446.7 MB
|
||||
*註:更多用法,請參考 [Dockerfile](../dockerfile/README.md) 章節。
|
||||
|
||||
### 從本地文件系統導入
|
||||
要從本地文件系統導入一個鏡像,可以使用 openvz(容器虛擬化的先鋒技術)的模板來創建:
|
||||
要從本地文件系統導入一個鏡像,可以使用 openvz(容器虛擬化的先鋒技術)的模板來建立:
|
||||
openvz 的模板下載地址為 http://openvz.org/Download/templates/precreated。
|
||||
|
||||
比如,先下載了一個 ubuntu-14.04 的鏡像,之後使用以下命令導入:
|
||||
@ -147,7 +147,7 @@ ubuntu 14.04 05ac7c0b9383 17 seconds ago
|
||||
```
|
||||
|
||||
###上傳鏡像
|
||||
用戶可以通過 `docker push` 命令,把自己創建的鏡像上傳到倉庫中來共享。例如,用戶在 Docker Hub 上完成註冊後,可以推送自己的鏡像到倉庫中。
|
||||
使用者可以透過 `docker push` 命令,把自己建立的鏡像上傳到倉庫中來共享。例如,使用者在 Docker Hub 上完成註冊後,可以推送自己的鏡像到倉庫中。
|
||||
```
|
||||
$ sudo docker push ouruser/sinatra
|
||||
The push refers to a repository [ouruser/sinatra] (len: 1)
|
||||
|
@ -1,7 +1,7 @@
|
||||
## 鏡像的實現原理
|
||||
## 鏡像的實做原理
|
||||
|
||||
Docker 鏡像是怎麽實現增量的修改和維護的?
|
||||
Docker 鏡像是怎麽實做增量的修改和維護的?
|
||||
每個鏡像都由很多層次構成,Docker 使用 [Union FS](http://en.wikipedia.org/wiki/UnionFS) 將這些不同的層結合到一個鏡像中去。
|
||||
|
||||
通常 Union FS 有兩個用途, 一方面可以實現不借助 LVM、RAID 將多個 disk 掛到同一個目錄下,另一個更常用的就是將一個唯讀的分支和一個可寫的分支聯合在一起,Live CD 正是基於此方法可以允許在鏡像不變的基礎上允許用戶在其上進行一些寫操作。
|
||||
通常 Union FS 有兩個用途, 一方面可以實做不借助 LVM、RAID 將多個 disk 掛到同一個目錄下,另一個更常用的就是將一個唯讀的分支和一個可寫的分支聯合在一起,Live CD 正是基於此方法可以允許在鏡像不變的基礎上允許使用者在其上進行一些寫操作。
|
||||
Docker 在 AUFS 上構建的容器也是利用了類似的原理。
|
||||
|
@ -16,12 +16,12 @@ ubuntu trusty 99ec81b80c55 4 weeks ago 266 MB
|
||||
* 來自於哪個倉庫,比如 ubuntu
|
||||
* 鏡像的標記,比如 14.04
|
||||
* 它的 `ID` 號(唯一)
|
||||
* 創建時間
|
||||
* 建立時間
|
||||
* 鏡像大小
|
||||
|
||||
其中鏡像的 `ID` 唯一標識了鏡像,注意到 `ubuntu:14.04` 和 `ubuntu:trusty` 具有相同的鏡像 `ID`,說明它們實際上是同一鏡像。
|
||||
|
||||
`TAG` 信息用來標記來自同一個倉庫的不同鏡像。例如 `ubuntu` 倉庫中有多個鏡像,通過 `TAG` 信息來區分發行版本,例如 `10.04`、`12.04`、`12.10`、`13.04`、`14.04` 等。例如下面的命令指定使用鏡像 `ubuntu:14.04` 來啟動一個容器。
|
||||
`TAG` 信息用來標記來自同一個倉庫的不同鏡像。例如 `ubuntu` 倉庫中有多個鏡像,透過 `TAG` 信息來區分發行版本,例如 `10.04`、`12.04`、`12.10`、`13.04`、`14.04` 等。例如下面的命令指定使用鏡像 `ubuntu:14.04` 來啟動一個容器。
|
||||
```
|
||||
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
|
||||
```
|
||||
|
@ -32,7 +32,7 @@ ffdaafd1ca50: Download complete
|
||||
d047ae21eeaf: Download complete
|
||||
```
|
||||
|
||||
完成後,即可隨時使用該映像檔了,例如創建一個容器,讓其中執行 bash 應用。
|
||||
完成後,即可隨時使用該映像檔了,例如建立一個容器,讓其中執行 bash 應用。
|
||||
```
|
||||
$ sudo docker run -t -i ubuntu:12.04 /bin/bash
|
||||
root@fe7fc4bd8fc9:/#
|
||||
|
@ -1,6 +1,6 @@
|
||||
## Ubuntu 系列安裝 Docker
|
||||
|
||||
### 通過系統內建套件安裝
|
||||
### 透過系統內建套件安裝
|
||||
Ubuntu 14.04 版本套件庫中已經內建了 Docker 套件,可以直接安裝。
|
||||
```
|
||||
$ sudo apt-get update
|
||||
@ -9,10 +9,10 @@ $ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
|
||||
$ sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io
|
||||
```
|
||||
|
||||
如果使用作業系統內建套件安裝 Docker,目前安裝的版本是比較舊的 0.9.1。 要安裝更新的版本,可以通過更新 Docker 套件庫的方式進行安裝。
|
||||
如果使用作業系統內建套件安裝 Docker,目前安裝的版本是比較舊的 0.9.1。 要安裝更新的版本,可以透過更新 Docker 套件庫的方式進行安裝。
|
||||
|
||||
### 通過Docker 套件庫安裝最新版本
|
||||
要安裝最新的 Docker 版本,首先需要安裝 apt-transport-https 支持,之後通過添加套件庫來安裝。
|
||||
### 透過Docker 套件庫安裝最新版本
|
||||
要安裝最新的 Docker 版本,首先需要安裝 apt-transport-https 支持,之後透過新增套件庫來安裝。
|
||||
```
|
||||
$ sudo apt-get install apt-transport-https
|
||||
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
|
||||
|
@ -5,4 +5,4 @@
|
||||
|
||||
用它會帶來什麼樣的好處?
|
||||
|
||||
好吧,讓我們帶著問題開始這神奇之旅。
|
||||
好吧,讓我們帶著問題開始這神奇之旅。
|
||||
|
@ -1,15 +1,15 @@
|
||||
## 什麼是 Docker
|
||||
Docker 是一個開源項目,誕生於 2013 年初,最初是 dotCloud 公司內部的一個業餘項目。它基於 Google 公司推出的 Go 語言實現。
|
||||
Docker 是一個開源項目,誕生於 2013 年初,最初是 dotCloud 公司內部的一個業餘項目。它基於 Google 公司推出的 Go 語言實做。
|
||||
項目後來加入了 Linux 基金會,遵從了 Apache 2.0 協議,原始碼在 [GitHub](https://github.com/docker/docker) 上進行維護。
|
||||
|
||||
Docker 自開源後受到廣泛的關注和討論,以至於 dotCloud 公司後來都改名為 Docker Inc。Redhat 已經在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 產品中廣泛應用。
|
||||
|
||||
Docker 項目的目標是實現輕量級的作業系統虛擬化解決方案。
|
||||
Docker 項目的目標是實做輕量級的作業系統虛擬化解決方案。
|
||||
Docker 的基礎是 Linux 容器(LXC)等技術。
|
||||
|
||||
在 LXC 的基礎上 Docker 進行了進一步的封裝,讓用戶不需要去關心容器的管理,使得操作更為簡便。用戶操作 Docker 的容器就像操作一個快速輕量級的虛擬機一樣簡單。
|
||||
在 LXC 的基礎上 Docker 進行了進一步的封裝,讓使用者不需要去關心容器的管理,使得操作更為簡便。使用者操作 Docker 的容器就像操作一個快速輕量級的虛擬機一樣簡單。
|
||||
|
||||
下面的圖片比較了 Docker 和傳統虛擬化方式的不同之處,可見容器是在作業系統層面上實現虛擬化,直接使用本地主機的作業系統,而傳統方式則是在硬體層面實現。
|
||||
下面的圖片比較了 Docker 和傳統虛擬化方式的不同之處,可見容器是在作業系統層面上實做虛擬化,直接使用本地主機的作業系統,而傳統方式則是在硬體層面實做。
|
||||
|
||||
![傳統虛擬化](../_images/virtualization.png)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 為什麼要使用 Docker?
|
||||
作為一種新興的虛擬化方式,Docker 跟傳統的虛擬化方式相比具有眾多的優勢。
|
||||
|
||||
首先,Docker 容器的啟動可以在秒級實現,這相比傳統的虛擬機方式要快得多。
|
||||
其次,Docker 對系統資源的利用率很高,一台主機上可以同時執行數千個 Docker 容器。
|
||||
首先,Docker 容器的啟動可以在秒級實做,這相比傳統的虛擬機方式要快得多。
|
||||
其次,Docker 對系統資源的使用率很高,一台主機上可以同時執行數千個 Docker 容器。
|
||||
|
||||
容器除了執行其中應用外,基本不消耗額外的系統資源,使得應用的性能很高,同時系統資源消耗更少。傳統虛擬機方式執行 10 個不同的應用就要啟動 10 個虛擬機,而 Docker 只需要啟動 10 個隔離的應用即可。
|
||||
|
||||
@ -12,19 +12,19 @@
|
||||
對開發和維運(develop)人員來說,最希望的就是一次建立或配置,可以在任意地方正常執行。
|
||||
|
||||
開發者可以使用一個標準的映像檔來構建一套開發容器,開發完成之後,維運人員可以直接使用這個容器來部署程式碼。
|
||||
Docker 可以快速創建容器,快速迭代應用程序,並讓整個過程全程可見,使團隊中的其他成員更容易理解應用程序是如何創建和工作的。
|
||||
Docker 可以快速建立容器,快速迭代應用程序,並讓整個過程全程可見,使團隊中的其他成員更容易理解應用程序是如何建立和工作的。
|
||||
Docker 容器很輕很快!容器的啟動時間是秒級的,大量地節約開發、測試、部署的時間。
|
||||
|
||||
### 更高效的虛擬化
|
||||
Docker 容器的執行不需要額外的虛擬化支持,它是核心層級的虛擬化,因此可以實現更高的性能和效率。
|
||||
Docker 容器的執行不需要額外的虛擬化支持,它是核心層級的虛擬化,因此可以實做更高的性能和效率。
|
||||
|
||||
### 更輕鬆的遷移和擴展
|
||||
|
||||
Docker 容器幾乎可以在任意的平台上執行,包括實體機器、虛擬機、公有雲、私有雲、個人電腦、伺服器等。
|
||||
這種兼容性可以讓用戶把一個應用程序從一個平台直接遷移到另外一個。
|
||||
這種兼容性可以讓使用者把一個應用程序從一個平台直接遷移到另外一個。
|
||||
|
||||
### 更簡單的管理
|
||||
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分發和更新,從而實現自動化並且高效的管理。
|
||||
使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分發和更新,從而實做自動化並且高效的管理。
|
||||
|
||||
### 對比傳統虛擬機總結
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
# Docker 中的網路功能介紹
|
||||
Docker 允許通過外部訪問容器或容器互聯的方式來提供網路服務。
|
||||
Docker 允許透過外部訪問容器或容器互聯的方式來提供網路服務。
|
||||
|
@ -1,12 +1,12 @@
|
||||
## 容器互聯
|
||||
容器的連接(linking)系統是除了端口映射外,另一種跟容器中應用交互的方式。
|
||||
|
||||
該系統會在源和接收容器之間創建一個隧道,接收容器可以看到源容器指定的信息。
|
||||
該系統會在源和接收容器之間建立一個隧道,接收容器可以看到源容器指定的信息。
|
||||
|
||||
### 自定義容器命名
|
||||
連接系統依據容器的名稱來執行。因此,首先需要自定義一個好記的容器命名。
|
||||
|
||||
雖然當創建容器的時候,系統默認會分配一個名字。自定義命名容器有2個好處:
|
||||
雖然當建立容器的時候,系統默認會分配一個名字。自定義命名容器有2個好處:
|
||||
* 自定義的命名,比較好記,比如一個web應用容器我們可以給它起名叫web
|
||||
* 當要連接其他容器時候,可以作為一個有用的參考點,比如連接web容器到db容器
|
||||
|
||||
@ -26,22 +26,22 @@ aed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0
|
||||
$ sudo docker inspect -f "{{ .Name }}" aed84ee21bde
|
||||
/web
|
||||
```
|
||||
註意:容器的名稱是唯一的。如果已經命名了一個叫 web 的容器,當你要再次使用 web 這個名稱的時候,需要先用`docker rm` 來刪除之前創建的同名容器。
|
||||
註意:容器的名稱是唯一的。如果已經命名了一個叫 web 的容器,當你要再次使用 web 這個名稱的時候,需要先用`docker rm` 來刪除之前建立的同名容器。
|
||||
|
||||
在執行 `docker run` 的時候如果添加 `--rm` 標記,則容器在終止後會立刻刪除。註意,`--rm` 和 `-d` 參數不能同時使用。
|
||||
在執行 `docker run` 的時候如果新增 `--rm` 標記,則容器在終止後會立刻刪除。註意,`--rm` 和 `-d` 參數不能同時使用。
|
||||
|
||||
###容器互聯
|
||||
使用 `--link` 參數可以讓容器之間安全的進行交互。
|
||||
|
||||
下面先創建一個新的數據庫容器。
|
||||
下面先建立一個新的數據庫容器。
|
||||
```
|
||||
$ sudo docker run -d --name db training/postgres
|
||||
```
|
||||
刪除之前創建的 web 容器
|
||||
刪除之前建立的 web 容器
|
||||
```
|
||||
$ docker rm -f web
|
||||
```
|
||||
然後創建一個新的 web 容器,並將它連接到 db 容器
|
||||
然後建立一個新的 web 容器,並將它連接到 db 容器
|
||||
```
|
||||
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
|
||||
```
|
||||
@ -58,9 +58,9 @@ aed84ee21bde training/webapp:latest python app.py 16 hours ago
|
||||
```
|
||||
可以看到自定義命名的容器,db 和 web,db 容器的 names 列有 db 也有 web/db。這表示 web 容器鏈接到 db 容器,web 容器將被允許訪問 db 容器的信息。
|
||||
|
||||
Docker 在兩個互聯的容器之間創建了一個安全隧道,而且不用映射它們的端口到宿主主機上。在啟動 db 容器的時候並沒有使用 `-p` 和 `-P` 標記,從而避免了暴露數據庫端口到外部網路上。
|
||||
Docker 在兩個互聯的容器之間建立了一個安全隧道,而且不用映射它們的端口到宿主主機上。在啟動 db 容器的時候並沒有使用 `-p` 和 `-P` 標記,從而避免了暴露數據庫端口到外部網路上。
|
||||
|
||||
Docker 通過 2 種方式為容器公開連接信息:
|
||||
Docker 透過 2 種方式為容器公開連接信息:
|
||||
* 環境變量
|
||||
* 更新 `/etc/hosts` 文件
|
||||
|
||||
@ -78,7 +78,7 @@ DB_PORT_5000_TCP_ADDR=172.17.0.5
|
||||
```
|
||||
其中 DB_ 開頭的環境變量是供 web 容器連接 db 容器使用,前綴采用大寫的連接別名。
|
||||
|
||||
除了環境變量,Docker 還添加 host 信息到父容器的 `/etc/hosts` 的文件。下面是父容器 web 的 hosts 文件
|
||||
除了環境變量,Docker 還新增 host 信息到父容器的 `/etc/hosts` 的文件。下面是父容器 web 的 hosts 文件
|
||||
```
|
||||
$ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
|
||||
root@aed84ee21bde:/opt/webapp# cat /etc/hosts
|
||||
@ -99,4 +99,4 @@ PING db (172.17.0.5): 48 data bytes
|
||||
用 ping 來測試db容器,它會解析成 `172.17.0.5`。
|
||||
*註意:官方的 ubuntu 鏡像默認沒有安裝 ping,需要自行安裝。
|
||||
|
||||
用戶可以鏈接多個子容器到父容器,比如可以鏈接多個 web 到 db 容器上。
|
||||
使用者可以鏈接多個子容器到父容器,比如可以鏈接多個 web 到 db 容器上。
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 外部訪問容器
|
||||
容器中可以執行一些網路應用,要讓外部也可以訪問這些應用,可以通過 `-P` 或 `-p` 參數來指定端口映射。
|
||||
容器中可以執行一些網路應用,要讓外部也可以訪問這些應用,可以透過 `-P` 或 `-p` 參數來指定端口映射。
|
||||
|
||||
當使用 -P 標記時,Docker 會隨機映射一個 `49000~49900` 的端口到內部容器開放的網路端口。
|
||||
|
||||
@ -10,7 +10,7 @@ $ sudo docker ps -l
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse
|
||||
```
|
||||
同樣的,可以通過 `docker logs` 命令來查看應用的信息。
|
||||
同樣的,可以透過 `docker logs` 命令來查看應用的信息。
|
||||
```
|
||||
$ sudo docker logs -f nostalgic_morse
|
||||
* Running on http://0.0.0.0:5000/
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 倉庫配置文件
|
||||
Docker 的 Registry 利用配置文件提供了一些倉庫的模組(flavor),用戶可以直接使用它們來進行開發或生產部署。
|
||||
Docker 的 Registry 利用配置文件提供了一些倉庫的模組(flavor),使用者可以直接使用它們來進行開發或生產部署。
|
||||
|
||||
### 模組
|
||||
在 `config_sample.yml` 文件中,可以看到一些現成的模組段:
|
||||
@ -15,9 +15,9 @@ Docker 的 Registry 利用配置文件提供了一些倉庫的模組(flavor)
|
||||
* `glance-swift`:儲存數據到 OpenStack Glance 服務,Swift 為後備
|
||||
* `elliptics`:儲存數據到 Elliptics key/value 存儲
|
||||
|
||||
用戶也可以添加自定義的模版段。
|
||||
使用者也可以新增自定義的模版段。
|
||||
|
||||
預設情況下使用的模組是 `dev`,要使用某個模組作為預設值,可以添加 `SETTINGS_FLAVOR` 到環境變數中,例如
|
||||
預設情況下使用的模組是 `dev`,要使用某個模組作為預設值,可以新增 `SETTINGS_FLAVOR` 到環境變數中,例如
|
||||
```
|
||||
export SETTINGS_FLAVOR=dev
|
||||
```
|
||||
|
@ -1,12 +1,12 @@
|
||||
## Docker Hub
|
||||
目前 Docker 官方維護了一個公共倉庫 [Docker Hub](https://hub.docker.com/),其中已經包括了超過 15,000 的映像檔。大部分需求,都可以通過在 Docker Hub 中直接下載映像檔來實現。
|
||||
目前 Docker 官方維護了一個公共倉庫 [Docker Hub](https://hub.docker.com/),其中已經包括了超過 15,000 的映像檔。大部分需求,都可以透過在 Docker Hub 中直接下載映像檔來實做。
|
||||
|
||||
### 登錄
|
||||
可以通過執行 `docker login` 命令來輸入用戶名稱、密碼和電子信箱來完成註冊和登錄。
|
||||
註冊成功後,本地用戶目錄的 `.dockercfg` 中將保存用戶的認證訊息。
|
||||
可以透過執行 `docker login` 命令來輸入使用者名稱、密碼和電子信箱來完成註冊和登錄。
|
||||
註冊成功後,本地使用者目錄的 `.dockercfg` 中將保存使用者的認證訊息。
|
||||
|
||||
### 基本操作
|
||||
用戶無需登錄即可通過 `docker search` 命令來查詢官方倉庫中的映像檔,並利用 `docker pull` 命令來將它下載到本地。
|
||||
使用者無需登錄即可透過 `docker search` 命令來查詢官方倉庫中的映像檔,並利用 `docker pull` 命令來將它下載到本地。
|
||||
|
||||
例如以 centos 為關鍵字進行搜索:
|
||||
```
|
||||
@ -19,14 +19,14 @@ saltstack/centos-6-minimal
|
||||
tutum/centos-6.4 DEPRECATED. Use tutum/centos:6.4 instead. ... 5 [OK]
|
||||
...
|
||||
```
|
||||
可以看到顯示了很多包含關鍵字的映像檔,其中包括映像檔名字、描述、星級(表示該映像檔的受歡迎程度)、是否官方創建、是否自動創建。
|
||||
官方的映像檔說明是官方項目組創建和維護的,automated 資源允許用戶驗證映像檔的來源和內容。
|
||||
可以看到顯示了很多包含關鍵字的映像檔,其中包括映像檔名字、描述、星級(表示該映像檔的受歡迎程度)、是否官方建立、是否自動建立。
|
||||
官方的映像檔說明是官方項目組建立和維護的,automated 資源允許使用者驗證映像檔的來源和內容。
|
||||
|
||||
根據是否是官方提供,可將映像檔資源分為兩類。
|
||||
一種是類似 centos 這樣的基礎映像檔,被稱為基礎或根映像檔。這些基礎映像檔是由 Docker 公司創建、驗證、支持、提供。這樣的映像檔往往使用單個單詞作為名字。
|
||||
還有一種類型,比如 `tianon/centos` 映像檔,它是由 Docker 的用戶創建並維護的,往往帶有用戶名稱前綴。可以通過前綴 `user_name/` 來指定使用某個用戶提供的映像檔,比如 tianon 用戶。
|
||||
一種是類似 centos 這樣的基礎映像檔,被稱為基礎或根映像檔。這些基礎映像檔是由 Docker 公司建立、驗證、支持、提供。這樣的映像檔往往使用單個單詞作為名字。
|
||||
還有一種類型,比如 `tianon/centos` 映像檔,它是由 Docker 的使用者建立並維護的,往往帶有使用者名稱前綴。可以透過前綴 `user_name/` 來指定使用某個使用者提供的映像檔,比如 tianon 使用者。
|
||||
|
||||
另外,在查詢的時候通過 `-s N` 參數可以指定僅顯示評價為 `N` 星以上的映像檔。
|
||||
另外,在查詢的時候透過 `-s N` 參數可以指定僅顯示評價為 `N` 星以上的映像檔。
|
||||
|
||||
下載官方 centos 映像檔到本地。
|
||||
```
|
||||
@ -37,19 +37,19 @@ Pulling repository centos
|
||||
511136ea3c5a: Download complete
|
||||
7064731afe90: Download complete
|
||||
```
|
||||
用戶也可以在登錄後通過 `docker push` 命令來將映像檔推送到 Docker Hub。
|
||||
使用者也可以在登錄後透過 `docker push` 命令來將映像檔推送到 Docker Hub。
|
||||
|
||||
### 自動創建
|
||||
自動創建(Automated Builds)功能對於需要經常升級映像檔內程序來說,十分方便。
|
||||
有時候,用戶創建了映像檔,安裝了某個軟體,如果軟體發布新版本則需要手動更新映像檔。。
|
||||
### 自動建立
|
||||
自動建立(Automated Builds)功能對於需要經常升級映像檔內程序來說,十分方便。
|
||||
有時候,使用者建立了映像檔,安裝了某個軟體,如果軟體發布新版本則需要手動更新映像檔。。
|
||||
|
||||
而自動創建允許用戶通過 Docker Hub 指定跟蹤一個目標網站(目前支持 [GitHub](github.org) 或 [BitBucket](bitbucket.org))上的項目,一旦項目發生新的提交,則自動執行創建。
|
||||
而自動建立允許使用者透過 Docker Hub 指定跟蹤一個目標網站(目前支持 [GitHub](github.org) 或 [BitBucket](bitbucket.org))上的項目,一旦項目發生新的提交,則自動執行建立。
|
||||
|
||||
要配置自動創建,包括如下的步驟:
|
||||
* 創建並登陸 Docker Hub,以及目標網站;
|
||||
要配置自動建立,包括如下的步驟:
|
||||
* 建立並登陸 Docker Hub,以及目標網站;
|
||||
* 在目標網站中連接帳戶到 Docker Hub;
|
||||
* 在 Docker Hub 中 [配置一個自動創建](https://registry.hub.docker.com/builds/add/);
|
||||
* 在 Docker Hub 中 [配置一個自動建立](https://registry.hub.docker.com/builds/add/);
|
||||
* 選取一個目標網站中的項目(需要含 Dockerfile)和分支;
|
||||
* 指定 Dockerfile 的位置,並提交創建。
|
||||
* 指定 Dockerfile 的位置,並提交建立。
|
||||
|
||||
之後,可以 在Docker Hub 的 [自動創建頁面](https://registry.hub.docker.com/builds/) 中跟蹤每次創建的狀態。
|
||||
之後,可以 在Docker Hub 的 [自動建立頁面](https://registry.hub.docker.com/builds/) 中跟蹤每次建立的狀態。
|
||||
|
@ -1,18 +1,18 @@
|
||||
## 私有倉庫
|
||||
|
||||
有時候使用 Docker Hub 這樣的公共倉庫可能不方便,用戶可以創建一個本地倉庫供私人使用。
|
||||
有時候使用 Docker Hub 這樣的公共倉庫可能不方便,使用者可以建立一個本地倉庫供私人使用。
|
||||
|
||||
本節介紹如何使用本地倉庫。
|
||||
|
||||
`docker-registry` 是官方提供的工具,可以用於構建私有的映像檔倉庫。
|
||||
### 安裝執行 docker-registry
|
||||
#### 容器執行
|
||||
在安裝了 Docker 後,可以通過獲取官方 registry 映像檔來執行。
|
||||
在安裝了 Docker 後,可以透過獲取官方 registry 映像檔來執行。
|
||||
```
|
||||
$ sudo docker run -d -p 5000:5000 registry
|
||||
```
|
||||
這將使用官方的 registry 映像檔來啟動本地的私有倉庫。
|
||||
用戶可以通過指定參數來配置私有倉庫位置,例如配置映像檔存儲到 Amazon S3 服務。
|
||||
使用者可以透過指定參數來配置私有倉庫位置,例如配置映像檔存儲到 Amazon S3 服務。
|
||||
```
|
||||
$ sudo docker run \
|
||||
-e SETTINGS_FLAVOR=s3 \
|
||||
@ -28,14 +28,14 @@ $ sudo docker run \
|
||||
```
|
||||
$ sudo docker run -d -p 5000:5000 -v /home/user/registry-conf:/registry-conf -e DOCKER_REGISTRY_CONFIG=/registry-conf/config.yml registry
|
||||
```
|
||||
預設情況下,倉庫會被創建在容器的 `/tmp/registry` 下。可以通過 `-v` 參數來將映像檔文件存放在本地的指定路徑。
|
||||
預設情況下,倉庫會被建立在容器的 `/tmp/registry` 下。可以透過 `-v` 參數來將映像檔文件存放在本地的指定路徑。
|
||||
例如下面的例子將上傳的映像檔放到 `/opt/data/registry` 目錄。
|
||||
```
|
||||
$ sudo docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry
|
||||
```
|
||||
|
||||
#### 本地安裝
|
||||
對於 Ubuntu 或 CentOS 等發行版,可以直接通過套件庫安裝。
|
||||
對於 Ubuntu 或 CentOS 等發行版,可以直接透過套件庫安裝。
|
||||
* Ubuntu
|
||||
```
|
||||
$ sudo apt-get install -y build-essential python-dev libevent-dev python-pip liblzma-dev
|
||||
@ -71,7 +71,7 @@ $ sudo gunicorn --access-logfile - --error-logfile - -k gevent -b 0.0.0.0:5000 -
|
||||
*註:`config/config_sample.yml` 文件是範例配置文件。
|
||||
|
||||
###在私有倉庫上傳、下載、搜索映像檔
|
||||
創建好私有倉庫之後,就可以使用 `docker tag` 來標記一個映像檔,然後推送它到倉庫,別的機器上就可以下載下來了。例如私有倉庫地址為 `192.168.7.26:5000`。
|
||||
建立好私有倉庫之後,就可以使用 `docker tag` 來標記一個映像檔,然後推送它到倉庫,別的機器上就可以下載下來了。例如私有倉庫地址為 `192.168.7.26:5000`。
|
||||
|
||||
先在本機查看已有的映像檔。
|
||||
```
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 控制組
|
||||
控制組是 Linux 容器機制的另外一個關鍵組件,負責實現資源的審計和限制。
|
||||
控制組是 Linux 容器機制的另外一個關鍵組件,負責實做資源的審計和限制。
|
||||
|
||||
它提供了很多有用的特性;以及確保各個容器可以公平地分享主機的內存、CPU、磁盤 IO 等資源;當然,更重要的是,控制組確保了當容器內的資源使用產生壓力時不會連累主機系統。
|
||||
|
||||
盡管控制組不負責隔離容器之間相互訪問、處理數據和程序,它在防止拒絕服務(DDOS)攻擊方面是必不可少的。尤其是在多用戶的平臺(比如公有或私有的 PaaS)上,控制組十分重要。例如,當某些應用程序表現異常的時候,可以保證一致地正常執行和性能。
|
||||
盡管控制組不負責隔離容器之間相互訪問、處理數據和程序,它在防止拒絕服務(DDOS)攻擊方面是必不可少的。尤其是在多使用者的平臺(比如公有或私有的 PaaS)上,控制組十分重要。例如,當某些應用程序表現異常的時候,可以保證一致地正常執行和性能。
|
||||
|
||||
控制組機制始於 2006 年,內核從 2.6.24 版本開始被引入。
|
||||
|
@ -1,18 +1,18 @@
|
||||
## Docker服務端的防護
|
||||
執行一個容器或應用程序的核心是通過 Docker 服務端。Docker 服務的執行目前需要 root 權限,因此其安全性十分關鍵。
|
||||
執行一個容器或應用程序的核心是透過 Docker 服務端。Docker 服務的執行目前需要 root 權限,因此其安全性十分關鍵。
|
||||
|
||||
首先,確保只有可信的用戶才可以訪問 Docker 服務。Docker 允許用戶在主機和容器間共享文件夾,同時不需要限制容器的訪問權限,這就容易讓容器突破資源限制。例如,惡意用戶啟動容器的時候將主機的根目錄`/`映射到容器的 `/host` 目錄中,那麽容器理論上就可以對主機的文件系統進行任意修改了。這聽起來很瘋狂?但是事實上幾乎所有虛擬化系統都允許類似的資源共享,而沒法禁止用戶共享主機根文件系統到虛擬機系統。
|
||||
首先,確保只有可信的使用者才可以訪問 Docker 服務。Docker 允許使用者在主機和容器間共享文件夾,同時不需要限制容器的訪問權限,這就容易讓容器突破資源限制。例如,惡意使用者啟動容器的時候將主機的根目錄`/`映射到容器的 `/host` 目錄中,那麽容器理論上就可以對主機的文件系統進行任意修改了。這聽起來很瘋狂?但是事實上幾乎所有虛擬化系統都允許類似的資源共享,而沒法禁止使用者共享主機根文件系統到虛擬機系統。
|
||||
|
||||
這將會造成很嚴重的安全後果。因此,當提供容器創建服務時(例如通過一個 web 服務器),要更加註意進行參數的安全檢查,防止惡意的用戶用特定參數來創建一些破壞性的容器
|
||||
這將會造成很嚴重的安全後果。因此,當提供容器建立服務時(例如透過一個 web 服務器),要更加註意進行參數的安全檢查,防止惡意的使用者用特定參數來建立一些破壞性的容器
|
||||
|
||||
為了加強對服務端的保護,Docker 的 REST API(客戶端用來跟服務端通信)在 0.5.2 之後使用本地的 Unix 套接字機制替代了原先綁定在 127.0.0.1 上的 TCP 套接字,因為後者容易遭受跨站腳本攻擊。現在用戶使用 Unix 權限檢查來加強套接字的訪問安全。
|
||||
為了加強對服務端的保護,Docker 的 REST API(客戶端用來跟服務端通信)在 0.5.2 之後使用本地的 Unix 套接字機制替代了原先綁定在 127.0.0.1 上的 TCP 套接字,因為後者容易遭受跨站腳本攻擊。現在使用者使用 Unix 權限檢查來加強套接字的訪問安全。
|
||||
|
||||
用戶仍可以利用 HTTP 提供 REST API 訪問。建議使用安全機制,確保只有可信的網路或 VPN,或證書保護機制(例如受保護的 stunnel 和 ssl 認證)下的訪問可以進行。此外,還可以使用 HTTPS 和證書來加強保護。
|
||||
使用者仍可以利用 HTTP 提供 REST API 訪問。建議使用安全機制,確保只有可信的網路或 VPN,或證書保護機制(例如受保護的 stunnel 和 ssl 認證)下的訪問可以進行。此外,還可以使用 HTTPS 和證書來加強保護。
|
||||
|
||||
最近改進的 Linux 名字空間機制將可以實現使用非 root 用戶來執行全功能的容器。這將從根本上解決了容器和主機之間共享文件系統而引起的安全問題。
|
||||
最近改進的 Linux 名字空間機制將可以實做使用非 root 使用者來執行全功能的容器。這將從根本上解決了容器和主機之間共享文件系統而引起的安全問題。
|
||||
|
||||
終極目標是改進 2 個重要的安全特性:
|
||||
* 將容器的 root 用戶映射到本地主機上的非 root 用戶,減輕容器和主機之間因權限提升而引起的安全問題;
|
||||
* 將容器的 root 使用者映射到本地主機上的非 root 使用者,減輕容器和主機之間因權限提升而引起的安全問題;
|
||||
* 允許 Docker 服務端在非 root 權限下執行,利用安全可靠的子程序來代理執行需要特權權限的操作。這些子程序將只允許在限定範圍內進行操作,例如僅僅負責虛擬網路設定或文件系統管理、配置操作等。
|
||||
|
||||
最後,建議采用專用的服務器來執行 Docker 和相關的管理服務(例如管理服務比如 ssh 監控和程序監控、管理工具 nrpe、collectd 等)。其它的業務服務都放到容器中去執行。
|
||||
|
@ -9,7 +9,7 @@ Linux 內核自 2.2 版本起就支持能力機制,它將權限劃分為更加
|
||||
|
||||
使用能力機制對加強 Docker 容器的安全有很多好處。通常,在服務器上會執行一堆需要特權權限的程序,包括有 ssh、cron、syslogd、硬件管理工具模塊(例如負載模塊)、網路配置工具等等。容器跟這些程序是不同的,因為幾乎所有的特權程序都由容器以外的支持系統來進行管理。
|
||||
* ssh 訪問被主機上ssh服務來管理;
|
||||
* cron 通常應該作為用戶程序執行,權限交給使用它服務的應用來處理;
|
||||
* cron 通常應該作為使用者程序執行,權限交給使用它服務的應用來處理;
|
||||
* 日誌系統可由 Docker 或第三方服務管理;
|
||||
* 硬件管理無關緊要,容器中也就無需執行 udevd 以及類似服務;
|
||||
* 網路管理也都在主機上設置,除非特殊需求,容器不需要對網路進行配置。
|
||||
@ -17,10 +17,10 @@ Linux 內核自 2.2 版本起就支持能力機制,它將權限劃分為更加
|
||||
從上面的例子可以看出,大部分情況下,容器並不需要“真正的” root 權限,容器只需要少數的能力即可。為了加強安全,容器可以禁用一些沒必要的權限。
|
||||
* 完全禁止任何 mount 操作;
|
||||
* 禁止直接訪問本地主機的套接字;
|
||||
* 禁止訪問一些文件系統的操作,比如創建新的設備、修改文件屬性等;
|
||||
* 禁止訪問一些文件系統的操作,比如建立新的設備、修改文件屬性等;
|
||||
* 禁止模塊加載。
|
||||
|
||||
這樣,就算攻擊者在容器中取得了 root 權限,也不能獲得本地主機的較高權限,能進行的破壞也有限。
|
||||
|
||||
默認情況下,Docker采用 [白名單](https://github.com/docker/docker/blob/master/daemon/execdriver/native/template/default_template.go) 機制,禁用 [必需功能](https://github.com/docker/docker/blob/master/daemon/execdriver/native/template/default_template.go) 之外的其它權限。
|
||||
當然,用戶也可以根據自身需求來為 Docker 容器啟用額外的權限。
|
||||
當然,使用者也可以根據自身需求來為 Docker 容器啟用額外的權限。
|
||||
|
@ -1,15 +1,15 @@
|
||||
## 內核名字空間
|
||||
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。當用 `docker run` 啟動一個容器時,在後臺 Docker 為容器創建了一個獨立的名字空間和控制組集合。
|
||||
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。當用 `docker run` 啟動一個容器時,在後臺 Docker 為容器建立了一個獨立的名字空間和控制組集合。
|
||||
|
||||
名字空間提供了最基礎也是最直接的隔離,在容器中執行的程序不會被執行在主機上的程序和其它容器發現和作用。
|
||||
|
||||
每個容器都有自己獨有的網路棧,意味著它們不能訪問其他容器的 sockets 或接口。不過,如果主機系統上做了相應的設置,容器可以像跟主機交互一樣的和其他容器交互。當指定公共端口或使用 links 來連接 2 個容器時,容器就可以相互通信了(可以根據配置來限制通信的策略)。
|
||||
|
||||
從網路架構的角度來看,所有的容器通過本地主機的網橋接口相互通信,就像物理機器通過物理交換機通信一樣。
|
||||
從網路架構的角度來看,所有的容器透過本地主機的網橋接口相互通信,就像物理機器透過物理交換機通信一樣。
|
||||
|
||||
那麽,內核中實現名字空間和私有網路的代碼是否足夠成熟?
|
||||
那麽,內核中實做名字空間和私有網路的代碼是否足夠成熟?
|
||||
|
||||
內核名字空間從 2.6.15 版本(2008 年 7 月發布)之後被引入,數年間,這些機制的可靠性在諸多大型生產系統中被實踐驗證。
|
||||
|
||||
實際上,名字空間的想法和設計提出的時間要更早,最初是為了在內核中引入一種機制來實現 [OpenVZ](http://en.wikipedia.org/wiki/OpenVZ) 的特性。
|
||||
而 OpenVZ 項目早在 2005 年就發布了,其設計和實現都已經十分成熟。
|
||||
實際上,名字空間的想法和設計提出的時間要更早,最初是為了在內核中引入一種機制來實做 [OpenVZ](http://en.wikipedia.org/wiki/OpenVZ) 的特性。
|
||||
而 OpenVZ 項目早在 2005 年就發布了,其設計和實做都已經十分成熟。
|
||||
|
@ -1,9 +1,9 @@
|
||||
## 其它安全特性
|
||||
除了能力機制之外,還可以利用一些現有的安全機制來增強使用 Docker 的安全性,例如 TOMOYO, AppArmor, SELinux, GRSEC 等。
|
||||
|
||||
Docker 當前默認只啟用了能力機制。用戶可以采用多種方案來加強 Docker 主機的安全,例如:
|
||||
* 在內核中啟用 GRSEC 和 PAX,這將增加很多編譯和執行時的安全檢查;通過地址隨機化避免惡意探測等。並且,啟用該特性不需要 Docker 進行任何配置。
|
||||
Docker 當前默認只啟用了能力機制。使用者可以采用多種方案來加強 Docker 主機的安全,例如:
|
||||
* 在內核中啟用 GRSEC 和 PAX,這將增加很多編譯和執行時的安全檢查;透過地址隨機化避免惡意探測等。並且,啟用該特性不需要 Docker 進行任何配置。
|
||||
* 使用一些有增強安全特性的容器模板,比如帶 AppArmor 的模板和 Redhat 帶 SELinux 策略的模板。這些模板提供了額外的安全特性。
|
||||
* 用戶可以自定義訪問控制機制來定制安全策略。
|
||||
* 使用者可以自定義訪問控制機制來定制安全策略。
|
||||
|
||||
跟其它添加到 Docker 容器的第三方工具一樣(比如網路拓撲和文件系統共享),有很多類似的機制,在不改變 Docker 內核情況下就可以加固現有的容器。
|
||||
跟其它新增到 Docker 容器的第三方工具一樣(比如網路拓撲和文件系統共享),有很多類似的機制,在不改變 Docker 內核情況下就可以加固現有的容器。
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 總結
|
||||
總體來看,Docker 容器還是十分安全的,特別是在容器內不使用 root 權限來執行程序的話。
|
||||
|
||||
另外,用戶可以使用現有工具,比如 Apparmor, SELinux, GRSEC 來增強安全性;甚至自己在內核中實現更復雜的安全機制。
|
||||
另外,使用者可以使用現有工具,比如 Apparmor, SELinux, GRSEC 來增強安全性;甚至自己在內核中實做更復雜的安全機制。
|
||||
|
@ -1,13 +1,13 @@
|
||||
# 底層實現
|
||||
# 底層實做
|
||||
|
||||
Docker 底層的核心技術包括 Linux 上的名字空間(Namespaces)、控制組(Control groups)、Union 文件系統(Union file systems)和容器格式(Container format)。
|
||||
|
||||
我們知道,傳統的虛擬機通過在宿主主機中執行 hypervisor 來模擬一整套完整的硬件環境提供給虛擬機的作業系統。虛擬機系統看到的環境是可限制的,也是彼此隔離的。
|
||||
這種直接的做法實現了對資源最完整的封裝,但很多時候往往意味著系統資源的浪費。
|
||||
我們知道,傳統的虛擬機透過在宿主主機中執行 hypervisor 來模擬一整套完整的硬件環境提供給虛擬機的作業系統。虛擬機系統看到的環境是可限制的,也是彼此隔離的。
|
||||
這種直接的做法實做了對資源最完整的封裝,但很多時候往往意味著系統資源的浪費。
|
||||
例如,以宿主機和虛擬機系統都為 Linux 系統為例,虛擬機中執行的應用其實可以利用宿主機系統中的執行環境。
|
||||
|
||||
我們知道,在作業系統中,包括內核、文件系統、網路、PID、UID、IPC、內存、硬盤、CPU 等等,所有的資源都是應用程序直接共享的。
|
||||
要想實現虛擬化,除了要實現對內存、CPU、網路IO、硬盤IO、存儲空間等的限制外,還要實現文件系統、網路、PID、UID、IPC等等的相互隔離。
|
||||
前者相對容易實現一些,後者則需要宿主機系統的深入支持。
|
||||
要想實做虛擬化,除了要實做對內存、CPU、網路IO、硬盤IO、存儲空間等的限制外,還要實做文件系統、網路、PID、UID、IPC等等的相互隔離。
|
||||
前者相對容易實做一些,後者則需要宿主機系統的深入支持。
|
||||
|
||||
隨著 Linux 系統對於名字空間功能的完善實現,程序員已經可以實現上面的所有需求,讓某些程序在彼此隔離的名字空間中執行。大家雖然都共用一個內核和某些執行時環境(例如一些系統命令和系統庫),但是彼此卻看不到,都以為系統中只有自己的存在。這種機制就是容器(Container),利用名字空間來做權限的隔離控制,利用 cgroups 來做資源分配。
|
||||
隨著 Linux 系統對於名字空間功能的完善實做,程序員已經可以實做上面的所有需求,讓某些程序在彼此隔離的名字空間中執行。大家雖然都共用一個內核和某些執行時環境(例如一些系統命令和系統庫),但是彼此卻看不到,都以為系統中只有自己的存在。這種機制就是容器(Container),利用名字空間來做權限的隔離控制,利用 cgroups 來做資源分配。
|
||||
|
@ -1,10 +1,10 @@
|
||||
## 基本架構
|
||||
Docker 采用了 C/S架構,包括客戶端和服務端。
|
||||
Docker daemon 作為服務端接受來自客戶的請求,並處理這些請求(創建、執行、分發容器)。
|
||||
客戶端和服務端既可以執行在一個機器上,也可通過 socket 或者 RESTful API 來進行通信。
|
||||
Docker daemon 作為服務端接受來自客戶的請求,並處理這些請求(建立、執行、分發容器)。
|
||||
客戶端和服務端既可以執行在一個機器上,也可透過 socket 或者 RESTful API 來進行通信。
|
||||
|
||||
![Docker 基本架構](../_images/docker_arch.png)
|
||||
|
||||
|
||||
Docker daemon 一般在宿主主機後臺執行,等待接收來自客戶端的消息。
|
||||
Docker 客戶端則為用戶提供一系列可執行命令,用戶用這些命令實現跟 Docker daemon 交互。
|
||||
Docker 客戶端則為使用者提供一系列可執行命令,使用者用這些命令實做跟 Docker daemon 交互。
|
||||
|
@ -2,10 +2,10 @@
|
||||
名字空間是 Linux 內核一個強大的特性。每個容器都有自己單獨的名字空間,執行在其中的應用都像是在獨立的作業系統中執行一樣。名字空間保證了容器之間彼此互不影響。
|
||||
|
||||
### pid 名字空間
|
||||
不同用戶的程序就是通過 pid 名字空間隔離開的,且不同名字空間中可以有相同 pid。所有的 LXC 程序在 Docker 中的父程序為Docker程序,每個 LXC 程序具有不同的名字空間。同時由於允許嵌套,因此可以很方便的實現嵌套的 Docker 容器。
|
||||
不同使用者的程序就是透過 pid 名字空間隔離開的,且不同名字空間中可以有相同 pid。所有的 LXC 程序在 Docker 中的父程序為Docker程序,每個 LXC 程序具有不同的名字空間。同時由於允許嵌套,因此可以很方便的實做嵌套的 Docker 容器。
|
||||
|
||||
### net 名字空間
|
||||
有了 pid 名字空間, 每個名字空間中的 pid 能夠相互隔離,但是網路端口還是共享 host 的端口。網路隔離是通過 net 名字空間實現的, 每個 net 名字空間有獨立的 網路設備, IP 地址, 路由表, /proc/net 目錄。這樣每個容器的網路就能隔離開來。Docker 默認采用 veth 的方式,將容器中的虛擬網卡同 host 上的一 個Docker 網橋 docker0 連接在一起。
|
||||
有了 pid 名字空間, 每個名字空間中的 pid 能夠相互隔離,但是網路端口還是共享 host 的端口。網路隔離是透過 net 名字空間實做的, 每個 net 名字空間有獨立的 網路設備, IP 地址, 路由表, /proc/net 目錄。這樣每個容器的網路就能隔離開來。Docker 默認采用 veth 的方式,將容器中的虛擬網卡同 host 上的一 個Docker 網橋 docker0 連接在一起。
|
||||
|
||||
### ipc 名字空間
|
||||
容器中程序交互還是采用了 Linux 常見的程序間交互方法(interprocess communication - IPC), 包括信號量、消息隊列和共享內存等。然而同 VM 不同的是,容器的程序間交互實際上還是 host 上具有相同 pid 名字空間中的程序間交互,因此需要在 IPC 資源申請時加入名字空間信息,每個 IPC 資源有一個唯一的 32 位 id。
|
||||
@ -17,6 +17,6 @@
|
||||
UTS("UNIX Time-sharing System") 名字空間允許每個容器擁有獨立的 hostname 和 domain name, 使其在網路上可以被視作一個獨立的節點而非 主機上的一個程序。
|
||||
|
||||
### user 名字空間
|
||||
每個容器可以有不同的用戶和組 id, 也就是說可以在容器內用容器內部的用戶執行程序而非主機上的用戶。
|
||||
每個容器可以有不同的使用者和組 id, 也就是說可以在容器內用容器內部的使用者執行程序而非主機上的使用者。
|
||||
|
||||
*註:關於 Linux 上的名字空間,[這篇文章](http://blog.scottlowe.org/2013/09/04/introducing-linux-network-namespaces/) 介紹的很好。
|
||||
|
@ -1,39 +1,39 @@
|
||||
## Docker 網路實現
|
||||
## Docker 網路實做
|
||||
|
||||
Docker 的網路實現其實就是利用了 Linux 上的網路名字空間和虛擬網路設備(特別是 veth pair)。建議先熟悉了解這兩部分的基本概念再閱讀本章。
|
||||
Docker 的網路實做其實就是利用了 Linux 上的網路名字空間和虛擬網路設備(特別是 veth pair)。建議先熟悉了解這兩部分的基本概念再閱讀本章。
|
||||
|
||||
### 基本原理
|
||||
首先,要實現網路通信,機器需要至少一個網路接口(物理接口或虛擬接口)來收發數據包;此外,如果不同子網之間要進行通信,需要路由機制。
|
||||
首先,要實做網路通信,機器需要至少一個網路接口(物理接口或虛擬接口)來收發數據包;此外,如果不同子網之間要進行通信,需要路由機制。
|
||||
|
||||
Docker 中的網路接口默認都是虛擬的接口。虛擬接口的優勢之一是轉發效率較高。
|
||||
Linux 通過在內核中進行數據復制來實現虛擬接口之間的數據轉發,發送接口的發送緩存中的數據包被直接復制到接收接口的接收緩存中。對於本地系統和容器內系統看來就像是一個正常的以太網卡,只是它不需要真正同外部網路設備通信,速度要快很多。
|
||||
Linux 透過在內核中進行數據復制來實做虛擬接口之間的數據轉發,發送接口的發送緩存中的數據包被直接復制到接收接口的接收緩存中。對於本地系統和容器內系統看來就像是一個正常的以太網卡,只是它不需要真正同外部網路設備通信,速度要快很多。
|
||||
|
||||
Docker 容器網路就利用了這項技術。它在本地主機和容器內分別創建一個虛擬接口,並讓它們彼此連通(這樣的一對接口叫做 `veth pair`)。
|
||||
Docker 容器網路就利用了這項技術。它在本地主機和容器內分別建立一個虛擬接口,並讓它們彼此連通(這樣的一對接口叫做 `veth pair`)。
|
||||
|
||||
### 創建網路參數
|
||||
Docker 創建一個容器的時候,會執行如下操作:
|
||||
* 創建一對虛擬接口,分別放到本地主機和新容器中;
|
||||
### 建立網路參數
|
||||
Docker 建立一個容器的時候,會執行如下操作:
|
||||
* 建立一對虛擬接口,分別放到本地主機和新容器中;
|
||||
* 本地主機一端橋接到默認的 docker0 或指定網橋上,並具有一個唯一的名字,如 veth65f9;
|
||||
* 容器一端放到新容器中,並修改名字作為 eth0,這個接口只在容器的名字空間可見;
|
||||
* 從網橋可用地址段中獲取一個空閑地址分配給容器的 eth0,並配置默認路由到橋接網卡 veth65f9。
|
||||
|
||||
完成這些之後,容器就可以使用 eth0 虛擬網卡來連接其他容器和其他網路。
|
||||
|
||||
可以在 `docker run` 的時候通過 `--net` 參數來指定容器的網路配置,有4個可選值:
|
||||
可以在 `docker run` 的時候透過 `--net` 參數來指定容器的網路配置,有4個可選值:
|
||||
* `--net=bridge` 這個是默認值,連接到默認的網橋。
|
||||
* `--net=host` 告訴 Docker 不要將容器網路放到隔離的名字空間中,即不要容器化容器內的網路。此時容器使用本地主機的網路,它擁有完全的本地主機接口訪問權限。容器程序可以跟主機其它 root 程序一樣可以打開低範圍的端口,可以訪問本地網路服務比如 D-bus,還可以讓容器做一些影響整個主機系統的事情,比如重啟主機。因此使用這個選項的時候要非常小心。如果進一步的使用 `--privileged=true`,容器會被允許直接配置主機的網路堆棧。
|
||||
* `--net=container:NAME_or_ID` 讓 Docker 將新建容器的程序放到一個已存在容器的網路棧中,新容器程序有自己的文件系統、程序列表和資源限制,但會和已存在的容器共享 IP 地址和端口等網路資源,兩者程序可以直接通過 `lo` 環回接口通信。
|
||||
* `--net=none` 讓 Docker 將新容器放到隔離的網路棧中,但是不進行網路配置。之後,用戶可以自己進行配置。
|
||||
* `--net=container:NAME_or_ID` 讓 Docker 將新建容器的程序放到一個已存在容器的網路棧中,新容器程序有自己的文件系統、程序列表和資源限制,但會和已存在的容器共享 IP 地址和端口等網路資源,兩者程序可以直接透過 `lo` 環回接口通信。
|
||||
* `--net=none` 讓 Docker 將新容器放到隔離的網路棧中,但是不進行網路配置。之後,使用者可以自己進行配置。
|
||||
|
||||
### 網路配置細節
|
||||
用戶使用 `--net=none` 後,可以自行配置網路,讓容器達到跟平常一樣具有訪問網路的權限。通過這個過程,可以了解 Docker 配置網路的細節。
|
||||
使用者使用 `--net=none` 後,可以自行配置網路,讓容器達到跟平常一樣具有訪問網路的權限。透過這個過程,可以了解 Docker 配置網路的細節。
|
||||
|
||||
首先,啟動一個 `/bin/bash` 容器,指定 `--net=none` 參數。
|
||||
```
|
||||
$ sudo docker run -i -t --rm --net=none base /bin/bash
|
||||
root@63f36fc01b5f:/#
|
||||
```
|
||||
在本地主機查找容器的程序 id,並為它創建網路命名空間。
|
||||
在本地主機查找容器的程序 id,並為它建立網路命名空間。
|
||||
```
|
||||
$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f
|
||||
2778
|
||||
@ -48,7 +48,7 @@ $ ip addr show docker0
|
||||
inet 172.17.42.1/16 scope global docker0
|
||||
...
|
||||
```
|
||||
創建一對 “veth pair” 接口 A 和 B,綁定 A 到網橋 `docker0`,並啟用它
|
||||
建立一對 “veth pair” 接口 A 和 B,綁定 A 到網橋 `docker0`,並啟用它
|
||||
```
|
||||
$ sudo ip link add A type veth peer name B
|
||||
$ sudo brctl addif docker0 A
|
||||
@ -66,4 +66,4 @@ $ sudo ip netns exec $pid ip route add default via 172.17.42.1
|
||||
|
||||
當容器結束後,Docker 會清空容器,容器內的 eth0 會隨網路命名空間一起被清除,A 接口也被自動從 `docker0` 卸載。
|
||||
|
||||
此外,用戶可以使用 `ip netns exec` 命令來在指定網路名字空間中進行配置,從而配置容器內的網路。
|
||||
此外,使用者可以使用 `ip netns exec` 命令來在指定網路名字空間中進行配置,從而配置容器內的網路。
|
||||
|
@ -1,7 +1,7 @@
|
||||
## Union 文件系統
|
||||
Union文件系統([UnionFS](http://en.wikipedia.org/wiki/UnionFS))是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。
|
||||
|
||||
Union 文件系統是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
|
||||
Union 文件系統是 Docker 鏡像的基礎。鏡像可以透過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
|
||||
|
||||
另外,不同 Docker 容器就可以共享一些基礎的文件系統層,同時再加上自己獨有的改動層,大大提高了存儲的效率。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user