mirror of
https://github.com/yeasy/docker_practice.git
synced 2024-11-16 11:33:40 +00:00
merge master and develop
This commit is contained in:
commit
d4ba34df99
@ -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 隨機分配一個本地未占用的私有網段(在 [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 網絡](../_images/network.png)
|
||||
|
||||
接下来的部分将介绍在一些场景中,Docker 所有的网络定制配置。以及通过 Linux 命令来调整、补充、甚至替换 Docker 默认的网络配置。
|
||||
接下來的部分將介紹在一些場景中,Docker 所有的網絡定制配置。以及通過 Linux 命令來調整、補充、甚至替換 Docker 默認的網絡配置。
|
||||
|
@ -1,35 +1,35 @@
|
||||
## 容器访问控制
|
||||
容器的访问控制,主要通过 Linux 上的 `iptables` 防火墙来进行管理和实现。`iptables` 是 Linux 上默认的防火墙软件,在大部分发行版中都自带。
|
||||
## 容器訪問控制
|
||||
容器的訪問控制,主要通過 Linux 上的 `iptables` 防火墻來進行管理和實現。`iptables` 是 Linux 上默認的防火墻軟件,在大部分發行版中都自帶。
|
||||
|
||||
### 容器访问外部网络
|
||||
容器要想访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开。
|
||||
### 容器訪問外部網絡
|
||||
容器要想訪問外部網絡,需要本地系統的轉發支持。在Linux 系統中,檢查轉發是否打開。
|
||||
|
||||
```
|
||||
$sysctl net.ipv4.ip_forward
|
||||
net.ipv4.ip_forward = 1
|
||||
```
|
||||
如果为 0,说明没有开启转发,则需要手动打开。
|
||||
如果為 0,說明沒有開啟轉發,則需要手動打開。
|
||||
```
|
||||
$sysctl -w net.ipv4.ip_forward=1
|
||||
```
|
||||
如果在启动 Docker 服务的时候设定 `--ip-forward=true`, Docker 就会自动设定系统的 `ip_forward` 参数为 1。
|
||||
如果在啟動 Docker 服務的時候設定 `--ip-forward=true`, Docker 就會自動設定系統的 `ip_forward` 參數為 1。
|
||||
|
||||
### 容器之间访问
|
||||
容器之间相互访问,需要两方面的支持。
|
||||
* 容器的网络拓扑是否已经互联。默认情况下,所有容器都会被连接到 `docker0` 网桥上。
|
||||
* 本地系统的防火墙软件 -- `iptables` 是否允许通过。
|
||||
### 容器之間訪問
|
||||
容器之間相互訪問,需要兩方面的支持。
|
||||
* 容器的網絡拓撲是否已經互聯。默認情況下,所有容器都會被連接到 `docker0` 網橋上。
|
||||
* 本地系統的防火墻軟件 -- `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` 来禁止它。
|
||||
可見,默認情況下,不同容器之間是允許網絡互通的。如果為了安全考慮,可以在 `/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` 规则。
|
||||
例如,在啟動 Docker 服務時,可以同時使用 `icc=false --iptables=true` 參數來關閉允許相互的網絡訪問,並讓 Docker 可以修改系統中的 `iptables` 規則。
|
||||
|
||||
此时,系统中的 `iptables` 规则可能是类似
|
||||
此時,系統中的 `iptables` 規則可能是類似
|
||||
```
|
||||
$ sudo iptables -nL
|
||||
...
|
||||
@ -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
|
||||
...
|
||||
@ -52,4 +52,4 @@ ACCEPT tcp -- 172.17.0.3 172.17.0.2 tcp dpt:80
|
||||
DROP all -- 0.0.0.0/0 0.0.0.0/0
|
||||
```
|
||||
|
||||
注意:`--link=CONTAINER_NAME:ALIAS` 中的 `CONTAINER_NAME` 目前必须是 Docker 分配的名字,或使用 `--name` 参数指定的名字。主机名则不会被识别。
|
||||
註意:`--link=CONTAINER_NAME:ALIAS` 中的 `CONTAINER_NAME` 目前必須是 Docker 分配的名字,或使用 `--name` 參數指定的名字。主機名則不會被識別。
|
||||
|
@ -1,21 +1,21 @@
|
||||
## 自定义网桥
|
||||
除了默认的 `docker0` 网桥,用户也可以指定网桥来连接各个容器。
|
||||
## 自定義網橋
|
||||
除了默認的 `docker0` 網橋,用戶也可以指定網橋來連接各個容器。
|
||||
|
||||
在启动 Docker 服务的时候,使用 `-b BRIDGE`或`--bridge=BRIDGE` 来指定使用的网桥。
|
||||
在啟動 Docker 服務的時候,使用 `-b BRIDGE`或`--bridge=BRIDGE` 來指定使用的網橋。
|
||||
|
||||
如果服务已经运行,那需要先停止服务,并删除旧的网桥。
|
||||
如果服務已經運行,那需要先停止服務,並刪除舊的網橋。
|
||||
```
|
||||
$ 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,12 +23,12 @@ $ 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
|
||||
```
|
||||
启动 Docker 服务。
|
||||
新建一个容器,可以看到它已经桥接到了 `bridge0` 上。
|
||||
啟動 Docker 服務。
|
||||
新建一個容器,可以看到它已經橋接到了 `bridge0` 上。
|
||||
|
||||
可以继续用 `brctl show` 命令查看桥接的信息。另外,在容器中可以使用 `ip addr` 和 `ip route` 命令来查看 IP 地址配置和路由信息。
|
||||
可以繼續用 `brctl show` 命令查看橋接的信息。另外,在容器中可以使用 `ip addr` 和 `ip route` 命令來查看 IP 地址配置和路由信息。
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 编辑网络配置文件
|
||||
## 編輯網絡配置文件
|
||||
|
||||
Docker 1.2.0 开始支持在运行中的容器里编辑 `/etc/hosts`, `/etc/hostname` 和 `/etc/resolve.conf` 文件。
|
||||
Docker 1.2.0 開始支持在運行中的容器裏編輯 `/etc/hosts`, `/etc/hostname` 和 `/etc/resolve.conf` 文件。
|
||||
|
||||
但是这些修改是临时的,只在运行的容器中保留,容器终止或重启后并不会被保存下来。也不会被 `docker commit` 提交。
|
||||
但是這些修改是臨時的,只在運行的容器中保留,容器終止或重啟後並不會被保存下來。也不會被 `docker commit` 提交。
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 配置 DNS
|
||||
Docker 没有为每个容器专门定制镜像,那么怎么自定义配置容器的主机名和 DNS 配置呢?
|
||||
秘诀就是它利用虚拟文件来挂载到来容器的 3 个相关配置文件。
|
||||
Docker 沒有為每個容器專門定制鏡像,那麽怎麽自定義配置容器的主機名和 DNS 配置呢?
|
||||
秘訣就是它利用虛擬文件來掛載到來容器的 3 個相關配置文件。
|
||||
|
||||
在容器中使用 mount 命令可以看到挂载信息:
|
||||
在容器中使用 mount 命令可以看到掛載信息:
|
||||
```
|
||||
$ mount
|
||||
...
|
||||
@ -11,19 +11,19 @@ $ 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` 看到。
|
||||
設定容器的主機名,它會被寫到容器內的 `/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`。
|
||||
注意:如果没有上述最后 2 个选项,Docker 会默认用主机上的 `/etc/resolv.conf` 来配置容器。
|
||||
設定容器的搜索域,當設定搜索域為 `.example.com` 時,在搜索一個名為 host 的主機時,DNS 不僅搜索host,還會搜索 `host.example.com`。
|
||||
註意:如果沒有上述最後 2 個選項,Docker 會默認用主機上的 `/etc/resolv.conf` 來配置容器。
|
||||
|
@ -1,22 +1,22 @@
|
||||
## 配置 docker0 网桥
|
||||
Docker 服务默认会创建一个 `docker0` 网桥(其上有一个 `docker0` 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
|
||||
## 配置 docker0 網橋
|
||||
Docker 服務默認會創建一個 `docker0` 網橋(其上有一個 `docker0` 內部接口),它在內核層連通了其他的物理或虛擬網卡,這就將所有容器和本地主機都放到同一個物理網絡。
|
||||
|
||||
Docker 默认指定了 `docker0` 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。
|
||||
* `--bip=CIDR` -- IP 地址加掩码格式,例如 192.168.1.5/24
|
||||
* `--mtu=BYTES` -- 覆盖默认的 Docker mtu 配置
|
||||
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_OPTS,然後重啟服務。
|
||||
由於目前 Docker 網橋是 Linux 網橋,用戶可以使用 `brctl show` 來查看網橋和端口連接信息。
|
||||
```
|
||||
$ sudo brctl show
|
||||
bridge name bridge id STP enabled interfaces
|
||||
docker0 8000.3a1d7362b4ee no veth65f9
|
||||
vethdda6
|
||||
```
|
||||
*注:`brctl` 命令在 Debian、Ubuntu 中可以使用 `sudo apt-get install bridge-utils` 来安装。
|
||||
*註:`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
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 工具和示例
|
||||
在介绍自定义网络拓扑之前,你可能会对一些外部工具和例子感兴趣:
|
||||
在介紹自定義網絡拓撲之前,你可能會對一些外部工具和例子感興趣:
|
||||
|
||||
### 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,10 +1,10 @@
|
||||
## 映射容器端口到宿主主机的实现
|
||||
## 映射容器端口到宿主主機的實現
|
||||
|
||||
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。
|
||||
### 容器访问外部实现
|
||||
容器所有到外部网络的连接,源地址都会被NAT成本地系统的IP地址。这是使用 `iptables` 的源地址伪装操作实现的。
|
||||
默認情況下,容器可以主動訪問到外部網絡的連接,但是外部網絡無法訪問到容器。
|
||||
### 容器訪問外部實現
|
||||
容器所有到外部網絡的連接,源地址都會被NAT成本地系統的IP地址。這是使用 `iptables` 的源地址偽裝操作實現的。
|
||||
|
||||
查看主机的 NAT 规则。
|
||||
查看主機的 NAT 規則。
|
||||
```
|
||||
$ sudo iptables -t nat -nL
|
||||
...
|
||||
@ -13,15 +13,15 @@ target prot opt source destination
|
||||
MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16
|
||||
...
|
||||
```
|
||||
其中,上述规则将所有源地址在 `172.17.0.0/16` 网段,目标地址为其他网段(外部网络)的流量动态伪装为从系统网卡发出。MASQUERADE 跟传统 SNAT 的好处是它能动态从网卡获取地址。
|
||||
其中,上述規則將所有源地址在 `172.17.0.0/16` 網段,目標地址為其他網段(外部網絡)的流量動態偽裝為從系統網卡發出。MASQUERADE 跟傳統 SNAT 的好處是它能動態從網卡獲取地址。
|
||||
|
||||
### 外部访问容器实现
|
||||
### 外部訪問容器實現
|
||||
|
||||
容器允许外部访问,可以在 `docker run` 时候通过 `-p` 或 `-P` 参数来启用。
|
||||
容器允許外部訪問,可以在 `docker run` 時候通過 `-p` 或 `-P` 參數來啟用。
|
||||
|
||||
不管用那种办法,其实也是在本地的 `iptable` 的 nat 表中添加相应的规则。
|
||||
不管用那種辦法,其實也是在本地的 `iptable` 的 nat 表中添加相應的規則。
|
||||
|
||||
使用 `-P` 时:
|
||||
使用 `-P` 時:
|
||||
```
|
||||
$ iptables -t nat -nL
|
||||
...
|
||||
@ -30,14 +30,14 @@ target prot opt source destination
|
||||
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49153 to:172.17.0.2:80
|
||||
```
|
||||
|
||||
使用 `-p 80:80` 时:
|
||||
使用 `-p 80:80` 時:
|
||||
```
|
||||
$ iptables -t nat -nL
|
||||
Chain DOCKER (2 references)
|
||||
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
|
||||
IP::port` 来指定允许访问容器的主机上的 IP、接口等,以制定更严格的规则。
|
||||
* 如果希望永久绑定到某个固定的 IP 地址,可以在 Docker 配置文件 `/etc/default/docker` 中指定 `DOCKER_OPTS="--ip=IP_ADDRESS"`,之后重启 Docker 服务即可生效。
|
||||
註意:
|
||||
* 這裏的規則映射了 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,11 +1,11 @@
|
||||
## 示例:创建一个点到点连接
|
||||
默认情况下,Docker 会将所有容器连接到由 `docker0` 提供的虚拟子网中。
|
||||
## 示例:創建一個點到點連接
|
||||
默認情況下,Docker 會將所有容器連接到由 `docker0` 提供的虛擬子網中。
|
||||
|
||||
用户有时候需要两个容器之间可以直连通信,而不用通过主机网桥进行桥接。
|
||||
用戶有時候需要兩個容器之間可以直連通信,而不用通過主機網橋進行橋接。
|
||||
|
||||
解决办法很简单:创建一对 `peer` 接口,分别放到两个容器中,配置成点到点链路类型即可。
|
||||
解決辦法很簡單:創建一對 `peer` 接口,分別放到兩個容器中,配置成點到點鏈路類型即可。
|
||||
|
||||
首先启动 2 个容器:
|
||||
首先啟動 2 個容器:
|
||||
```
|
||||
$ sudo docker run -i -t --rm --net=none base /bin/bash
|
||||
root@1f1f4c1f931a:/#
|
||||
@ -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
|
||||
|
||||
@ -38,8 +38,8 @@ $ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B
|
||||
$ sudo ip netns exec 3004 ip link set B up
|
||||
$ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B
|
||||
```
|
||||
现在这 2 个容器就可以相互 ping 通,并成功建立连接。点到点链路不需要子网和子网掩码。
|
||||
現在這 2 個容器就可以相互 ping 通,並成功建立連接。點到點鏈路不需要子網和子網掩碼。
|
||||
|
||||
此外,也可以不指定 `--net=none` 来创建点到点链路。这样容器还可以通过原先的网络来通信。
|
||||
此外,也可以不指定 `--net=none` 來創建點到點鏈路。這樣容器還可以通過原先的網絡來通信。
|
||||
|
||||
利用类似的办法,可以创建一个只跟主机通信的容器。但是一般情况下,更推荐使用 `--icc=false` 来关闭容器之间的通信。
|
||||
利用類似的辦法,可以創建一個只跟主機通信的容器。但是一般情況下,更推薦使用 `--icc=false` 來關閉容器之間的通信。
|
||||
|
@ -1,23 +1,23 @@
|
||||
## 快速配置指南
|
||||
|
||||
下面是一个跟 Docker 网络相关的命令列表。
|
||||
下面是一個跟 Docker 網絡相關的命令列表。
|
||||
|
||||
其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效。
|
||||
* `-b BRIDGE or --bridge=BRIDGE` --指定容器挂载的网桥
|
||||
* `--bip=CIDR` --定制 docker0 的掩码
|
||||
* `-H SOCKET... or --host=SOCKET...` --Docker 服务端接收命令的通道
|
||||
* `--icc=true|false` --是否支持容器之间进行通信
|
||||
* `--ip-forward=true|false` --请看下文容器之间的通信
|
||||
* `--iptables=true|false` --禁止 Docker 添加 iptables 规则
|
||||
* `--mtu=BYTES` --容器网络中的 MTU
|
||||
其中有些命令選項只有在 Docker 服務啟動的時候才能配置,而且不能馬上生效。
|
||||
* `-b BRIDGE or --bridge=BRIDGE` --指定容器掛載的網橋
|
||||
* `--bip=CIDR` --定制 docker0 的掩碼
|
||||
* `-H SOCKET... or --host=SOCKET...` --Docker 服務端接收命令的通道
|
||||
* `--icc=true|false` --是否支持容器之間進行通信
|
||||
* `--ip-forward=true|false` --請看下文容器之間的通信
|
||||
* `--iptables=true|false` --禁止 Docker 添加 iptables 規則
|
||||
* `--mtu=BYTES` --容器網絡中的 MTU
|
||||
|
||||
下面2个命令选项既可以在启动服务时指定,也可以 Docker 容器启动(`docker run`)时候指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 `docker run` 时可以覆盖设置的默认值。
|
||||
* `--dns=IP_ADDRESS...` --使用指定的DNS服务器
|
||||
下面2個命令選項既可以在啟動服務時指定,也可以 Docker 容器啟動(`docker run`)時候指定。在 Docker 服務啟動的時候指定則會成為默認值,後面執行 `docker run` 時可以覆蓋設置的默認值。
|
||||
* `--dns=IP_ADDRESS...` --使用指定的DNS服務器
|
||||
* `--dns-search=DOMAIN...` --指定DNS搜索域
|
||||
|
||||
最后这些选项只有在 `docker run` 执行时使用,因为它是针对容器的特性内容。
|
||||
* `-h HOSTNAME or --hostname=HOSTNAME` --配置容器主机名
|
||||
* `--link=CONTAINER_NAME:ALIAS` --添加到另一个容器的连接
|
||||
* `--net=bridge|none|container:NAME_or_ID|host` --配置容器的桥接模式
|
||||
* `-p SPEC or --publish=SPEC` --映射容器端口到宿主主机
|
||||
* `-P or --publish-all=true|false` --映射容器所有端口到宿主主机
|
||||
最後這些選項只有在 `docker run` 執行時使用,因為它是針對容器的特性內容。
|
||||
* `-h HOSTNAME or --hostname=HOSTNAME` --配置容器主機名
|
||||
* `--link=CONTAINER_NAME:ALIAS` --添加到另一個容器的連接
|
||||
* `--net=bridge|none|container:NAME_or_ID|host` --配置容器的橋接模式
|
||||
* `-p SPEC or --publish=SPEC` --映射容器端口到宿主主機
|
||||
* `-P or --publish-all=true|false` --映射容器所有端口到宿主主機
|
||||
|
@ -1,168 +1,168 @@
|
||||
# Docker命令查询
|
||||
# Docker命令查詢
|
||||
|
||||
##基本语法
|
||||
##基本語法
|
||||
docker [OPTIONS] COMMAND [arg...]
|
||||
一般来说,Docker 命令可以用来管理 daemon,或者通过 CLI 命令管理镜像和容器。可以通过 `man docker` 来查看这些命令。
|
||||
一般來說,Docker 命令可以用來管理 daemon,或者通過 CLI 命令管理鏡像和容器。可以通過 `man docker` 來查看這些命令。
|
||||
|
||||
|
||||
##选项
|
||||
##選項
|
||||
-D=true|false
|
||||
使用 debug 模式。默认为 false。
|
||||
使用 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 来指定。
|
||||
-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 來指定。
|
||||
|
||||
--api-enable-cors=true|false
|
||||
在远端 API 中启用 CORS 头。缺省为 false。
|
||||
在遠端 API 中啟用 CORS 頭。缺省為 false。
|
||||
|
||||
-b=""
|
||||
将容器挂载到一个已存在的网桥上。指定为 'none' 时则禁用容器的网络。
|
||||
將容器掛載到一個已存在的網橋上。指定為 'none' 時則禁用容器的網絡。
|
||||
|
||||
--bip=""
|
||||
让动态创建的 docker0 采用给定的 CIDR 地址; 与 -b 选项互斥。
|
||||
讓動態創建的 docker0 采用給定的 CIDR 地址; 與 -b 選項互斥。
|
||||
|
||||
-d=true|false
|
||||
使用 daemon 模式。缺省为 false。
|
||||
使用 daemon 模式。缺省為 false。
|
||||
|
||||
--dns=""
|
||||
让 Docker 使用给定的 DNS 服务器。
|
||||
讓 Docker 使用給定的 DNS 服務器。
|
||||
|
||||
-g=""
|
||||
指定 Docker 运行时的 root 路径。缺省为 /var/lib/docker。
|
||||
指定 Docker 運行時的 root 路徑。缺省為 /var/lib/docker。
|
||||
|
||||
--icc=true|false
|
||||
启用容器间通信。默认为 true。
|
||||
啟用容器間通信。默認為 true。
|
||||
|
||||
--ip=""
|
||||
绑定端口时候的默认 IP 地址。缺省为 0.0.0.0。
|
||||
綁定端口時候的默認 IP 地址。缺省為 0.0.0.0。
|
||||
|
||||
--iptables=true|false
|
||||
禁止 Docker 添加 iptables 规则。缺省为 true。
|
||||
禁止 Docker 添加 iptables 規則。缺省為 true。
|
||||
|
||||
--mtu=VALUE
|
||||
指定容器网络的 mtu。缺省为 1500。
|
||||
指定容器網絡的 mtu。缺省為 1500。
|
||||
|
||||
-p=""
|
||||
指定 daemon 的 PID 文件路径。缺省为 /var/run/docker.pid。
|
||||
指定 daemon 的 PID 文件路徑。缺省為 /var/run/docker.pid。
|
||||
|
||||
-s=""
|
||||
强制 Docker 运行时使用给定的存储驱动。
|
||||
強制 Docker 運行時使用給定的存儲驅動。
|
||||
|
||||
-v=true|false
|
||||
输出版本信息并退出。缺省值为 false。
|
||||
輸出版本信息並退出。缺省值為 false。
|
||||
|
||||
--selinux-enabled=true|false
|
||||
启用 SELinux 支持。缺省值为 false。SELinux 目前不支持 BTRFS 存储驱动。
|
||||
啟用 SELinux 支持。缺省值為 false。SELinux 目前不支持 BTRFS 存儲驅動。
|
||||
|
||||
|
||||
##命令
|
||||
Docker 的命令可以采用 `docker-CMD` 或者 `docker CMD` 的方式执行。两者一致。
|
||||
Docker 的命令可以采用 `docker-CMD` 或者 `docker CMD` 的方式執行。兩者一致。
|
||||
|
||||
docker-attach(1)
|
||||
依附到一个正在运行的容器中。
|
||||
依附到一個正在運行的容器中。
|
||||
|
||||
docker-build(1)
|
||||
从一个 Dockerfile 创建一个镜像
|
||||
從一個 Dockerfile 創建一個鏡像
|
||||
|
||||
docker-commit(1)
|
||||
从一个容器的修改中创建一个新的镜像
|
||||
從一個容器的修改中創建一個新的鏡像
|
||||
|
||||
docker-cp(1)
|
||||
从容器中复制文件到宿主系统中
|
||||
從容器中復制文件到宿主系統中
|
||||
|
||||
docker-diff(1)
|
||||
检查一个容器文件系统的修改
|
||||
檢查一個容器文件系統的修改
|
||||
|
||||
docker-events(1)
|
||||
从服务端获取实时的事件
|
||||
從服務端獲取實時的事件
|
||||
|
||||
docker-export(1)
|
||||
导出容器内容为一个 tar 包
|
||||
導出容器內容為一個 tar 包
|
||||
|
||||
docker-history(1)
|
||||
显示一个镜像的历史
|
||||
顯示一個鏡像的歷史
|
||||
|
||||
docker-images(1)
|
||||
列出存在的镜像
|
||||
列出存在的鏡像
|
||||
|
||||
docker-import(1)
|
||||
导入一个文件(典型为 tar 包)路径或目录来创建一个镜像
|
||||
導入一個文件(典型為 tar 包)路徑或目錄來創建一個鏡像
|
||||
|
||||
docker-info(1)
|
||||
显示一些相关的系统信息
|
||||
顯示一些相關的系統信息
|
||||
|
||||
docker-inspect(1)
|
||||
显示一个容器的底层具体信息。
|
||||
顯示一個容器的底層具體信息。
|
||||
|
||||
docker-kill(1)
|
||||
关闭一个运行中的容器 (包括进程和所有资源)
|
||||
關閉一個運行中的容器 (包括進程和所有資源)
|
||||
|
||||
docker-load(1)
|
||||
从一个 tar 包中加载一个镜像
|
||||
從一個 tar 包中加載一個鏡像
|
||||
|
||||
docker-login(1)
|
||||
注册或登录到一个 Docker 的仓库服务器
|
||||
註冊或登錄到一個 Docker 的倉庫服務器
|
||||
|
||||
docker-logout(1)
|
||||
从 Docker 的仓库服务器登出
|
||||
從 Docker 的倉庫服務器登出
|
||||
|
||||
docker-logs(1)
|
||||
获取容器的 log 信息
|
||||
獲取容器的 log 信息
|
||||
|
||||
docker-pause(1)
|
||||
暂停一个容器中的所有进程
|
||||
暫停一個容器中的所有進程
|
||||
|
||||
docker-port(1)
|
||||
查找一个 nat 到一个私有网口的公共口
|
||||
查找一個 nat 到一個私有網口的公共口
|
||||
|
||||
docker-ps(1)
|
||||
列出容器
|
||||
|
||||
docker-pull(1)
|
||||
从一个Docker的仓库服务器下拉一个镜像或仓库
|
||||
從一個Docker的倉庫服務器下拉一個鏡像或倉庫
|
||||
|
||||
docker-push(1)
|
||||
将一个镜像或者仓库推送到一个 Docker 的注册服务器
|
||||
將一個鏡像或者倉庫推送到一個 Docker 的註冊服務器
|
||||
|
||||
docker-restart(1)
|
||||
重启一个运行中的容器
|
||||
重啟一個運行中的容器
|
||||
|
||||
docker-rm(1)
|
||||
删除给定的若干个容器
|
||||
刪除給定的若幹個容器
|
||||
|
||||
docker-rmi(1)
|
||||
删除给定的若干个镜像
|
||||
刪除給定的若幹個鏡像
|
||||
|
||||
docker-run(1)
|
||||
创建一个新容器,并在其中运行给定命令
|
||||
創建一個新容器,並在其中運行給定命令
|
||||
|
||||
docker-save(1)
|
||||
保存一个镜像为 tar 包文件
|
||||
保存一個鏡像為 tar 包文件
|
||||
|
||||
docker-search(1)
|
||||
在 Docker index 中搜索一个镜像
|
||||
在 Docker index 中搜索一個鏡像
|
||||
|
||||
docker-start(1)
|
||||
启动一个容器
|
||||
啟動一個容器
|
||||
|
||||
docker-stop(1)
|
||||
终止一个运行中的容器
|
||||
終止一個運行中的容器
|
||||
|
||||
docker-tag(1)
|
||||
为一个镜像打标签
|
||||
為一個鏡像打標簽
|
||||
|
||||
docker-top(1)
|
||||
查看一个容器中的正在运行的进程信息
|
||||
查看一個容器中的正在運行的進程信息
|
||||
|
||||
docker-unpause(1)
|
||||
将一个容器内所有的进程从暂停状态中恢复
|
||||
將一個容器內所有的進程從暫停狀態中恢復
|
||||
|
||||
docker-version(1)
|
||||
输出 Docker 的版本信息
|
||||
輸出 Docker 的版本信息
|
||||
|
||||
docker-wait(1)
|
||||
阻塞直到一个容器终止,然后输出它的退出符
|
||||
阻塞直到一個容器終止,然後輸出它的退出符
|
||||
|
||||
##一张图总结 Docker 的命令
|
||||
##一張圖總結 Docker 的命令
|
||||
|
||||
![命令周期](../_images/cmd_logic.png)
|
||||
|
@ -1,2 +1,2 @@
|
||||
# 常见仓库介绍
|
||||
本章将介绍常见的一些仓库和镜像的功能,使用方法和生成它们的 Dockerfile 等。包括 Ubuntu、CentOS、MySQL、MongoDB、Redis、Nginx、Wordpress、Node.js 等。
|
||||
# 常見倉庫介紹
|
||||
本章將介紹常見的一些倉庫和鏡像的功能,使用方法和生成它們的 Dockerfile 等。包括 Ubuntu、CentOS、MySQL、MongoDB、Redis、Nginx、Wordpress、Node.js 等。
|
||||
|
@ -1,11 +1,11 @@
|
||||
## [CentOS](https://registry.hub.docker.com/_/centos/)
|
||||
|
||||
### 基本信息
|
||||
[CentOS](https://en.wikipedia.org/wiki/CentOS) 是流行的 Linux 发行版,其软件包大多跟 RedHat 系列保持一致。
|
||||
该仓库提供了 CentOS 从 5 ~ 7 各个版本的镜像。
|
||||
[CentOS](https://en.wikipedia.org/wiki/CentOS) 是流行的 Linux 發行版,其軟件包大多跟 RedHat 系列保持一致。
|
||||
該倉庫提供了 CentOS 從 5 ~ 7 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
默认会启动一个最小化的 CentOS 环境。
|
||||
默認會啟動一個最小化的 CentOS 環境。
|
||||
```
|
||||
$ sudo docker run --name some-centos -i -t centos bash
|
||||
bash-4.2#
|
||||
|
@ -1,20 +1,20 @@
|
||||
## [MongoDB](https://registry.hub.docker.com/_/mongo/)
|
||||
|
||||
### 基本信息
|
||||
[MongoDB](https://en.wikipedia.org/wiki/MongoDB) 是开源的 NoSQL 数据库实现。
|
||||
该仓库提供了 MongoDB 2.2 ~ 2.7 各个版本的镜像。
|
||||
[MongoDB](https://en.wikipedia.org/wiki/MongoDB) 是開源的 NoSQL 數據庫實現。
|
||||
該倉庫提供了 MongoDB 2.2 ~ 2.7 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
默认会在 `27017` 端口启动数据库。
|
||||
默認會在 `27017` 端口啟動數據庫。
|
||||
```
|
||||
$ 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,19 +1,19 @@
|
||||
## [MySQL](https://registry.hub.docker.com/_/mysql/)
|
||||
|
||||
### 基本信息
|
||||
[MySQL](https://en.wikipedia.org/wiki/MySQL) 是开源的关系数据库实现。
|
||||
该仓库提供了 MySQL 各个版本的镜像,包括 5.6 系列、5.7 系列等。
|
||||
[MySQL](https://en.wikipedia.org/wiki/MySQL) 是開源的關系數據庫實現。
|
||||
該倉庫提供了 MySQL 各個版本的鏡像,包括 5.6 系列、5.7 系列等。
|
||||
|
||||
### 使用方法
|
||||
默认会在 `3306` 端口启动数据库。
|
||||
默認會在 `3306` 端口啟動數據庫。
|
||||
```
|
||||
$ sudo docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=mysecretpassword -d mysql
|
||||
```
|
||||
之后就可以使用其它应用来连接到该容器。
|
||||
之後就可以使用其它應用來連接到該容器。
|
||||
```
|
||||
$ 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,34 +1,34 @@
|
||||
## [Nginx](https://registry.hub.docker.com/_/nginx/)
|
||||
|
||||
### 基本信息
|
||||
[Nginx](https://en.wikipedia.org/wiki/Nginx) 是开源的高效的 Web 服务器实现,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等协议。
|
||||
该仓库提供了 Nginx 1.0 ~ 1.7 各个版本的镜像。
|
||||
[Nginx](https://en.wikipedia.org/wiki/Nginx) 是開源的高效的 Web 服務器實現,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等協議。
|
||||
該倉庫提供了 Nginx 1.0 ~ 1.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
|
||||
```
|
||||
之后生成新的镜像,并启动一个容器。
|
||||
之後生成新的鏡像,並啟動一個容器。
|
||||
```
|
||||
$ sudo docker build -t some-content-nginx .
|
||||
$ sudo docker run --name some-nginx -d some-content-nginx
|
||||
```
|
||||
开放端口,并映射到本地的 `8080` 端口。
|
||||
開放端口,並映射到本地的 `8080` 端口。
|
||||
```
|
||||
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
|
||||
```
|
||||
使用配置文件时,为了在容器中正常运行,需要保持 `daemon off;`。
|
||||
使用配置文件時,為了在容器中正常運行,需要保持 `daemon off;`。
|
||||
|
||||
### Dockerfile
|
||||
* [1 ~ 1.7 版本](https://github.com/nginxinc/docker-nginx/blob/3713a0157083eb4776e71f5a5aef4b2a5bc03ab1/Dockerfile)
|
||||
|
@ -1,23 +1,23 @@
|
||||
## [Node.js](https://registry.hub.docker.com/_/node/)
|
||||
|
||||
### 基本信息
|
||||
[Node.js](https://en.wikipedia.org/wiki/Node.js)是基于 JavaScript 的可扩展服务端和网络软件开发平台。
|
||||
该仓库提供了 Node.js 0.8 ~ 0.11 各个版本的镜像。
|
||||
[Node.js](https://en.wikipedia.org/wiki/Node.js)是基於 JavaScript 的可擴展服務端和網絡軟件開發平臺。
|
||||
該倉庫提供了 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
|
||||
```
|
||||
|
||||
也可以直接运行一个简单容器。
|
||||
也可以直接運行一個簡單容器。
|
||||
```
|
||||
$ sudo docker run -it --rm --name my-running-script -v "$(pwd)":/usr/src/myapp -w /usr/src/myapp node:0.10 node your-daemon-or-script.js
|
||||
```
|
||||
|
@ -1,25 +1,25 @@
|
||||
## [Redis](https://registry.hub.docker.com/_/redis/)
|
||||
|
||||
### 基本信息
|
||||
[Redis](https://en.wikipedia.org/wiki/Redis) 是开源的内存 Key-Value 数据库实现。
|
||||
该仓库提供了 Redis 2.6 ~ 2.8.9 各个版本的镜像。
|
||||
[Redis](https://en.wikipedia.org/wiki/Redis) 是開源的內存 Key-Value 數據庫實現。
|
||||
該倉庫提供了 Redis 2.6 ~ 2.8.9 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
默认会在 `6379` 端口启动数据库。
|
||||
默認會在 `6379` 端口啟動數據庫。
|
||||
```
|
||||
$ sudo docker run --name some-redis -d redis
|
||||
```
|
||||
另外还可以启用 [持久存储](http://redis.io/topics/persistence)。
|
||||
另外還可以啟用 [持久存儲](http://redis.io/topics/persistence)。
|
||||
```
|
||||
$ sudo docker run --name some-redis -d redis redis-server --appendonly yes
|
||||
```
|
||||
默认数据存储位置在 `VOLUME/data`。可以使用 `--volumes-from some-volume-container` 或 `-v /docker/host/dir:/data` 将数据存放到本地。
|
||||
默認數據存儲位置在 `VOLUME/data`。可以使用 `--volumes-from some-volume-container` 或 `-v /docker/host/dir:/data` 將數據存放到本地。
|
||||
|
||||
使用其他应用连接到容器,可以用
|
||||
使用其他應用連接到容器,可以用
|
||||
```
|
||||
$ 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,11 +1,11 @@
|
||||
## [Ubuntu](https://registry.hub.docker.com/_/ubuntu/)
|
||||
|
||||
### 基本信息
|
||||
[Ubuntu](https://en.wikipedia.org/wiki/Ubuntu) 是流行的 Linux 发行版,其自带软件版本往往较新一些。
|
||||
该仓库提供了 Ubuntu从12.04 ~ 14.10 各个版本的镜像。
|
||||
[Ubuntu](https://en.wikipedia.org/wiki/Ubuntu) 是流行的 Linux 發行版,其自帶軟件版本往往較新一些。
|
||||
該倉庫提供了 Ubuntu從12.04 ~ 14.10 各個版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
默认会启动一个最小化的 Ubuntu 环境。
|
||||
默認會啟動一個最小化的 Ubuntu 環境。
|
||||
```
|
||||
$ sudo docker run --name some-ubuntu -i -t ubuntu
|
||||
root@523c70904d54:/#
|
||||
|
@ -1,19 +1,19 @@
|
||||
## [WordPress](https://registry.hub.docker.com/_/wordpress/)
|
||||
|
||||
### 基本信息
|
||||
[WordPress](https://en.wikipedia.org/wiki/WordPress) 是开源的 Blog 和内容管理系统框架,它基于 PhP 和 MySQL。
|
||||
该仓库提供了 WordPress 4.0 版本的镜像。
|
||||
[WordPress](https://en.wikipedia.org/wiki/WordPress) 是開源的 Blog 和內容管理系統框架,它基於 PhP 和 MySQL。
|
||||
該倉庫提供了 WordPress 4.0 版本的鏡像。
|
||||
|
||||
### 使用方法
|
||||
启动容器需要 MySQL 的支持,默认端口为 `80`。
|
||||
啟動容器需要 MySQL 的支持,默認端口為 `80`。
|
||||
```
|
||||
$ sudo docker run --name some-wordpress --link some-mysql:mysql -d wordpress
|
||||
```
|
||||
启动 WordPress 容器时可以指定的一些环境参数包括
|
||||
* `-e WORDPRESS_DB_USER=...` 缺省为 “root”
|
||||
* `-e WORDPRESS_DB_PASSWORD=...` 缺省为连接 mysql 容器的环境变量 `MYSQL_ROOT_PASSWORD` 的值
|
||||
* `-e WORDPRESS_DB_NAME=...` 缺省为 “wordpress”
|
||||
* `-e WORDPRESS_AUTH_KEY=...`, `-e WORDPRESS_SECURE_AUTH_KEY=...`, `-e WORDPRESS_LOGGED_IN_KEY=...`, `-e WORDPRESS_NONCE_KEY=...`, `-e WORDPRESS_AUTH_SALT=...`, `-e WORDPRESS_SECURE_AUTH_SALT=...`, `-e WORDPRESS_LOGGED_IN_SALT=...`, `-e WORDPRESS_NONCE_SALT=...` 缺省为随机 sha1 串
|
||||
啟動 WordPress 容器時可以指定的一些環境參數包括
|
||||
* `-e WORDPRESS_DB_USER=...` 缺省為 “root”
|
||||
* `-e WORDPRESS_DB_PASSWORD=...` 缺省為連接 mysql 容器的環境變量 `MYSQL_ROOT_PASSWORD` 的值
|
||||
* `-e WORDPRESS_DB_NAME=...` 缺省為 “wordpress”
|
||||
* `-e WORDPRESS_AUTH_KEY=...`, `-e WORDPRESS_SECURE_AUTH_KEY=...`, `-e WORDPRESS_LOGGED_IN_KEY=...`, `-e WORDPRESS_NONCE_KEY=...`, `-e WORDPRESS_AUTH_SALT=...`, `-e WORDPRESS_SECURE_AUTH_SALT=...`, `-e WORDPRESS_LOGGED_IN_SALT=...`, `-e WORDPRESS_NONCE_SALT=...` 缺省為隨機 sha1 串
|
||||
|
||||
### Dockerfile
|
||||
* [4.0 版本](https://github.com/docker-library/wordpress/blob/aee00669e7c43f435f021cb02871bffd63d5677a/Dockerfile)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# 资源链接
|
||||
* Docker 主站点: https://www.docker.io
|
||||
* Docker 注册中心API: http://docs.docker.com/reference/api/registry_api/
|
||||
# 資源鏈接
|
||||
* Docker 主站點: https://www.docker.io
|
||||
* Docker 註冊中心API: http://docs.docker.com/reference/api/registry_api/
|
||||
* Docker Hub API: http://docs.docker.com/reference/api/docker-io_api/
|
||||
* Docker 远端应用API: http://docs.docker.com/reference/api/docker_remote_api/
|
||||
* Dockerfile 参考:https://docs.docker.com/reference/builder/
|
||||
* Dockerfile 最佳实践:https://docs.docker.com/articles/dockerfile_best-practices/
|
||||
* Docker 遠端應用API: http://docs.docker.com/reference/api/docker_remote_api/
|
||||
* Dockerfile 參考:https://docs.docker.com/reference/builder/
|
||||
* Dockerfile 最佳實踐:https://docs.docker.com/articles/dockerfile_best-practices/
|
||||
|
@ -1,7 +1,7 @@
|
||||
## Docker 鏡像
|
||||
Docker 鏡像就是一個唯讀的模板。
|
||||
|
||||
例如:一個鏡像可以包含一個完整的 ubuntu 操作系統環境,裡面僅安裝了 Apache 或用戶需要的其它應用程序。
|
||||
例如:一個鏡像可以包含一個完整的 ubuntu 作業系統環境,裡面僅安裝了 Apache 或用戶需要的其它應用程序。
|
||||
|
||||
鏡像可以用來創建 Docker 容器。
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
#实战案例
|
||||
介绍一些典型的应用场景和案例。
|
||||
#實戰案例
|
||||
介紹一些典型的應用場景和案例。
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 多台物理主机之间的容器互联(暴露容器到真实网络中)
|
||||
Docker 默认的桥接网卡是 docker0。它只会在本机桥接所有的容器网卡,举例来说容器的虚拟网卡在主机上看一般叫做 veth*** 而 Docker 只是把所有这些网卡桥接在一起,如下:
|
||||
## 多臺物理主機之間的容器互聯(暴露容器到真實網絡中)
|
||||
Docker 默認的橋接網卡是 docker0。它只會在本機橋接所有的容器網卡,舉例來說容器的虛擬網卡在主機上看一般叫做 veth*** 而 Docker 只是把所有這些網卡橋接在一起,如下:
|
||||
```
|
||||
[root@opnvz ~]# brctl show
|
||||
bridge name bridge id STP enabled interfaces
|
||||
@ -7,7 +7,7 @@ docker0 8000.56847afe9799 no veth0889
|
||||
veth3c7b
|
||||
veth4061
|
||||
```
|
||||
在容器中看到的地址一般是像下面这样的地址:
|
||||
在容器中看到的地址一般是像下面這樣的地址:
|
||||
```
|
||||
root@ac6474aeb31d:~# ip a
|
||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
|
||||
@ -23,17 +23,17 @@ root@ac6474aeb31d:~# ip a
|
||||
inet6 fe80::487d:68ff:feda:9cf/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
```
|
||||
这样就可以把这个网络看成是一个私有的网络,通过 nat 连接外网,如果要让外网连接到容器中,就需要做端口映射,即 -p 参数。
|
||||
這樣就可以把這個網絡看成是一個私有的網絡,通過 nat 連接外網,如果要讓外網連接到容器中,就需要做端口映射,即 -p 參數。
|
||||
|
||||
如果在企业内部应用,或者做多个物理主机的集群,可能需要将多个物理主机的容器组到一个物理网络中来,那么就需要将这个网桥桥接到我们指定的网卡上。
|
||||
如果在企業內部應用,或者做多個物理主機的集群,可能需要將多個物理主機的容器組到一個物理網絡中來,那麽就需要將這個網橋橋接到我們指定的網卡上。
|
||||
|
||||
### 拓扑图
|
||||
主机 A 和主机 B 的网卡一都连着物理交换机的同一个 vlan 101,这样网桥一和网桥三就相当于在同一个物理网络中了,而容器一、容器三、容器四也在同一物理网络中了,他们之间可以相互通信,而且可以跟同一 vlan 中的其他物理机器互联。
|
||||
![物理拓扑图](../_images/container_connect_topology.png)
|
||||
### 拓撲圖
|
||||
主機 A 和主機 B 的網卡一都連著物理交換機的同一個 vlan 101,這樣網橋一和網橋三就相當於在同一個物理網絡中了,而容器一、容器三、容器四也在同一物理網絡中了,他們之間可以相互通信,而且可以跟同一 vlan 中的其他物理機器互聯。
|
||||
![物理拓撲圖](../_images/container_connect_topology.png)
|
||||
|
||||
### ubuntu 示例
|
||||
下面以 ubuntu 为例创建多个主机的容器联网:
|
||||
创建自己的网桥,编辑 /etc/network/interface 文件
|
||||
下面以 ubuntu 為例創建多個主機的容器聯網:
|
||||
創建自己的網橋,編輯 /etc/network/interface 文件
|
||||
```
|
||||
auto br0
|
||||
iface br0 inet static
|
||||
@ -44,9 +44,9 @@ bridge_ports em1
|
||||
bridge_stp off
|
||||
dns-nameservers 8.8.8.8 192.168.6.1
|
||||
```
|
||||
将 Docker 的默认网桥绑定到这个新建的 br0 上面,这样就将这台机器上容器绑定到 em1 这个网卡所对应的物理网络上了。
|
||||
將 Docker 的默認網橋綁定到這個新建的 br0 上面,這樣就將這臺機器上容器綁定到 em1 這個網卡所對應的物理網絡上了。
|
||||
|
||||
ubuntu 修改 /etc/default/docker 文件,添加最后一行内容
|
||||
ubuntu 修改 /etc/default/docker 文件,添加最後一行內容
|
||||
|
||||
```
|
||||
# Docker Upstart and SysVinit configuration file
|
||||
@ -64,7 +64,7 @@ ubuntu 修改 /etc/default/docker 文件,添加最后一行内容
|
||||
DOCKER_OPTS="-b=br0"
|
||||
```
|
||||
|
||||
在启动 Docker 的时候 使用 -b 参数 将容器绑定到物理网络上。重启 Docker 服务后,再进入容器可以看到它已经绑定到你的物理网络上了。
|
||||
在啟動 Docker 的時候 使用 -b 參數 將容器綁定到物理網絡上。重啟 Docker 服務後,再進入容器可以看到它已經綁定到你的物理網絡上了。
|
||||
|
||||
```
|
||||
root@ubuntudocker:~# docker ps
|
||||
@ -75,4 +75,4 @@ bridge name bridge id STP enabled interfaces
|
||||
br0 8000.7e6e617c8d53 no em1
|
||||
vethe6e5
|
||||
```
|
||||
这样就直接把容器暴露到物理网络上了,多台物理主机的容器也可以相互联网了。需要注意的是,这样就需要自己来保证容器的网络安全了。
|
||||
這樣就直接把容器暴露到物理網絡上了,多臺物理主機的容器也可以相互聯網了。需要註意的是,這樣就需要自己來保證容器的網絡安全了。
|
||||
|
@ -1,14 +1,14 @@
|
||||
## 标准化开发测试和生产环境
|
||||
对于大部分企业来说,搭建 PaaS 既没有那个精力,也没那个必要,用 Docker 做个人的 sandbox 用处又小了点。
|
||||
## 標準化開發測試和生產環境
|
||||
對於大部分企業來說,搭建 PaaS 既沒有那個精力,也沒那個必要,用 Docker 做個人的 sandbox 用處又小了點。
|
||||
|
||||
可以用 Docker 来标准化开发、测试、生产环境。
|
||||
可以用 Docker 來標準化開發、測試、生產環境。
|
||||
|
||||
|
||||
![企业应用结构](../_images/enterprise_usage.png)
|
||||
![企業應用結構](../_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 目錄啟動即可。這樣,在公司內部的開發、測試基本就統一了,不會出現開發部門提交的代碼,測試部門部署不了的問題。
|
||||
|
||||
测试部门发布测试通过的报告后,架构师再一次检测容器环境,就可以直接交由部署工程师将代码和容器分别部署到生产环境中了。这种方式的部署横向性能的扩展性也极好。
|
||||
測試部門發布測試通過的報告後,架構師再一次檢測容器環境,就可以直接交由部署工程師將代碼和容器分別部署到生產環境中了。這種方式的部署橫向性能的擴展性也極好。
|
||||
|
@ -1,10 +1,10 @@
|
||||
## 使用 Supervisor 来管理进程
|
||||
Docker 容器在启动的时候开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务。但我们经常需要在一个机器上开启多个服务,这可以有很多方法,最简单的就是把多个启动命令方到一个启动脚本里面,启动的时候直接启动这个脚本,另外就是安装进程管理工具。
|
||||
## 使用 Supervisor 來管理進程
|
||||
Docker 容器在啟動的時候開啟單個進程,比如,一個 ssh 或者 apache 的 daemon 服務。但我們經常需要在一個機器上開啟多個服務,這可以有很多方法,最簡單的就是把多個啟動命令方到一個啟動腳本裏面,啟動的時候直接啟動這個腳本,另外就是安裝進程管理工具。
|
||||
|
||||
本小节将使用进程管理工具 supervisor 来管理容器中的多个进程。使用 Supervisor 可以更好的控制、管理、重启我们希望运行的进程。在这里我们演示一下如何同时使用 ssh 和 apache 服务。
|
||||
本小節將使用進程管理工具 supervisor 來管理容器中的多個進程。使用 Supervisor 可以更好的控制、管理、重啟我們希望運行的進程。在這裏我們演示一下如何同時使用 ssh 和 apache 服務。
|
||||
|
||||
### 配置
|
||||
首先创建一个 Dockerfile,内容和各部分的解释如下。
|
||||
首先創建一個 Dockerfile,內容和各部分的解釋如下。
|
||||
```
|
||||
FROM ubuntu:13.04
|
||||
MAINTAINER examples@docker.com
|
||||
@ -13,28 +13,28 @@ RUN apt-get update
|
||||
RUN apt-get upgrade -y
|
||||
```
|
||||
|
||||
### 安装 supervisor
|
||||
安装 ssh、apache 和 supervisor。
|
||||
### 安裝 supervisor
|
||||
安裝 ssh、apache 和 supervisor。
|
||||
```
|
||||
RUN apt-get install -y openssh-server apache2 supervisor
|
||||
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
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
```
|
||||
这里我们映射了 22 和 80 端口,使用 supervisord 的可执行路径启动服务。
|
||||
這裏我們映射了 22 和 80 端口,使用 supervisord 的可執行路徑啟動服務。
|
||||
|
||||
|
||||
### supervisor配置文件内容
|
||||
### supervisor配置文件內容
|
||||
```
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
@ -44,14 +44,14 @@ command=/usr/sbin/sshd -D
|
||||
[program:apache2]
|
||||
command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND"
|
||||
```
|
||||
配置文件包含目录和进程,第一段 supervsord 配置软件本身,使用 nodaemon 参数来运行。第二段包含要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令。
|
||||
配置文件包含目錄和進程,第一段 supervsord 配置軟件本身,使用 nodaemon 參數來運行。第二段包含要控制的 2 個服務。每一段包含一個服務的目錄和啟動這個服務的命令。
|
||||
|
||||
### 使用方法
|
||||
创建镜像。
|
||||
創建鏡像。
|
||||
```
|
||||
$ sudo docker build -t test/supervisord .
|
||||
```
|
||||
启动 supervisor 容器。
|
||||
啟動 supervisor 容器。
|
||||
```
|
||||
$ sudo docker run -p 22 -p 80 -t -i test/supervisords
|
||||
2013-11-25 18:53:22,312 CRIT Supervisor running as root (no user in config file)
|
||||
@ -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 镜像
|
||||
准备好需要的 jdk、tomcat 等软件放到 home 目录下面,启动一个容器
|
||||
## 創建 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
|
||||
@ -18,19 +18,19 @@ command=/usr/sbin/sshd -D
|
||||
docker commit ac6474aeb31d tomcat
|
||||
```
|
||||
|
||||
新建 tomcat 文件夹,新建 Dockerfile。
|
||||
新建 tomcat 文件夾,新建 Dockerfile。
|
||||
```
|
||||
FROM mk_tomcat
|
||||
EXPOSE 22 8080
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
```
|
||||
根据 Dockerfile 创建镜像。
|
||||
根據 Dockerfile 創建鏡像。
|
||||
```
|
||||
docker build tomcat tomcat
|
||||
```
|
||||
### 安装 weblogic 镜像
|
||||
### 安裝 weblogic 鏡像
|
||||
|
||||
步骤和 tomcat 基本一致,这里贴一下配置文件
|
||||
步驟和 tomcat 基本一致,這裏貼一下配置文件
|
||||
```
|
||||
supervisor.conf
|
||||
[supervisord]
|
||||
@ -48,34 +48,34 @@ EXPOSE 22 7001
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
```
|
||||
|
||||
### tomcat/weblogic 镜像的使用
|
||||
#### 存储的使用
|
||||
在启动的时候,使用 `-v` 参数
|
||||
### tomcat/weblogic 鏡像的使用
|
||||
#### 存儲的使用
|
||||
在啟動的時候,使用 `-v` 參數
|
||||
|
||||
-v, --volume=[] Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)
|
||||
|
||||
将本地磁盘映射到容器内部,它在主机和容器之间是实时变化的,所以我们更新程序、上传代码只需要更新物理主机的目录就可以了
|
||||
將本地磁盤映射到容器內部,它在主機和容器之間是實時變化的,所以我們更新程序、上傳代碼只需要更新物理主機的目錄就可以了
|
||||
|
||||
#### tomcat 和 weblogic 集群的实现
|
||||
tomcat 只要开启多个容器即可
|
||||
#### tomcat 和 weblogic 集群的實現
|
||||
tomcat 只要開啟多個容器即可
|
||||
```
|
||||
docker run -d -v -p 204:22 -p 7003:8080 -v /home/data:/opt/data --name tm1 tomcat /usr/bin/supervisord
|
||||
docker run -d -v -p 205:22 -p 7004:8080 -v /home/data:/opt/data --name tm2 tomcat /usr/bin/supervisord
|
||||
docker run -d -v -p 206:22 -p 7005:8080 -v /home/data:/opt/data --name tm3 tomcat /usr/bin/supervisord
|
||||
```
|
||||
|
||||
这里说一下 weblogic 的配置,大家知道 weblogic 有一个域的概念。如果要使用常规的 administrator +node 的方式部署,就需要在 supervisord 中分别写出 administartor server 和 node server 的启动脚本,这样做的优点是:
|
||||
這裏說一下 weblogic 的配置,大家知道 weblogic 有一個域的概念。如果要使用常規的 administrator +node 的方式部署,就需要在 supervisord 中分別寫出 administartor server 和 node server 的啟動腳本,這樣做的優點是:
|
||||
* 可以使用 weblogic 的集群,同步等概念
|
||||
* 部署一个集群应用程序,只需要安装一次应用到集群上即可
|
||||
* 部署一個集群應用程序,只需要安裝一次應用到集群上即可
|
||||
|
||||
缺点是:
|
||||
* Docker 配置复杂了
|
||||
* 没办法自动扩展集群的计算容量,如需添加节点,需要在 administrator 上先创建节点,然后再配置新的容器 supervisor 启动脚本,然后再启动容器
|
||||
另外种方法是将所有的程序都安装在 adminiserver 上面,需要扩展的时候,启动多个节点即可,它的优点和缺点和上一种方法恰恰相反。(建议使用这种方式来部署开发和测试环境)
|
||||
缺點是:
|
||||
* Docker 配置復雜了
|
||||
* 沒辦法自動擴展集群的計算容量,如需添加節點,需要在 administrator 上先創建節點,然後再配置新的容器 supervisor 啟動腳本,然後再啟動容器
|
||||
另外種方法是將所有的程序都安裝在 adminiserver 上面,需要擴展的時候,啟動多個節點即可,它的優點和缺點和上一種方法恰恰相反。(建議使用這種方式來部署開發和測試環境)
|
||||
```
|
||||
docker run -d -v -p 204:22 -p 7001:7001 -v /home/data:/opt/data --name node1 weblogic /usr/bin/supervisord
|
||||
docker run -d -v -p 205:22 -p 7002:7001 -v /home/data:/opt/data --name node2 weblogic /usr/bin/supervisord
|
||||
docker run -d -v -p 206:22 -p 7003:7001 -v /home/data:/opt/data --name node3 weblogic /usr/bin/supervisord
|
||||
```
|
||||
|
||||
这样在前端使用 nginx 来做负载均衡就可以完成配置了
|
||||
這樣在前端使用 nginx 來做負載均衡就可以完成配置了
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Docker 容器
|
||||
容器是 Docker 又一核心概念。
|
||||
|
||||
简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。
|
||||
簡單的說,容器是獨立運行的一個或一組應用,以及它們的運行態環境。對應的,虛擬機可以理解為模擬運行的一整套作業系統(提供了運行態環境和其他系統環境)和跑在上面的應用。
|
||||
|
||||
本章将具体介绍如何来管理一个容器,包括创建、启动和停止等。
|
||||
本章將具體介紹如何來管理一個容器,包括創建、啟動和停止等。
|
||||
|
@ -1,20 +1,20 @@
|
||||
##守护态运行
|
||||
##守護態運行
|
||||
|
||||
更多的时候,需要让 Docker 容器在后台以守护态(Daemonized)形式运行。此时,可以通过添加 `-d` 参数来实现。
|
||||
更多的時候,需要讓 Docker 容器在後臺以守護態(Daemonized)形式運行。此時,可以通過添加 `-d` 參數來實現。
|
||||
|
||||
例如下面的命令会在后台运行容器。
|
||||
例如下面的命令會在後臺運行容器。
|
||||
```
|
||||
$ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
|
||||
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
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 进入容器
|
||||
在使用 `-d` 参数时,容器启动后会进入后台。
|
||||
某些时候需要进入容器进行操作,有很多种方法,包括使用 `docker attach` 命令或 `nsenter` 工具等。
|
||||
## 進入容器
|
||||
在使用 `-d` 參數時,容器啟動後會進入後臺。
|
||||
某些時候需要進入容器進行操作,有很多種方法,包括使用 `docker attach` 命令或 `nsenter` 工具等。
|
||||
### attach 命令
|
||||
`docker attach` 是Docker自带的命令。下面示例如何使用该命令。
|
||||
`docker attach` 是Docker自帶的命令。下面示例如何使用該命令。
|
||||
```
|
||||
$ sudo docker run -idt ubuntu
|
||||
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
|
||||
@ -12,12 +12,12 @@ CONTAINER ID IMAGE COMMAND CREATED
|
||||
$sudo docker attach nostalgic_hypatia
|
||||
root@243c32535da7:/#
|
||||
```
|
||||
但是使用 `attach` 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。
|
||||
但是使用 `attach` 命令有時候並不方便。當多個窗口同時 attach 到同一個容器的時候,所有窗口都會同步顯示。當某個窗口因命令阻塞時,其他窗口也無法執行操作了。
|
||||
|
||||
### nsenter 命令
|
||||
#### 安装
|
||||
`nsenter` 工具在 util-linux 包2.23版本后包含。
|
||||
如果系统中 util-linux 包没有该命令,可以按照下面的方法从源码安装。
|
||||
#### 安裝
|
||||
`nsenter` 工具在 util-linux 包2.23版本後包含。
|
||||
如果系統中 util-linux 包沒有該命令,可以按照下面的方法從源碼安裝。
|
||||
```
|
||||
$ cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
|
||||
$ ./configure --without-ncurses
|
||||
@ -25,23 +25,23 @@ $ make nsenter && sudo cp nsenter /usr/local/bin
|
||||
```
|
||||
|
||||
#### 使用
|
||||
`nsenter` 可以访问另一个进程的名字空间。nsenter 要正常工作需要有 root 权限。
|
||||
很不幸,Ubuntu 14.4 仍然使用的是 util-linux 2.20。安装最新版本的 util-linux(2.24)版,请按照以下步骤:
|
||||
`nsenter` 可以訪問另一個進程的名字空間。nsenter 要正常工作需要有 root 權限。
|
||||
很不幸,Ubuntu 14.4 仍然使用的是 util-linux 2.20。安裝最新版本的 util-linux(2.24)版,請按照以下步驟:
|
||||
```
|
||||
$ wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz; tar xzvf util-linux-2.24.tar.gz
|
||||
$ 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
|
||||
```
|
||||
下面给出一个完整的例子。
|
||||
下面給出一個完整的例子。
|
||||
```
|
||||
$ sudo docker run -idt ubuntu
|
||||
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
|
||||
@ -53,13 +53,13 @@ $ PID=$(docker-pid 243c32535da7)
|
||||
$ sudo nsenter --target 10981 --mount --uts --ipc --net --pid
|
||||
root@243c32535da7:/#
|
||||
```
|
||||
更简单的,建议大家下载
|
||||
[.bashrc_docker](https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker),并将内容放到 .bashrc 中。
|
||||
更簡單的,建議大家下載
|
||||
[.bashrc_docker](https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker),並將內容放到 .bashrc 中。
|
||||
```
|
||||
$ wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker;
|
||||
$ echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc; source ~/.bashrc
|
||||
```
|
||||
这个文件中定义了很多方便使用 Docker 的命令,例如 `docker-pid` 可以获取某个容器的 PID;而 `docker-enter` 可以进入容器或直接在容器内执行命令。
|
||||
這個文件中定義了很多方便使用 Docker 的命令,例如 `docker-pid` 可以獲取某個容器的 PID;而 `docker-enter` 可以進入容器或直接在容器內執行命令。
|
||||
```
|
||||
$ echo $(docker-pid <container>)
|
||||
$ docker-enter <container> ls
|
||||
|
@ -1,28 +1,28 @@
|
||||
##导出和导入容器
|
||||
##導出和導入容器
|
||||
|
||||
###导出容器
|
||||
如果要导出本地某个容器,可以使用 `docker export` 命令。
|
||||
###導出容器
|
||||
如果要導出本地某個容器,可以使用 `docker export` 命令。
|
||||
```
|
||||
$ sudo docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7691a814370e ubuntu:14.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test
|
||||
$ sudo docker export 7691a814370e > ubuntu.tar
|
||||
```
|
||||
这样将导出容器快照到本地文件。
|
||||
這樣將導出容器快照到本地文件。
|
||||
|
||||
###导入容器快照
|
||||
可以使用 `docker import` 从容器快照文件中再导入为镜像,例如
|
||||
###導入容器快照
|
||||
可以使用 `docker import` 從容器快照文件中再導入為鏡像,例如
|
||||
```
|
||||
$ cat ubuntu.tar | sudo docker import - test/buntu:v1.0
|
||||
$ 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` 來導入一個容器快照到本地鏡像庫。這兩者的區別在於容器快照文件將丟棄所有的歷史記錄和元數據信息(即僅保存容器當時的快照狀態),而鏡像存儲文件將保存完整記錄,體積也要大。此外,從容器快照文件導入時可以重新指定標簽等元數據信息。
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
##删除容器
|
||||
可以使用 `docker rm` 来删除一个处于终止状态的容器。
|
||||
##刪除容器
|
||||
可以使用 `docker rm` 來刪除一個處於終止狀態的容器。
|
||||
例如
|
||||
```
|
||||
$sudo docker rm trusting_newton
|
||||
trusting_newton
|
||||
```
|
||||
如果要删除一个运行中的容器,可以添加 `-f` 参数。Docker 会发送 `SIGKILL` 信号给容器。
|
||||
如果要刪除一個運行中的容器,可以添加 `-f` 參數。Docker 會發送 `SIGKILL` 信號給容器。
|
||||
|
||||
|
@ -1,26 +1,26 @@
|
||||
##启动容器
|
||||
启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容器重新启动。
|
||||
##啟動容器
|
||||
啟動容器有兩種方式,一種是基於鏡像新建一個容器並啟動,另外一個是將在終止狀態(stopped)的容器重新啟動。
|
||||
|
||||
因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器。
|
||||
因為 Docker 的容器實在太輕量級了,很多時候用戶都是隨時刪除和新創建容器。
|
||||
|
||||
###新建并启动
|
||||
所需要的命令主要为 `docker run`。
|
||||
###新建並啟動
|
||||
所需要的命令主要為 `docker run`。
|
||||
|
||||
例如,下面的命令输出一个 “Hello World”,之后终止容器。
|
||||
例如,下面的命令輸出一個 “Hello World”,之後終止容器。
|
||||
```
|
||||
$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
|
||||
Hello world
|
||||
```
|
||||
这跟在本地直接执行 `/bin/echo '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` 则让容器的标准输入保持打开。
|
||||
其中,`-t` 選項讓Docker分配一個偽終端(pseudo-tty)並綁定到容器的標準輸入上, `-i` 則讓容器的標準輸入保持打開。
|
||||
|
||||
在交互模式下,用户可以通过所创建的终端来输入命令,例如
|
||||
在交互模式下,用戶可以通過所創建的終端來輸入命令,例如
|
||||
```
|
||||
root@af8bae53bdd3:/# pwd
|
||||
/
|
||||
@ -28,24 +28,24 @@ 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 地址给容器
|
||||
* 执行用户指定的应用程序
|
||||
* 执行完毕后容器被终止
|
||||
* 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
|
||||
* 利用鏡像創建並啟動一個容器
|
||||
* 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
|
||||
* 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
|
||||
* 從地址池配置一個 ip 地址給容器
|
||||
* 執行用戶指定的應用程序
|
||||
* 執行完畢後容器被終止
|
||||
|
||||
###启动已终止容器
|
||||
可以利用 `docker start` 命令,直接将一个已经终止的容器启动运行。
|
||||
###啟動已終止容器
|
||||
可以利用 `docker start` 命令,直接將一個已經終止的容器啟動運行。
|
||||
|
||||
容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。可以在伪终端中利用 `ps` 或 `top` 来查看进程信息。
|
||||
容器的核心為所執行的應用程序,所需要的資源都是應用程序運行所必需的。除此之外,並沒有其它的資源。可以在偽終端中利用 `ps` 或 `top` 來查看進程信息。
|
||||
```
|
||||
root@ba267838cc1b:/# ps
|
||||
PID TTY TIME CMD
|
||||
1 ? 00:00:00 bash
|
||||
11 ? 00:00:00 ps
|
||||
```
|
||||
可见,容器中仅运行了指定的 bash 应用。这种特点使得 Docker 对资源的利用率极高,是货真价实的轻量级虚拟化。
|
||||
可見,容器中僅運行了指定的 bash 應用。這種特點使得 Docker 對資源的利用率極高,是貨真價實的輕量級虛擬化。
|
||||
|
@ -1,10 +1,10 @@
|
||||
##终止容器
|
||||
可以使用 `docker stop` 来终止一个运行中的容器。
|
||||
##終止容器
|
||||
可以使用 `docker stop` 來終止一個運行中的容器。
|
||||
|
||||
此外,当Docker容器中指定的应用终结时,容器也自动终止。
|
||||
例如对于上一章节中只启动了一个终端的容器,用户通过 `exit` 命令或 `Ctrl+d` 来退出终端时,所创建的容器立刻终止。
|
||||
此外,當Docker容器中指定的應用終結時,容器也自動終止。
|
||||
例如對於上一章節中只啟動了一個終端的容器,用戶通過 `exit` 命令或 `Ctrl+d` 來退出終端時,所創建的容器立刻終止。
|
||||
|
||||
终止状态的容器可以用 `docker ps -a` 命令看到。例如
|
||||
終止狀態的容器可以用 `docker ps -a` 命令看到。例如
|
||||
```
|
||||
sudo docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
@ -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` 命令会将一个运行态的容器终止,然后再重新启动它。
|
||||
此外,`docker restart` 命令會將一個運行態的容器終止,然後再重新啟動它。
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Docker 数据管理
|
||||
这一章介绍如何在 Docker 内部以及容器之间管理数据,在容器中管理数据主要有两种方式:
|
||||
* 数据卷(Data volumes)
|
||||
* 数据卷容器(Data volume containers)
|
||||
# Docker 數據管理
|
||||
這一章介紹如何在 Docker 內部以及容器之間管理數據,在容器中管理數據主要有兩種方式:
|
||||
* 數據卷(Data volumes)
|
||||
* 數據卷容器(Data volume containers)
|
||||
|
@ -1,23 +1,23 @@
|
||||
## 数据卷容器
|
||||
如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。
|
||||
## 數據卷容器
|
||||
如果你有一些持續更新的數據需要在容器之間共享,最好創建數據卷容器。
|
||||
|
||||
数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
|
||||
數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。
|
||||
|
||||
首先,创建一个命名的数据卷容器 dbdata:
|
||||
首先,創建一個命名的數據卷容器 dbdata:
|
||||
```
|
||||
$ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
|
||||
```
|
||||
然后,在其他容器中使用 `--volumes-from` 来挂载 dbdata 容器中的数据卷。
|
||||
然後,在其他容器中使用 `--volumes-from` 來掛載 dbdata 容器中的數據卷。
|
||||
```
|
||||
$ sudo docker run -d --volumes-from dbdata --name db1 training/postgres
|
||||
$ sudo docker run -d --volumes-from dbdata --name db2 training/postgres
|
||||
```
|
||||
还可以使用多个 `--volumes-from` 参数来从多个容器挂载多个数据卷。
|
||||
也可以从其他已经挂载了容器卷的容器来挂载数据卷。
|
||||
還可以使用多個 `--volumes-from` 參數來從多個容器掛載多個數據卷。
|
||||
也可以從其他已經掛載了容器卷的容器來掛載數據卷。
|
||||
```
|
||||
$ sudo docker run -d --name db3 --volumes-from db1 training/postgres
|
||||
```
|
||||
*注意:使用 `--volumes-from` 参数所挂载数据卷的容器自己并不需要保持在运行状态。
|
||||
*註意:使用 `--volumes-from` 參數所掛載數據卷的容器自己並不需要保持在運行狀態。
|
||||
|
||||
如果删除了挂载的容器(包括 dbdata、db1 和 db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时使用 `docker rm -v` 命令来指定同时删除关联的容器。
|
||||
这可以让用户在容器之间升级和移动数据卷。具体的操作将在下一节中进行讲解。
|
||||
如果刪除了掛載的容器(包括 dbdata、db1 和 db2),數據卷並不會被自動刪除。如果要刪除一個數據卷,必須在刪除最後一個還掛載著它的容器時使用 `docker rm -v` 命令來指定同時刪除關聯的容器。
|
||||
這可以讓用戶在容器之間升級和移動數據卷。具體的操作將在下一節中進行講解。
|
||||
|
@ -1,20 +1,20 @@
|
||||
## 利用数据卷容器来备份、恢复、迁移数据卷
|
||||
可以利用数据卷对其中的数据进行进行备份、恢复和迁移。
|
||||
## 利用數據卷容器來備份、恢復、遷移數據卷
|
||||
可以利用數據卷對其中的數據進行進行備份、恢復和遷移。
|
||||
|
||||
### 备份
|
||||
首先使用 `--volumes-from` 标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:
|
||||
### 備份
|
||||
首先使用 `--volumes-from` 標記來創建一個加載 dbdata 容器卷的容器,並從本地主機掛載當前到容器的 /backup 目錄。命令如下:
|
||||
```
|
||||
$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
|
||||
```
|
||||
容器启动后,使用了 `tar` 命令来将 dbdata 卷备份为本地的 `/backup/backup.tar`。
|
||||
容器啟動後,使用了 `tar` 命令來將 dbdata 卷備份為本地的 `/backup/backup.tar`。
|
||||
|
||||
|
||||
### 恢复
|
||||
如果要恢复数据到一个容器,首先创建一个带有数据卷的容器 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
|
||||
|
@ -1,45 +1,45 @@
|
||||
## 数据卷
|
||||
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
|
||||
* 数据卷可以在容器之间共享和重用
|
||||
* 对数据卷的修改会立马生效
|
||||
* 对数据卷的更新,不会影响镜像
|
||||
* 卷会一直存在,直到没有容器使用
|
||||
## 數據卷
|
||||
數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:
|
||||
* 數據卷可以在容器之間共享和重用
|
||||
* 對數據卷的修改會立馬生效
|
||||
* 對數據卷的更新,不會影響鏡像
|
||||
* 卷會一直存在,直到沒有容器使用
|
||||
|
||||
*数据卷的使用,类似于 Linux 下对目录或文件进行 mount。
|
||||
*數據卷的使用,類似於 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` 标记也可以指定挂载一个本地主机的目录到容器中去。
|
||||
### 掛載一個主機目錄作為數據卷
|
||||
使用 `-v` 標記也可以指定掛載一個本地主機的目錄到容器中去。
|
||||
```
|
||||
$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
|
||||
```
|
||||
上面的命令加载主机的 `/src/webapp` 目录到容器的 `/opt/webapp`
|
||||
目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它。
|
||||
上面的命令加載主機的 `/src/webapp` 目錄到容器的 `/opt/webapp`
|
||||
目錄。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你創建它。
|
||||
|
||||
*注意:Dockerfile 中不支持这种用法,这是因为 Dockerfile 是为了移植和分享用的。然而,不同操作系统的路径格式不一样,所以目前还不能支持。
|
||||
*註意:Dockerfile 中不支持這種用法,這是因為 Dockerfile 是為了移植和分享用的。然而,不同作業系統的路徑格式不一樣,所以目前還不能支持。
|
||||
|
||||
Docker 挂载数据卷的默认权限是读写,用户也可以通过 `:ro` 指定为只读。
|
||||
Docker 掛載數據卷的默認權限是讀寫,用戶也可以通過 `:ro` 指定為只讀。
|
||||
```
|
||||
$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:ro
|
||||
training/webapp python app.py
|
||||
```
|
||||
加了 `:ro` 之后,就挂载为只读了。
|
||||
加了 `:ro` 之後,就掛載為只讀了。
|
||||
|
||||
### 挂载一个本地主机文件作为数据卷
|
||||
`-v` 标记也可以从主机挂载单个文件到容器中
|
||||
### 掛載一個本地主機文件作為數據卷
|
||||
`-v` 標記也可以從主機掛載單個文件到容器中
|
||||
```
|
||||
$ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
|
||||
```
|
||||
这样就可以记录在容器输入过的命令了。
|
||||
這樣就可以記錄在容器輸入過的命令了。
|
||||
|
||||
*注意:如果直接挂载一个文件,很多文件编辑工具,包括 `vi` 或者 `sed --in-place`,可能会造成文件 inode 的改变,从 Docker 1.1
|
||||
.0起,这会导致报错误信息。所以最简单的办法就直接挂载文件的父目录。
|
||||
*註意:如果直接掛載一個文件,很多文件編輯工具,包括 `vi` 或者 `sed --in-place`,可能會造成文件 inode 的改變,從 Docker 1.1
|
||||
.0起,這會導致報錯誤信息。所以最簡單的辦法就直接掛載文件的父目錄。
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 基本結構
|
||||
Dockerfile 由一行行命令語句組成,並且支援以 `#` 開頭的注釋行。
|
||||
Dockerfile 由一行行命令語句組成,並且支援以 `#` 開頭的註釋行。
|
||||
|
||||
一般而言,Dockerfile 分為四部分:基礎鏡像資訊、維護者資訊、鏡像操作指令和容器啟動時執行指令。
|
||||
|
||||
|
@ -1,40 +1,40 @@
|
||||
## 指令
|
||||
指令的一般格式为 `INSTRUCTION arguments`,指令包括 `FROM`、`MAINTAINER`、`RUN` 等。
|
||||
指令的一般格式為 `INSTRUCTION arguments`,指令包括 `FROM`、`MAINTAINER`、`RUN` 等。
|
||||
|
||||
### FROM
|
||||
格式为 `FROM <image>`或`FROM <image>:<tag>`。
|
||||
格式為 `FROM <image>`或`FROM <image>:<tag>`。
|
||||
|
||||
第一条指令必须为 `FROM` 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 `FROM` 指令(每个镜像一次)。
|
||||
第一條指令必須為 `FROM` 指令。並且,如果在同一個Dockerfile中創建多個鏡像時,可以使用多個 `FROM` 指令(每個鏡像一次)。
|
||||
|
||||
### MAINTAINER
|
||||
格式为 `MAINTAINER <name>`,指定维护者信息。
|
||||
格式為 `MAINTAINER <name>`,指定維護者信息。
|
||||
|
||||
### RUN
|
||||
格式为 `RUN <command>` 或 `RUN ["executable", "param1", "param2"]`。
|
||||
格式為 `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` 指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 `\` 来换行。
|
||||
每條 `RUN` 指令將在當前鏡像基礎上執行指定命令,並提交為新的鏡像。當命令較長時可以使用 `\` 來換行。
|
||||
|
||||
### CMD
|
||||
支持三种格式
|
||||
* `CMD ["executable","param1","param2"]` 使用 `exec` 执行,推荐方式;
|
||||
* `CMD command param1 param2` 在 `/bin/sh` 中执行,提供给需要交互的应用;
|
||||
* `CMD ["param1","param2"]` 提供给 `ENTRYPOINT` 的默认参数;
|
||||
支持三種格式
|
||||
* `CMD ["executable","param1","param2"]` 使用 `exec` 執行,推薦方式;
|
||||
* `CMD command param1 param2` 在 `/bin/sh` 中執行,提供給需要交互的應用;
|
||||
* `CMD ["param1","param2"]` 提供給 `ENTRYPOINT` 的默認參數;
|
||||
|
||||
|
||||
指定启动容器时执行的命令,每个 Dockerfile 只能有一条 `CMD` 命令。如果指定了多条命令,只有最后一条会被执行。
|
||||
指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 `CMD` 命令。如果指定了多條命令,只有最後一條會被執行。
|
||||
|
||||
如果用户启动容器时候指定了运行的命令,则会覆盖掉 `CMD` 指定的命令。
|
||||
如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 `CMD` 指定的命令。
|
||||
|
||||
### EXPOSE
|
||||
格式为 `EXPOSE <port> [<port>...]`。
|
||||
格式為 `EXPOSE <port> [<port>...]`。
|
||||
|
||||
告诉 Docker 服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过 -P,Docker 主机会自动分配一个端口转发到指定的端口。
|
||||
告訴 Docker 服務端容器暴露的端口號,供互聯系統使用。在啟動容器時需要通過 -P,Docker 主機會自動分配一個端口轉發到指定的端口。
|
||||
|
||||
### ENV
|
||||
格式为 `ENV <key> <value>`。
|
||||
指定一个环境变量,会被后续 `RUN` 指令使用,并在容器运行时保持。
|
||||
格式為 `ENV <key> <value>`。
|
||||
指定一個環境變量,會被後續 `RUN` 指令使用,並在容器運行時保持。
|
||||
|
||||
例如
|
||||
```
|
||||
@ -45,59 +45,59 @@ ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
|
||||
```
|
||||
|
||||
### ADD
|
||||
格式为 `ADD <src> <dest>`。
|
||||
格式為 `ADD <src> <dest>`。
|
||||
|
||||
该命令将复制指定的 `<src>` 到容器中的 `<dest>`。
|
||||
其中 `<src>` 可以是Dockerfile所在目录的一个相对路径;也可以是一个 URL;还可以是一个 tar 文件(自动解压为目录)。
|
||||
該命令將復制指定的 `<src>` 到容器中的 `<dest>`。
|
||||
其中 `<src>` 可以是Dockerfile所在目錄的一個相對路徑;也可以是一個 URL;還可以是一個 tar 文件(自動解壓為目錄)。
|
||||
|
||||
### COPY
|
||||
格式为 `COPY <src> <dest>`。
|
||||
格式為 `COPY <src> <dest>`。
|
||||
|
||||
复制本地主机的 `<src>`(为 Dockerfile 所在目录的相对路径)到容器中的 `<dest>`。
|
||||
復制本地主機的 `<src>`(為 Dockerfile 所在目錄的相對路徑)到容器中的 `<dest>`。
|
||||
|
||||
当使用本地目录为源目录时,推荐使用 `COPY`。
|
||||
當使用本地目錄為源目錄時,推薦使用 `COPY`。
|
||||
|
||||
### ENTRYPOINT
|
||||
两种格式:
|
||||
兩種格式:
|
||||
* `ENTRYPOINT ["executable", "param1", "param2"]`
|
||||
* `ENTRYPOINT command param1 param2`(shell中执行)。
|
||||
* `ENTRYPOINT command param1 param2`(shell中執行)。
|
||||
|
||||
配置容器启动后执行的命令,并且不可被 `docker run` 提供的参数覆盖。
|
||||
配置容器啟動後執行的命令,並且不可被 `docker run` 提供的參數覆蓋。
|
||||
|
||||
每个 Dockerfile 中只能有一个 `ENTRYPOINT`,当指定多个时,只有最后一个起效。
|
||||
每個 Dockerfile 中只能有一個 `ENTRYPOINT`,當指定多個時,只有最後一個起效。
|
||||
|
||||
### VOLUME
|
||||
格式为 `VOLUME ["/data"]`。
|
||||
格式為 `VOLUME ["/data"]`。
|
||||
|
||||
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。
|
||||
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等。
|
||||
|
||||
### USER
|
||||
格式为 `USER daemon`。
|
||||
格式為 `USER daemon`。
|
||||
|
||||
指定运行容器时的用户名或 UID,后续的 `RUN` 也会使用指定用户。
|
||||
指定運行容器時的用戶名或 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`。
|
||||
格式為 `WORKDIR /path/to/workdir`。
|
||||
|
||||
为后续的 `RUN`、`CMD`、`ENTRYPOINT` 指令配置工作目录。
|
||||
為後續的 `RUN`、`CMD`、`ENTRYPOINT` 指令配置工作目錄。
|
||||
|
||||
可以使用多个 `WORKDIR` 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如
|
||||
可以使用多個 `WORKDIR` 指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。例如
|
||||
```
|
||||
WORKDIR /a
|
||||
WORKDIR b
|
||||
WORKDIR c
|
||||
RUN pwd
|
||||
```
|
||||
则最终路径为 `/a/b/c`。
|
||||
則最終路徑為 `/a/b/c`。
|
||||
|
||||
### ONBUILD
|
||||
格式为 `ONBUILD [INSTRUCTION]`。
|
||||
格式為 `ONBUILD [INSTRUCTION]`。
|
||||
|
||||
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。
|
||||
配置當所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。
|
||||
|
||||
例如,Dockerfile 使用如下的内容创建了镜像 `image-A`。
|
||||
例如,Dockerfile 使用如下的內容創建了鏡像 `image-A`。
|
||||
```
|
||||
[...]
|
||||
ONBUILD ADD . /app/src
|
||||
@ -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
|
||||
|
||||
@ -114,5 +114,5 @@ ADD . /app/src
|
||||
RUN /usr/local/bin/python-build --dir /app/src
|
||||
```
|
||||
|
||||
使用 `ONBUILD` 指令的镜像,推荐在标签中注明,例如 `ruby:1.9-onbuild`。
|
||||
使用 `ONBUILD` 指令的鏡像,推薦在標簽中註明,例如 `ruby:1.9-onbuild`。
|
||||
|
||||
|
@ -1,28 +1,28 @@
|
||||
##创建镜像
|
||||
##創建鏡像
|
||||
|
||||
创建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统创建一个。
|
||||
創建鏡像有很多方法,用戶可以從 Docker Hub 獲取已有鏡像並更新,也可以利用本地文件系統創建一個。
|
||||
|
||||
### 修改已有镜像
|
||||
先使用下载的镜像启动容器。
|
||||
### 修改已有鏡像
|
||||
先使用下載的鏡像啟動容器。
|
||||
```
|
||||
$ sudo docker run -t -i training/sinatra /bin/bash
|
||||
root@0b2616b0e5a8:/#
|
||||
```
|
||||
注意:记住容器的 ID,稍后还会用到。
|
||||
註意:記住容器的 ID,稍後還會用到。
|
||||
|
||||
在容器中添加 json 和 gem 两个应用。
|
||||
在容器中添加 json 和 gem 兩個應用。
|
||||
```
|
||||
root@0b2616b0e5a8:/# gem install json
|
||||
```
|
||||
当结束后,我们使用 exit 来退出,现在我们的容器已经被我们改变了,使用 `docker commit` 命令来提交更新后的副本。
|
||||
當結束後,我們使用 exit 來退出,現在我們的容器已經被我們改變了,使用 `docker commit` 命令來提交更新後的副本。
|
||||
```
|
||||
$ 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
|
||||
@ -30,22 +30,22 @@ training/sinatra latest 5bc342fa0b91 10 hours ago 446.7 MB
|
||||
ouruser/sinatra v2 3c59e02ddd1a 10 hours ago 446.7 MB
|
||||
ouruser/sinatra latest 5db5f8471261 10 hours ago 446.7 MB
|
||||
```
|
||||
之后,可以使用新的镜像来启动容器
|
||||
之後,可以使用新的鏡像來啟動容器
|
||||
```
|
||||
$ 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
|
||||
新建一個目錄和一個 Dockerfile
|
||||
```
|
||||
$ mkdir sinatra
|
||||
$ cd sinatra
|
||||
$ touch Dockerfile
|
||||
```
|
||||
Dockerfile 中每一条指令都创建镜像的一层,例如:
|
||||
Dockerfile 中每一條指令都創建鏡像的一層,例如:
|
||||
```
|
||||
# This is a comment
|
||||
FROM ubuntu:14.04
|
||||
@ -54,13 +54,13 @@ RUN apt-get -qq update
|
||||
RUN apt-get -qqy install ruby ruby-dev
|
||||
RUN gem install sinatra
|
||||
```
|
||||
Dockerfile 基本的语法是
|
||||
* 使用`#`来注释
|
||||
* `FROM` 指令告诉 Docker 使用哪个镜像作为基础
|
||||
* 接着是维护者的信息
|
||||
* `RUN`开头的指令会在创建中运行,比如安装一个软件包,在这里使用 apt-get 来安装了一些软件
|
||||
Dockerfile 基本的語法是
|
||||
* 使用`#`來註釋
|
||||
* `FROM` 指令告訴 Docker 使用哪個鏡像作為基礎
|
||||
* 接著是維護者的信息
|
||||
* `RUN`開頭的指令會在創建中運行,比如安裝一個軟件包,在這裏使用 apt-get 來安裝了一些軟件
|
||||
|
||||
编写完成 Dockerfile 后可以使用 `docker build` 来生成镜像。
|
||||
編寫完成 Dockerfile 後可以使用 `docker build` 來生成鏡像。
|
||||
|
||||
```
|
||||
$ sudo docker build -t="ouruser/sinatra:v2" .
|
||||
@ -96,15 +96,15 @@ Successfully installed sinatra-1.4.5
|
||||
Removing intermediate container 5e9d0065c1f7
|
||||
Successfully built 324104cde6ad
|
||||
```
|
||||
其中 `-t` 标记来添加 tag,指定新的镜像的用户信息。
|
||||
“.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径。
|
||||
其中 `-t` 標記來添加 tag,指定新的鏡像的用戶信息。
|
||||
“.” 是 Dockerfile 所在的路徑(當前目錄),也可以替換為一個具體的 Dockerfile 的路徑。
|
||||
|
||||
可以看到 build 进程在执行操作。它要做的第一件事情就是上传这个 Dockerfile 内容,因为所有的操作都要依据 Dockerfile 来进行。
|
||||
然后,Dockfile 中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改(就跟之前介绍过的 `docker commit` 一样)。当所有的指令都执行完毕之后,返回了最终的镜像 id。所有的中间步骤所产生的容器都被删除和清理了。
|
||||
可以看到 build 進程在執行操作。它要做的第一件事情就是上傳這個 Dockerfile 內容,因為所有的操作都要依據 Dockerfile 來進行。
|
||||
然後,Dockfile 中的指令被一條一條的執行。每一步都創建了一個新的容器,在容器中執行指令並提交修改(就跟之前介紹過的 `docker commit` 一樣)。當所有的指令都執行完畢之後,返回了最終的鏡像 id。所有的中間步驟所產生的容器都被刪除和清理了。
|
||||
|
||||
*注意一个镜像不能超过 127 层
|
||||
*註意一個鏡像不能超過 127 層
|
||||
|
||||
此外,还可以利用 `ADD` 命令复制本地文件到镜像;用 `EXPOSE` 命令来向外部开放端口;用 `CMD` 命令来描述容器启动后运行的程序等。例如
|
||||
此外,還可以利用 `ADD` 命令復制本地文件到鏡像;用 `EXPOSE` 命令來向外部開放端口;用 `CMD` 命令來描述容器啟動後運行的程序等。例如
|
||||
```
|
||||
# put my local web site in myApp folder to /var/www
|
||||
ADD myApp /var/www
|
||||
@ -114,12 +114,12 @@ EXPOSE 80
|
||||
CMD ["/usr/sbin/apachectl", "-D", "FOREGROUND"]
|
||||
```
|
||||
|
||||
现在可以利用新创建的镜像来启动一个容器。
|
||||
現在可以利用新創建的鏡像來啟動一個容器。
|
||||
```
|
||||
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
|
||||
root@8196968dac35:/#
|
||||
```
|
||||
还可以用 `docker tag` 命令来修改镜像的标签。
|
||||
還可以用 `docker tag` 命令來修改鏡像的標簽。
|
||||
```
|
||||
$ sudo docker tag 5db5f8471261 ouruser/sinatra:devel
|
||||
$ sudo docker images ouruser/sinatra
|
||||
@ -129,25 +129,25 @@ ouruser/sinatra devel 5db5f8471261 11 hours ago 446.7 MB
|
||||
ouruser/sinatra v2 5db5f8471261 11 hours ago 446.7 MB
|
||||
```
|
||||
|
||||
*注:更多用法,请参考 [Dockerfile](../dockerfile/README.md) 章节。
|
||||
*註:更多用法,請參考 [Dockerfile](../dockerfile/README.md) 章節。
|
||||
|
||||
### 从本地文件系统导入
|
||||
要从本地文件系统导入一个镜像,可以使用 openvz(容器虚拟化的先锋技术)的模板来创建:
|
||||
openvz 的模板下载地址为 http://openvz.org/Download/templates/precreated。
|
||||
### 從本地文件系統導入
|
||||
要從本地文件系統導入一個鏡像,可以使用 openvz(容器虛擬化的先鋒技術)的模板來創建:
|
||||
openvz 的模板下載地址為 http://openvz.org/Download/templates/precreated。
|
||||
|
||||
比如,先下载了一个 ubuntu-14.04 的镜像,之后使用以下命令导入:
|
||||
比如,先下載了一個 ubuntu-14.04 的鏡像,之後使用以下命令導入:
|
||||
```
|
||||
sudo cat ubuntu-14.04-x86_64-minimal.tar.gz |docker import - ubuntu:14.04
|
||||
```
|
||||
然后查看新导入的镜像。
|
||||
然後查看新導入的鏡像。
|
||||
```
|
||||
docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
ubuntu 14.04 05ac7c0b9383 17 seconds ago 215.5 MB
|
||||
```
|
||||
|
||||
###上传镜像
|
||||
用户可以通过 `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 使用 [Union FS](http://en.wikipedia.org/wiki/UnionFS) 将这些不同的层结合到一个镜像中去。
|
||||
Docker 鏡像是怎麽實現增量的修改和維護的?
|
||||
每個鏡像都由很多層次構成,Docker 使用 [Union FS](http://en.wikipedia.org/wiki/UnionFS) 將這些不同的層結合到一個鏡像中去。
|
||||
|
||||
通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。
|
||||
Docker 在 AUFS 上构建的容器也是利用了类似的原理。
|
||||
通常 Union FS 有兩個用途, 一方面可以實現不借助 LVM、RAID 將多個 disk 掛到同一個目錄下,另一個更常用的就是將一個只讀的分支和一個可寫的分支聯合在一起,Live CD 正是基於此方法可以允許在鏡像不變的基礎上允許用戶在其上進行一些寫操作。
|
||||
Docker 在 AUFS 上構建的容器也是利用了類似的原理。
|
||||
|
@ -26,4 +26,4 @@ ubuntu trusty 99ec81b80c55 4 weeks ago 266 MB
|
||||
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
|
||||
```
|
||||
|
||||
如果不指定具體的標記,則預設使用 `latest` 標記信息。
|
||||
如果不指定具體的標記,則預設使用 `latest`
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
可以使用 `docker pull` 命令來從倉庫獲取所需要的鏡像。
|
||||
|
||||
下面的例子將從 Docker Hub 倉庫下載一個 Ubuntu 12.04 操作系統的鏡像。
|
||||
下面的例子將從 Docker Hub 倉庫下載一個 Ubuntu 12.04 作業系統的鏡像。
|
||||
```
|
||||
$ sudo docker pull ubuntu:12.04
|
||||
Pulling repository ubuntu
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 移除本地镜像
|
||||
如果要移除本地的镜像,可以使用 `docker rmi` 命令。注意 `docker rm` 命令是移除容器。
|
||||
## 移除本地鏡像
|
||||
如果要移除本地的鏡像,可以使用 `docker rmi` 命令。註意 `docker rm` 命令是移除容器。
|
||||
```
|
||||
$ sudo docker rmi training/sinatra
|
||||
Untagged: training/sinatra:latest
|
||||
@ -8,4 +8,4 @@ Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
|
||||
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0
|
||||
```
|
||||
|
||||
*注意:在删除镜像之前要先用 `docker rm` 删掉依赖于这个镜像的所有容器。
|
||||
*註意:在刪除鏡像之前要先用 `docker rm` 刪掉依賴於這個鏡像的所有容器。
|
||||
|
@ -1,7 +1,7 @@
|
||||
## 存出和载入镜像
|
||||
## 存出和載入鏡像
|
||||
|
||||
### 存出镜像
|
||||
如果要导出镜像到本地文件,可以使用 `docker save` 命令。
|
||||
### 存出鏡像
|
||||
如果要導出鏡像到本地文件,可以使用 `docker save` 命令。
|
||||
```
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
@ -10,8 +10,8 @@ ubuntu 14.04 c4ff7513909d 5 weeks ago
|
||||
$sudo docker save -o ubuntu_14.04.tar ubuntu:14.04
|
||||
```
|
||||
|
||||
### 载入镜像
|
||||
可以使用 `docker load` 从导出的本地文件中再导入到本地镜像库,例如
|
||||
### 載入鏡像
|
||||
可以使用 `docker load` 從導出的本地文件中再導入到本地鏡像庫,例如
|
||||
```
|
||||
$ sudo docker load --input ubuntu_14.04.tar
|
||||
```
|
||||
@ -19,4 +19,4 @@ $ sudo docker load --input ubuntu_14.04.tar
|
||||
```
|
||||
$ sudo docker load < ubuntu_14.04.tar
|
||||
```
|
||||
这将导入镜像以及其相关的元数据信息(包括标签等)。
|
||||
這將導入鏡像以及其相關的元數據信息(包括標簽等)。
|
||||
|
@ -9,7 +9,7 @@ $ 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 支持,之後通過添加源來安裝。
|
||||
|
@ -4,12 +4,12 @@ Docker 是一個開源項目,誕生於 2013 年初,最初是 dotCloud 公司
|
||||
|
||||
Docker 自開源後受到廣泛的關注和討論,以至於 dotCloud 公司後來都改名為 Docker Inc。Redhat 已經在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 產品中廣泛應用。
|
||||
|
||||
Docker 項目的目標是實現輕量級的操作系統虛擬化解決方案。
|
||||
Docker 項目的目標是實現輕量級的作業系統虛擬化解決方案。
|
||||
Docker 的基礎是 Linux 容器(LXC)等技術。
|
||||
|
||||
在 LXC 的基礎上 Docker 進行了進一步的封裝,讓用戶不需要去關心容器的管理,使得操作更為簡便。用戶操作 Docker 的容器就像操作一個快速輕量級的虛擬機一樣簡單。
|
||||
|
||||
下面的圖片比較了 Docker 和傳統虛擬化方式的不同之處,可見容器是在操作系統層面上實現虛擬化,直接使用本地主機的操作系統,而傳統方式則是在硬體層面實現。
|
||||
下面的圖片比較了 Docker 和傳統虛擬化方式的不同之處,可見容器是在作業系統層面上實現虛擬化,直接使用本地主機的作業系統,而傳統方式則是在硬體層面實現。
|
||||
|
||||
![傳統虛擬化](../_images/virtualization.png)
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
# Docker 中的网络功能介绍
|
||||
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。
|
||||
# Docker 中的網絡功能介紹
|
||||
Docker 允許通過外部訪問容器或容器互聯的方式來提供網絡服務。
|
||||
|
@ -1,70 +1,70 @@
|
||||
## 容器互联
|
||||
容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式。
|
||||
## 容器互聯
|
||||
容器的連接(linking)系統是除了端口映射外,另一種跟容器中應用交互的方式。
|
||||
|
||||
该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。
|
||||
該系統會在源和接收容器之間創建一個隧道,接收容器可以看到源容器指定的信息。
|
||||
|
||||
### 自定义容器命名
|
||||
连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。
|
||||
### 自定義容器命名
|
||||
連接系統依據容器的名稱來執行。因此,首先需要自定義一個好記的容器命名。
|
||||
|
||||
虽然当创建容器的时候,系统默认会分配一个名字。自定义命名容器有2个好处:
|
||||
* 自定义的命名,比较好记,比如一个web应用容器我们可以给它起名叫web
|
||||
* 当要连接其他容器时候,可以作为一个有用的参考点,比如连接web容器到db容器
|
||||
雖然當創建容器的時候,系統默認會分配一個名字。自定義命名容器有2個好處:
|
||||
* 自定義的命名,比較好記,比如一個web應用容器我們可以給它起名叫web
|
||||
* 當要連接其他容器時候,可以作為一個有用的參考點,比如連接web容器到db容器
|
||||
|
||||
使用 `--name` 标记可以为容器自定义命名。
|
||||
使用 `--name` 標記可以為容器自定義命名。
|
||||
```
|
||||
$ sudo docker run -d -P --name web training/webapp python app.py
|
||||
```
|
||||
|
||||
使用 `docker ps` 来验证设定的命名。
|
||||
使用 `docker ps` 來驗證設定的命名。
|
||||
```
|
||||
$ sudo docker ps -l
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
aed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0.0.0.0:49154->5000/tcp web
|
||||
```
|
||||
也可以使用 `docker inspect` 来查看容器的名字
|
||||
也可以使用 `docker inspect` 來查看容器的名字
|
||||
```
|
||||
$ 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` 参数可以让容器之间安全的进行交互。
|
||||
###容器互聯
|
||||
使用 `--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
|
||||
```
|
||||
此时,db 容器和 web 容器建立互联关系。
|
||||
此時,db 容器和 web 容器建立互聯關系。
|
||||
|
||||
`--link` 参数的格式为 `--link name:alias`,其中 `name` 是要链接的容器的名称,`alias` 是这个连接的别名。
|
||||
`--link` 參數的格式為 `--link name:alias`,其中 `name` 是要鏈接的容器的名稱,`alias` 是這個連接的別名。
|
||||
|
||||
使用 `docker ps` 来查看容器的连接
|
||||
使用 `docker ps` 來查看容器的連接
|
||||
```
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
349169744e49 training/postgres:latest su postgres -c '/usr About a minute ago Up About a minute 5432/tcp db, web/db
|
||||
aed84ee21bde training/webapp:latest python app.py 16 hours ago Up 2 minutes 0.0.0.0:49154->5000/tcp web
|
||||
```
|
||||
可以看到自定义命名的容器,db 和 web,db 容器的 names 列有 db 也有 web/db。这表示 web 容器链接到 db 容器,web 容器将被允许访问 db 容器的信息。
|
||||
可以看到自定義命名的容器,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` 文件
|
||||
|
||||
使用 `env` 命令来查看 web 容器的环境变量
|
||||
使用 `env` 命令來查看 web 容器的環境變量
|
||||
```
|
||||
$ sudo docker run --rm --name web2 --link db:db training/webapp env
|
||||
. . .
|
||||
@ -76,9 +76,9 @@ DB_PORT_5000_TCP_PORT=5432
|
||||
DB_PORT_5000_TCP_ADDR=172.17.0.5
|
||||
. . .
|
||||
```
|
||||
其中 DB_ 开头的环境变量是供 web 容器连接 db 容器使用,前缀采用大写的连接别名。
|
||||
其中 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
|
||||
@ -86,8 +86,8 @@ root@aed84ee21bde:/opt/webapp# cat /etc/hosts
|
||||
. . .
|
||||
172.17.0.5 db
|
||||
```
|
||||
这里有 2 个 hosts,第一个是 web 容器,web 容器用 id 作为他的主机名,第二个是 db 容器的 ip 和主机名。
|
||||
可以在 web 容器中安装 ping 命令来测试跟db容器的连通。
|
||||
這裏有 2 個 hosts,第一個是 web 容器,web 容器用 id 作為他的主機名,第二個是 db 容器的 ip 和主機名。
|
||||
可以在 web 容器中安裝 ping 命令來測試跟db容器的連通。
|
||||
```
|
||||
root@aed84ee21bde:/opt/webapp# apt-get install -yqq inetutils-ping
|
||||
root@aed84ee21bde:/opt/webapp# ping db
|
||||
@ -96,7 +96,7 @@ PING db (172.17.0.5): 48 data bytes
|
||||
56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms
|
||||
56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms
|
||||
```
|
||||
用 ping 来测试db容器,它会解析成 `172.17.0.5`。
|
||||
*注意:官方的 ubuntu 镜像默认没有安装 ping,需要自行安装。
|
||||
用 ping 來測試db容器,它會解析成 `172.17.0.5`。
|
||||
*註意:官方的 ubuntu 鏡像默認沒有安裝 ping,需要自行安裝。
|
||||
|
||||
用户可以链接多个子容器到父容器,比如可以链接多个 web 到 db 容器上。
|
||||
用戶可以鏈接多個子容器到父容器,比如可以鏈接多個 web 到 db 容器上。
|
||||
|
@ -1,16 +1,16 @@
|
||||
## 外部访问容器
|
||||
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 `-P` 或 `-p` 参数来指定端口映射。
|
||||
## 外部訪問容器
|
||||
容器中可以運行一些網絡應用,要讓外部也可以訪問這些應用,可以通過 `-P` 或 `-p` 參數來指定端口映射。
|
||||
|
||||
当使用 -P 标记时,Docker 会随机映射一个 `49000~49900` 的端口到内部容器开放的网络端口。
|
||||
當使用 -P 標記時,Docker 會隨機映射一個 `49000~49900` 的端口到內部容器開放的網絡端口。
|
||||
|
||||
使用 `docker ps` 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。此时访问本机的 49115 端口即可访问容器内 web 应用提供的界面。
|
||||
使用 `docker ps` 可以看到,本地主機的 49155 被映射到了容器的 5000 端口。此時訪問本機的 49115 端口即可訪問容器內 web 應用提供的界面。
|
||||
```
|
||||
$ sudo docker run -d -P training/webapp python app.py
|
||||
$ 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/
|
||||
@ -18,38 +18,38 @@ $ sudo docker logs -f nostalgic_morse
|
||||
10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -
|
||||
```
|
||||
|
||||
-p(小写的)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 `ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort`。
|
||||
-p(小寫的)則可以指定要映射的端口,並且,在一個指定端口上只可以綁定一個容器。支持的格式有 `ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort`。
|
||||
|
||||
### 映射所有接口地址
|
||||
使用 `hostPort:containerPort` 格式本地的 5000 端口映射到容器的 5000 端口,可以执行
|
||||
使用 `hostPort:containerPort` 格式本地的 5000 端口映射到容器的 5000 端口,可以執行
|
||||
```
|
||||
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
|
||||
```
|
||||
此时默认会绑定本地所有接口上的所有地址。
|
||||
此時默認會綁定本地所有接口上的所有地址。
|
||||
|
||||
### 映射到指定地址的指定端口
|
||||
可以使用 `ip:hostPort:containerPort` 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1
|
||||
可以使用 `ip:hostPort:containerPort` 格式指定映射使用一個特定地址,比如 localhost 地址 127.0.0.1
|
||||
```
|
||||
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
|
||||
```
|
||||
### 映射到指定地址的任意端口
|
||||
使用 `ip::containerPort` 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。
|
||||
使用 `ip::containerPort` 綁定 localhost 的任意端口到容器的 5000 端口,本地主機會自動分配一個端口。
|
||||
```
|
||||
$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
|
||||
```
|
||||
还可以使用 udp 标记来指定 udp 端口
|
||||
還可以使用 udp 標記來指定 udp 端口
|
||||
```
|
||||
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
|
||||
```
|
||||
### 查看映射端口配置
|
||||
使用 `docker port` 来查看当前映射的端口配置,也可以查看到绑定的地址
|
||||
使用 `docker port` 來查看當前映射的端口配置,也可以查看到綁定的地址
|
||||
```
|
||||
$ docker port nostalgic_morse 5000
|
||||
127.0.0.1:49155.
|
||||
```
|
||||
注意:
|
||||
* 容器有自己的内部网络和 ip 地址(使用 `docker inspect` 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)
|
||||
* -p 标记可以多次使用来绑定多个端口
|
||||
註意:
|
||||
* 容器有自己的內部網絡和 ip 地址(使用 `docker inspect` 可以獲取所有的變量,Docker 還可以有一個可變的網絡配置。)
|
||||
* -p 標記可以多次使用來綁定多個端口
|
||||
|
||||
例如
|
||||
```
|
||||
|
@ -1,10 +1,10 @@
|
||||
# 仓库
|
||||
# 倉庫
|
||||
|
||||
仓库(Repository)是集中存放镜像的地方。
|
||||
倉庫(Repository)是集中存放鏡像的地方。
|
||||
|
||||
一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 `dl.dockerpool.com/ubuntu` 来说,`dl.dockerpool.com` 是注册服务器地址,`ubuntu` 是仓库名。
|
||||
一個容易混淆的概念是註冊服務器(Registry)。實際上註冊服務器是管理倉庫的具體服務器,每個服務器上可以有多個倉庫,而每個倉庫下面有多個鏡像。從這方面來說,倉庫可以被認為是一個具體的項目或目錄。例如對於倉庫地址 `dl.dockerpool.com/ubuntu` 來說,`dl.dockerpool.com` 是註冊服務器地址,`ubuntu` 是倉庫名。
|
||||
|
||||
大部分时候,并不需要严格区分这两者的概念。
|
||||
大部分時候,並不需要嚴格區分這兩者的概念。
|
||||
|
||||
|
||||
|
||||
|
@ -1,28 +1,28 @@
|
||||
## 仓库配置文件
|
||||
Docker 的 Registry 利用配置文件提供了一些仓库的模板(flavor),用户可以直接使用它们来进行开发或生产部署。
|
||||
## 倉庫配置文件
|
||||
Docker 的 Registry 利用配置文件提供了一些倉庫的模板(flavor),用戶可以直接使用它們來進行開發或生產部署。
|
||||
|
||||
### 模板
|
||||
在 `config_sample.yml` 文件中,可以看到一些现成的模板段:
|
||||
* `common`:基础配置
|
||||
* `local`:存储数据到本地文件系统
|
||||
* `s3`:存储数据到 AWS S3 中
|
||||
在 `config_sample.yml` 文件中,可以看到一些現成的模板段:
|
||||
* `common`:基礎配置
|
||||
* `local`:存儲數據到本地文件系統
|
||||
* `s3`:存儲數據到 AWS S3 中
|
||||
* `dev`:使用 `local` 模板的基本配置
|
||||
* `test`:单元测试使用
|
||||
* `prod`:生产环境配置(基本上跟s3配置类似)
|
||||
* `gcs`:存储数据到 Google 的云存储
|
||||
* `swift`:存储数据到 OpenStack Swift 服务
|
||||
* `glance`:存储数据到 OpenStack Glance 服务,本地文件系统为后备
|
||||
* `glance-swift`:存储数据到 OpenStack Glance 服务,Swift 为后备
|
||||
* `elliptics`:存储数据到 Elliptics key/value 存储
|
||||
* `test`:單元測試使用
|
||||
* `prod`:生產環境配置(基本上跟s3配置類似)
|
||||
* `gcs`:存儲數據到 Google 的雲存儲
|
||||
* `swift`:存儲數據到 OpenStack Swift 服務
|
||||
* `glance`:存儲數據到 OpenStack Glance 服務,本地文件系統為後備
|
||||
* `glance-swift`:存儲數據到 OpenStack Glance 服務,Swift 為後備
|
||||
* `elliptics`:存儲數據到 Elliptics key/value 存儲
|
||||
|
||||
用户也可以添加自定义的模版段。
|
||||
用戶也可以添加自定義的模版段。
|
||||
|
||||
默认情况下使用的模板是 `dev`,要使用某个模板作为默认值,可以添加 `SETTINGS_FLAVOR` 到环境变量中,例如
|
||||
默認情況下使用的模板是 `dev`,要使用某個模板作為默認值,可以添加 `SETTINGS_FLAVOR` 到環境變量中,例如
|
||||
```
|
||||
export SETTINGS_FLAVOR=dev
|
||||
```
|
||||
|
||||
另外,配置文件中支持从环境变量中加载值,语法格式为 `_env:VARIABLENAME[:DEFAULT]`。
|
||||
另外,配置文件中支持從環境變量中加載值,語法格式為 `_env:VARIABLENAME[:DEFAULT]`。
|
||||
|
||||
### 示例配置
|
||||
```
|
||||
@ -54,4 +54,4 @@ test:
|
||||
storage_path: /tmp/tmpdockertmp
|
||||
```
|
||||
|
||||
### 选项
|
||||
### 選項
|
||||
|
@ -1,14 +1,14 @@
|
||||
## 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 为关键词进行搜索:
|
||||
例如以 centos 為關鍵詞進行搜索:
|
||||
```
|
||||
$ sudo docker search centos
|
||||
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
||||
@ -19,16 +19,16 @@ 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 镜像到本地。
|
||||
下載官方 centos 鏡像到本地。
|
||||
```
|
||||
$ sudo docker pull centos
|
||||
Pulling repository 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 中 [配置一个自动创建](https://registry.hub.docker.com/builds/add/);
|
||||
* 选取一个目标网站中的项目(需要含 Dockerfile)和分支;
|
||||
* 指定 Dockerfile 的位置,并提交创建。
|
||||
要配置自動創建,包括如下的步驟:
|
||||
* 創建並登陸 Docker Hub,以及目標網站;
|
||||
* 在目標網站中連接帳戶到 Docker Hub;
|
||||
* 在 Docker Hub 中 [配置一個自動創建](https://registry.hub.docker.com/builds/add/);
|
||||
* 選取一個目標網站中的項目(需要含 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` 是官方提供的工具,可以用於構建私有的鏡像倉庫。
|
||||
### 安裝運行 docker-registry
|
||||
#### 容器運行
|
||||
在安裝了 Docker 後,可以通過獲取官方 registry 鏡像來運行。
|
||||
```
|
||||
$ sudo docker run -d -p 5000:5000 registry
|
||||
```
|
||||
这将使用官方的 registry 镜像来启动本地的私有仓库。
|
||||
用户可以通过指定参数来配置私有仓库位置,例如配置镜像存储到 Amazon S3 服务。
|
||||
這將使用官方的 registry 鏡像來啟動本地的私有倉庫。
|
||||
用戶可以通過指定參數來配置私有倉庫位置,例如配置鏡像存儲到 Amazon S3 服務。
|
||||
```
|
||||
$ sudo docker run \
|
||||
-e SETTINGS_FLAVOR=s3 \
|
||||
@ -24,18 +24,18 @@ $ sudo docker run \
|
||||
-p 5000:5000 \
|
||||
registry
|
||||
````
|
||||
此外,还可以指定本地路径(如 `/home/user/registry-conf` )下的配置文件。
|
||||
此外,還可以指定本地路徑(如 `/home/user/registry-conf` )下的配置文件。
|
||||
```
|
||||
$ 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` 参数来将镜像文件存放在本地的指定路径。
|
||||
例如下面的例子将上传的镜像放到 `/opt/data/registry` 目录。
|
||||
默認情況下,倉庫會被創建在容器的 `/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
|
||||
@ -47,18 +47,18 @@ $ sudo yum install -y python-devel libevent-devel python-pip gcc xz-devel
|
||||
$ sudo python-pip install docker-registry
|
||||
```
|
||||
|
||||
也可以从 [docker-registry](https://github.com/docker/docker-registry) 项目下载源码进行安装。
|
||||
也可以從 [docker-registry](https://github.com/docker/docker-registry) 項目下載源碼進行安裝。
|
||||
```
|
||||
$ sudo apt-get install build-essential python-dev libevent-dev python-pip libssl-dev liblzma-dev libffi-dev
|
||||
$ git clone https://github.com/docker/docker-registry.git
|
||||
$ cd docker-registry
|
||||
$ sudo python setup.py install
|
||||
```
|
||||
然后修改配置文件,主要修改 dev 模板段的 `storage_path` 到本地的存储仓库的路径。
|
||||
然後修改配置文件,主要修改 dev 模板段的 `storage_path` 到本地的存儲倉庫的路徑。
|
||||
```
|
||||
$ cp config/config_sample.yml config/config.yml
|
||||
```
|
||||
之后启动 Web 服务。
|
||||
之後啟動 Web 服務。
|
||||
```
|
||||
$ sudo gunicorn -c contrib/gunicorn.py docker_registry.wsgi:application
|
||||
```
|
||||
@ -66,14 +66,14 @@ $ sudo gunicorn -c contrib/gunicorn.py docker_registry.wsgi:application
|
||||
```
|
||||
$ sudo gunicorn --access-logfile - --error-logfile - -k gevent -b 0.0.0.0:5000 -w 4 --max-requests 100 docker_registry.wsgi:application
|
||||
```
|
||||
此时使用访问本地的 5000 端口,看到输出 docker-registry 的版本信息说明运行成功。
|
||||
此時使用訪問本地的 5000 端口,看到輸出 docker-registry 的版本信息說明運行成功。
|
||||
|
||||
*注:`config/config_sample.yml` 文件是示例配置文件。
|
||||
*註:`config/config_sample.yml` 文件是示例配置文件。
|
||||
|
||||
###在私有仓库上传、下载、搜索镜像
|
||||
创建好私有仓库之后,就可以使用 `docker tag` 来标记一个镜像,然后推送它到仓库,别的机器上就可以下载下来了。例如私有仓库地址为 `192.168.7.26:5000`。
|
||||
###在私有倉庫上傳、下載、搜索鏡像
|
||||
創建好私有倉庫之後,就可以使用 `docker tag` 來標記一個鏡像,然後推送它到倉庫,別的機器上就可以下載下來了。例如私有倉庫地址為 `192.168.7.26:5000`。
|
||||
|
||||
先在本机查看已有的镜像。
|
||||
先在本機查看已有的鏡像。
|
||||
```
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
@ -81,7 +81,7 @@ ubuntu latest ba5877dc9bec 6 week
|
||||
ubuntu 14.04 ba5877dc9bec 6 weeks ago 192.7 MB
|
||||
```
|
||||
|
||||
使用`docker tag` 将 `ba58` 这个镜像标记为 `192.168.7.26:5000/test`(格式为 `docker tag IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]`)。
|
||||
使用`docker tag` 將 `ba58` 這個鏡像標記為 `192.168.7.26:5000/test`(格式為 `docker tag IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]`)。
|
||||
```
|
||||
$ sudo docker tag ba58 192.168.7.26:5000/test
|
||||
root ~ # docker images
|
||||
@ -90,7 +90,7 @@ ubuntu 14.04 ba5877dc9bec 6 week
|
||||
ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB
|
||||
192.168.7.26:5000/test latest ba5877dc9bec 6 weeks ago 192.7 MB
|
||||
```
|
||||
使用 `docker push` 上传标记的镜像。
|
||||
使用 `docker push` 上傳標記的鏡像。
|
||||
```
|
||||
$ sudo docker push 192.168.7.26:5000/test
|
||||
The push refers to a repository [192.168.7.26:5000/test] (len: 1)
|
||||
@ -104,14 +104,14 @@ Image 2318d26665ef already pushed, skipping
|
||||
Image ba5877dc9bec already pushed, skipping
|
||||
Pushing tag for rev [ba5877dc9bec] on {http://192.168.7.26:5000/v1/repositories/test/tags/latest}
|
||||
```
|
||||
用 curl 查看仓库中的镜像。
|
||||
用 curl 查看倉庫中的鏡像。
|
||||
```
|
||||
$ curl http://192.168.7.26:5000/v1/search
|
||||
{"num_results": 7, "query": "", "results": [{"description": "", "name": "library/miaxis_j2ee"}, {"description": "", "name": "library/tomcat"}, {"description": "", "name": "library/ubuntu"}, {"description": "", "name": "library/ubuntu_office"}, {"description": "", "name": "library/desktop_ubu"}, {"description": "", "name": "dockerfile/ubuntu"}, {"description": "", "name": "library/test"}]}
|
||||
```
|
||||
这里可以看到 `{"description": "", "name": "library/test"}`,表明镜像已经被成功上传了。
|
||||
這裏可以看到 `{"description": "", "name": "library/test"}`,表明鏡像已經被成功上傳了。
|
||||
|
||||
现在可以到另外一台机器去下载这个镜像。
|
||||
現在可以到另外一臺機器去下載這個鏡像。
|
||||
```
|
||||
$ sudo docker pull 192.168.7.26:5000/test
|
||||
Pulling repository 192.168.7.26:5000/test
|
||||
@ -126,7 +126,7 @@ REPOSITORY TAG IMAGE ID CREAT
|
||||
192.168.7.26:5000/test latest ba5877dc9bec 6 weeks ago 192.7 MB
|
||||
```
|
||||
|
||||
可以使用 [这个脚本](https://github.com/yeasy/docker_practice/raw/master/_local/push_images.sh) 批量上传本地的镜像到注册服务器中,默认是本地注册服务器 `127.0.0.1:5000`。例如:
|
||||
可以使用 [這個腳本](https://github.com/yeasy/docker_practice/raw/master/_local/push_images.sh) 批量上傳本地的鏡像到註冊服務器中,默認是本地註冊服務器 `127.0.0.1:5000`。例如:
|
||||
```
|
||||
$ wget https://github.com/yeasy/docker_practice/raw/master/_local/push_images.sh; sudo chmod a+x push_images.sh
|
||||
$ ./push_images.sh ubuntu:latest centos:centos7
|
||||
|
@ -1,5 +1,5 @@
|
||||
# 安全
|
||||
评估 Docker 的安全性时,主要考虑三个方面:
|
||||
* 由内核的名字空间和控制组机制提供的容器内在安全
|
||||
* Docker程序(特别是服务端)本身的抗攻击性
|
||||
* 内核安全性的加强机制对容器安全性的影响
|
||||
評估 Docker 的安全性時,主要考慮三個方面:
|
||||
* 由內核的名字空間和控制組機制提供的容器內在安全
|
||||
* Docker程序(特別是服務端)本身的抗攻擊性
|
||||
* 內核安全性的加強機制對容器安全性的影響
|
||||
|
@ -1,8 +1,8 @@
|
||||
## 控制组
|
||||
控制组是 Linux 容器机制的另外一个关键组件,负责实现资源的审计和限制。
|
||||
## 控制組
|
||||
控制組是 Linux 容器機制的另外一個關鍵組件,負責實現資源的審計和限制。
|
||||
|
||||
它提供了很多有用的特性;以及确保各个容器可以公平地分享主机的内存、CPU、磁盘 IO 等资源;当然,更重要的是,控制组确保了当容器内的资源使用产生压力时不会连累主机系统。
|
||||
它提供了很多有用的特性;以及確保各個容器可以公平地分享主機的內存、CPU、磁盤 IO 等資源;當然,更重要的是,控制組確保了當容器內的資源使用產生壓力時不會連累主機系統。
|
||||
|
||||
尽管控制组不负责隔离容器之间相互访问、处理数据和进程,它在防止拒绝服务(DDOS)攻击方面是必不可少的。尤其是在多用户的平台(比如公有或私有的 PaaS)上,控制组十分重要。例如,当某些应用程序表现异常的时候,可以保证一致地正常运行和性能。
|
||||
盡管控制組不負責隔離容器之間相互訪問、處理數據和進程,它在防止拒絕服務(DDOS)攻擊方面是必不可少的。尤其是在多用戶的平臺(比如公有或私有的 PaaS)上,控制組十分重要。例如,當某些應用程序表現異常的時候,可以保證一致地正常運行和性能。
|
||||
|
||||
控制组机制始于 2006 年,内核从 2.6.24 版本开始被引入。
|
||||
控制組機制始於 2006 年,內核從 2.6.24 版本開始被引入。
|
||||
|
@ -1,18 +1,18 @@
|
||||
## Docker服务端的防护
|
||||
运行一个容器或应用程序的核心是通过 Docker 服务端。Docker 服务的运行目前需要 root 权限,因此其安全性十分关键。
|
||||
## Docker服務端的防護
|
||||
運行一個容器或應用程序的核心是通過 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 用户,减轻容器和主机之间因权限提升而引起的安全问题;
|
||||
* 允许 Docker 服务端在非 root 权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程将只允许在限定范围内进行操作,例如仅仅负责虚拟网络设定或文件系统管理、配置操作等。
|
||||
終極目標是改進 2 個重要的安全特性:
|
||||
* 將容器的 root 用戶映射到本地主機上的非 root 用戶,減輕容器和主機之間因權限提升而引起的安全問題;
|
||||
* 允許 Docker 服務端在非 root 權限下運行,利用安全可靠的子進程來代理執行需要特權權限的操作。這些子進程將只允許在限定範圍內進行操作,例如僅僅負責虛擬網絡設定或文件系統管理、配置操作等。
|
||||
|
||||
最后,建议采用专用的服务器来运行 Docker 和相关的管理服务(例如管理服务比如 ssh 监控和进程监控、管理工具 nrpe、collectd 等)。其它的业务服务都放到容器中去运行。
|
||||
最後,建議采用專用的服務器來運行 Docker 和相關的管理服務(例如管理服務比如 ssh 監控和進程監控、管理工具 nrpe、collectd 等)。其它的業務服務都放到容器中去運行。
|
||||
|
@ -1,26 +1,26 @@
|
||||
## 内核能力机制
|
||||
## 內核能力機制
|
||||
|
||||
能力机制(Capability)是 Linux 内核一个强大的特性,可以提供细粒度的权限访问控制。
|
||||
Linux 内核自 2.2 版本起就支持能力机制,它将权限划分为更加细粒度的操作能力,既可以作用在进程上,也可以作用在文件上。
|
||||
能力機制(Capability)是 Linux 內核一個強大的特性,可以提供細粒度的權限訪問控制。
|
||||
Linux 內核自 2.2 版本起就支持能力機制,它將權限劃分為更加細粒度的操作能力,既可以作用在進程上,也可以作用在文件上。
|
||||
|
||||
例如,一个 Web 服务进程只需要绑定一个低于 1024 的端口的权限,并不需要 root 权限。那么它只需要被授权 `net_bind_service` 能力即可。此外,还有很多其他的类似能力来避免进程获取 root 权限。
|
||||
例如,一個 Web 服務進程只需要綁定一個低於 1024 的端口的權限,並不需要 root 權限。那麽它只需要被授權 `net_bind_service` 能力即可。此外,還有很多其他的類似能力來避免進程獲取 root 權限。
|
||||
|
||||
默认情况下,Docker 启动的容器被严格限制只允许使用内核的一部分能力。
|
||||
默認情況下,Docker 啟動的容器被嚴格限制只允許使用內核的一部分能力。
|
||||
|
||||
使用能力机制对加强 Docker 容器的安全有很多好处。通常,在服务器上会运行一堆需要特权权限的进程,包括有 ssh、cron、syslogd、硬件管理工具模块(例如负载模块)、网络配置工具等等。容器跟这些进程是不同的,因为几乎所有的特权进程都由容器以外的支持系统来进行管理。
|
||||
* ssh 访问被主机上ssh服务来管理;
|
||||
* cron 通常应该作为用户进程执行,权限交给使用它服务的应用来处理;
|
||||
* 日志系统可由 Docker 或第三方服务管理;
|
||||
* 硬件管理无关紧要,容器中也就无需执行 udevd 以及类似服务;
|
||||
* 网络管理也都在主机上设置,除非特殊需求,容器不需要对网络进行配置。
|
||||
使用能力機制對加強 Docker 容器的安全有很多好處。通常,在服務器上會運行一堆需要特權權限的進程,包括有 ssh、cron、syslogd、硬件管理工具模塊(例如負載模塊)、網絡配置工具等等。容器跟這些進程是不同的,因為幾乎所有的特權進程都由容器以外的支持系統來進行管理。
|
||||
* ssh 訪問被主機上ssh服務來管理;
|
||||
* cron 通常應該作為用戶進程執行,權限交給使用它服務的應用來處理;
|
||||
* 日誌系統可由 Docker 或第三方服務管理;
|
||||
* 硬件管理無關緊要,容器中也就無需執行 udevd 以及類似服務;
|
||||
* 網絡管理也都在主機上設置,除非特殊需求,容器不需要對網絡進行配置。
|
||||
|
||||
从上面的例子可以看出,大部分情况下,容器并不需要“真正的” root 权限,容器只需要少数的能力即可。为了加强安全,容器可以禁用一些没必要的权限。
|
||||
從上面的例子可以看出,大部分情況下,容器並不需要“真正的” root 權限,容器只需要少數的能力即可。為了加強安全,容器可以禁用一些沒必要的權限。
|
||||
* 完全禁止任何 mount 操作;
|
||||
* 禁止直接访问本地主机的套接字;
|
||||
* 禁止访问一些文件系统的操作,比如创建新的设备、修改文件属性等;
|
||||
* 禁止模块加载。
|
||||
* 禁止直接訪問本地主機的套接字;
|
||||
* 禁止訪問一些文件系統的操作,比如創建新的設備、修改文件屬性等;
|
||||
* 禁止模塊加載。
|
||||
|
||||
这样,就算攻击者在容器中取得了 root 权限,也不能获得本地主机的较高权限,能进行的破坏也有限。
|
||||
這樣,就算攻擊者在容器中取得了 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采用 [白名單](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 容器啟用額外的權限。
|
||||
|
@ -1,15 +1,15 @@
|
||||
## 内核名字空间
|
||||
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。当用 `docker run` 启动一个容器时,在后台 Docker 为容器创建了一个独立的名字空间和控制组集合。
|
||||
## 內核名字空間
|
||||
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。當用 `docker run` 啟動一個容器時,在後臺 Docker 為容器創建了一個獨立的名字空間和控制組集合。
|
||||
|
||||
名字空间提供了最基础也是最直接的隔离,在容器中运行的进程不会被运行在主机上的进程和其它容器发现和作用。
|
||||
名字空間提供了最基礎也是最直接的隔離,在容器中運行的進程不會被運行在主機上的進程和其它容器發現和作用。
|
||||
|
||||
每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的 sockets 或接口。不过,如果主机系统上做了相应的设置,容器可以像跟主机交互一样的和其他容器交互。当指定公共端口或使用 links 来连接 2 个容器时,容器就可以相互通信了(可以根据配置来限制通信的策略)。
|
||||
每個容器都有自己獨有的網絡棧,意味著它們不能訪問其他容器的 sockets 或接口。不過,如果主機系統上做了相應的設置,容器可以像跟主機交互一樣的和其他容器交互。當指定公共端口或使用 links 來連接 2 個容器時,容器就可以相互通信了(可以根據配置來限制通信的策略)。
|
||||
|
||||
从网络架构的角度来看,所有的容器通过本地主机的网桥接口相互通信,就像物理机器通过物理交换机通信一样。
|
||||
從網絡架構的角度來看,所有的容器通過本地主機的網橋接口相互通信,就像物理機器通過物理交換機通信一樣。
|
||||
|
||||
那么,内核中实现名字空间和私有网络的代码是否足够成熟?
|
||||
那麽,內核中實現名字空間和私有網絡的代碼是否足夠成熟?
|
||||
|
||||
内核名字空间从 2.6.15 版本(2008 年 7 月发布)之后被引入,数年间,这些机制的可靠性在诸多大型生产系统中被实践验证。
|
||||
內核名字空間從 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 的安全性,例如 TOMOYO, AppArmor, SELinux, GRSEC 等。
|
||||
|
||||
Docker 当前默认只启用了能力机制。用户可以采用多种方案来加强 Docker 主机的安全,例如:
|
||||
* 在内核中启用 GRSEC 和 PAX,这将增加很多编译和运行时的安全检查;通过地址随机化避免恶意探测等。并且,启用该特性不需要 Docker 进行任何配置。
|
||||
* 使用一些有增强安全特性的容器模板,比如带 AppArmor 的模板和 Redhat 带 SELinux 策略的模板。这些模板提供了额外的安全特性。
|
||||
* 用户可以自定义访问控制机制来定制安全策略。
|
||||
Docker 當前默認只啟用了能力機制。用戶可以采用多種方案來加強 Docker 主機的安全,例如:
|
||||
* 在內核中啟用 GRSEC 和 PAX,這將增加很多編譯和運行時的安全檢查;通過地址隨機化避免惡意探測等。並且,啟用該特性不需要 Docker 進行任何配置。
|
||||
* 使用一些有增強安全特性的容器模板,比如帶 AppArmor 的模板和 Redhat 帶 SELinux 策略的模板。這些模板提供了額外的安全特性。
|
||||
* 用戶可以自定義訪問控制機制來定制安全策略。
|
||||
|
||||
跟其它添加到 Docker 容器的第三方工具一样(比如网络拓扑和文件系统共享),有很多类似的机制,在不改变 Docker 内核情况下就可以加固现有的容器。
|
||||
跟其它添加到 Docker 容器的第三方工具一樣(比如網絡拓撲和文件系統共享),有很多類似的機制,在不改變 Docker 內核情況下就可以加固現有的容器。
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 总结
|
||||
总体来看,Docker 容器还是十分安全的,特别是在容器内不使用 root 权限来运行进程的话。
|
||||
## 總結
|
||||
總體來看,Docker 容器還是十分安全的,特別是在容器內不使用 root 權限來運行進程的話。
|
||||
|
||||
另外,用户可以使用现有工具,比如 Apparmor, SELinux, GRSEC 来增强安全性;甚至自己在内核中实现更复杂的安全机制。
|
||||
另外,用戶可以使用現有工具,比如 Apparmor, SELinux, GRSEC 來增強安全性;甚至自己在內核中實現更復雜的安全機制。
|
||||
|
@ -1,13 +1,13 @@
|
||||
# 底层实现
|
||||
# 底層實現
|
||||
|
||||
Docker 底层的核心技术包括 Linux 上的名字空间(Namespaces)、控制组(Control groups)、Union 文件系统(Union file systems)和容器格式(Container format)。
|
||||
Docker 底層的核心技術包括 Linux 上的名字空間(Namespaces)、控制組(Control groups)、Union 文件系統(Union file systems)和容器格式(Container format)。
|
||||
|
||||
我们知道,传统的虚拟机通过在宿主主机中运行 hypervisor 来模拟一整套完整的硬件环境提供给虚拟机的操作系统。虚拟机系统看到的环境是可限制的,也是彼此隔离的。
|
||||
这种直接的做法实现了对资源最完整的封装,但很多时候往往意味着系统资源的浪费。
|
||||
例如,以宿主机和虚拟机系统都为 Linux 系统为例,虚拟机中运行的应用其实可以利用宿主机系统中的运行环境。
|
||||
我們知道,傳統的虛擬機通過在宿主主機中運行 hypervisor 來模擬一整套完整的硬件環境提供給虛擬機的作業系統。虛擬機系統看到的環境是可限制的,也是彼此隔離的。
|
||||
這種直接的做法實現了對資源最完整的封裝,但很多時候往往意味著系統資源的浪費。
|
||||
例如,以宿主機和虛擬機系統都為 Linux 系統為例,虛擬機中運行的應用其實可以利用宿主機系統中的運行環境。
|
||||
|
||||
我们知道,在操作系统中,包括内核、文件系统、网络、PID、UID、IPC、内存、硬盘、CPU 等等,所有的资源都是应用进程直接共享的。
|
||||
要想实现虚拟化,除了要实现对内存、CPU、网络IO、硬盘IO、存储空间等的限制外,还要实现文件系统、网络、PID、UID、IPC等等的相互隔离。
|
||||
前者相对容易实现一些,后者则需要宿主机系统的深入支持。
|
||||
我們知道,在作業系統中,包括內核、文件系統、網絡、PID、UID、IPC、內存、硬盤、CPU 等等,所有的資源都是應用進程直接共享的。
|
||||
要想實現虛擬化,除了要實現對內存、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 采用了 C/S架構,包括客戶端和服務端。
|
||||
Docker daemon 作為服務端接受來自客戶的請求,並處理這些請求(創建、運行、分發容器)。
|
||||
客戶端和服務端既可以運行在一個機器上,也可通過 socket 或者 RESTful API 來進行通信。
|
||||
|
||||
![Docker 基本架构](../_images/docker_arch.png)
|
||||
![Docker 基本架構](../_images/docker_arch.png)
|
||||
|
||||
|
||||
Docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。
|
||||
Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。
|
||||
Docker daemon 一般在宿主主機後臺運行,等待接收來自客戶端的消息。
|
||||
Docker 客戶端則為用戶提供一系列可執行命令,用戶用這些命令實現跟 Docker daemon 交互。
|
||||
|
@ -1,9 +1,9 @@
|
||||
## 控制组
|
||||
## 控制組
|
||||
|
||||
控制组([cgroups](http://en.wikipedia.org/wiki/Cgroups))是 Linux 内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,才能避免当多个容器同时运行时的对系统资源的竞争。
|
||||
控制組([cgroups](http://en.wikipedia.org/wiki/Cgroups))是 Linux 內核的一個特性,主要用來對共享資源進行隔離、限制、審計等。只有能控制分配到容器的資源,才能避免當多個容器同時運行時的對系統資源的競爭。
|
||||
|
||||
控制组技术最早是由 Google 的程序员 2006 年起提出,Linux 内核自 2.6.24 开始支持。
|
||||
控制組技術最早是由 Google 的程序員 2006 年起提出,Linux 內核自 2.6.24 開始支持。
|
||||
|
||||
控制组可以提供对容器的内存、CPU、磁盘 IO 等资源的限制和审计管理。
|
||||
控制組可以提供對容器的內存、CPU、磁盤 IO 等資源的限制和審計管理。
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
## 容器格式
|
||||
最初,Docker 采用了 LXC 中的容器格式。自 1.20 版本开始,Docker 也开始支持新的 [libcontainer](https://github.com/docker/libcontainer) 格式,并作为默认选项。
|
||||
最初,Docker 采用了 LXC 中的容器格式。自 1.20 版本開始,Docker 也開始支持新的 [libcontainer](https://github.com/docker/libcontainer) 格式,並作為默認選項。
|
||||
|
||||
对更多容器格式的支持,还在进一步的发展中。
|
||||
對更多容器格式的支持,還在進一步的發展中。
|
||||
|
@ -1,22 +1,22 @@
|
||||
## 名字空间
|
||||
名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
|
||||
## 名字空間
|
||||
名字空間是 Linux 內核一個強大的特性。每個容器都有自己單獨的名字空間,運行在其中的應用都像是在獨立的作業系統中運行一樣。名字空間保證了容器之間彼此互不影響。
|
||||
|
||||
### pid 名字空间
|
||||
不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。
|
||||
### pid 名字空間
|
||||
不同用戶的進程就是通過 pid 名字空間隔離開的,且不同名字空間中可以有相同 pid。所有的 LXC 進程在 Docker 中的父進程為Docker進程,每個 LXC 進程具有不同的名字空間。同時由於允許嵌套,因此可以很方便的實現嵌套的 Docker 容器。
|
||||
|
||||
### net 名字空间
|
||||
有了 pid 名字空间, 每个名字空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 名字空间实现的, 每个 net 名字空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker 网桥 docker0 连接在一起。
|
||||
### net 名字空間
|
||||
有了 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。
|
||||
### ipc 名字空間
|
||||
容器中進程交互還是采用了 Linux 常見的進程間交互方法(interprocess communication - IPC), 包括信號量、消息隊列和共享內存等。然而同 VM 不同的是,容器的進程間交互實際上還是 host 上具有相同 pid 名字空間中的進程間交互,因此需要在 IPC 資源申請時加入名字空間信息,每個 IPC 資源有一個唯一的 32 位 id。
|
||||
|
||||
### mnt 名字空间
|
||||
类似 chroot,将一个进程放到一个特定的目录执行。mnt 名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名字空间中的容器在 /proc/mounts 的信息只包含所在名字空间的 mount point。
|
||||
### mnt 名字空間
|
||||
類似 chroot,將一個進程放到一個特定的目錄執行。mnt 名字空間允許不同名字空間的進程看到的文件結構不同,這樣每個名字空間 中的進程所看到的文件目錄就被隔離開了。同 chroot 不同,每個名字空間中的容器在 /proc/mounts 的信息只包含所在名字空間的 mount point。
|
||||
|
||||
### uts 名字空间
|
||||
UTS("UNIX Time-sharing System") 名字空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 主机上的一个进程。
|
||||
### uts 名字空間
|
||||
UTS("UNIX Time-sharing System") 名字空間允許每個容器擁有獨立的 hostname 和 domain name, 使其在網絡上可以被視作一個獨立的節點而非 主機上的一個進程。
|
||||
|
||||
### user 名字空间
|
||||
每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。
|
||||
### user 名字空間
|
||||
每個容器可以有不同的用戶和組 id, 也就是說可以在容器內用容器內部的用戶執行程序而非主機上的用戶。
|
||||
|
||||
*注:关于 Linux 上的名字空间,[这篇文章](http://blog.scottlowe.org/2013/09/04/introducing-linux-network-namespaces/) 介绍的很好。
|
||||
*註:關於 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 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。
|
||||
Docker 中的網絡接口默認都是虛擬的接口。虛擬接口的優勢之一是轉發效率較高。
|
||||
Linux 通過在內核中進行數據復制來實現虛擬接口之間的數據轉發,發送接口的發送緩存中的數據包被直接復制到接收接口的接收緩存中。對於本地系統和容器內系統看來就像是一個正常的以太網卡,只是它不需要真正同外部網絡設備通信,速度要快很多。
|
||||
|
||||
Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 `veth pair`)。
|
||||
Docker 容器網絡就利用了這項技術。它在本地主機和容器內分別創建一個虛擬接口,並讓它們彼此連通(這樣的一對接口叫做 `veth pair`)。
|
||||
|
||||
### 创建网络参数
|
||||
Docker 创建一个容器的时候,会执行如下操作:
|
||||
* 创建一对虚拟接口,分别放到本地主机和新容器中;
|
||||
* 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth65f9;
|
||||
* 容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的名字空间可见;
|
||||
* 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 veth65f9。
|
||||
### 創建網絡參數
|
||||
Docker 創建一個容器的時候,會執行如下操作:
|
||||
* 創建一對虛擬接口,分別放到本地主機和新容器中;
|
||||
* 本地主機一端橋接到默認的 docker0 或指定網橋上,並具有一個唯一的名字,如 veth65f9;
|
||||
* 容器一端放到新容器中,並修改名字作為 eth0,這個接口只在容器的名字空間可見;
|
||||
* 從網橋可用地址段中獲取一個空閑地址分配給容器的 eth0,並配置默認路由到橋接網卡 veth65f9。
|
||||
|
||||
完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。
|
||||
完成這些之後,容器就可以使用 eth0 虛擬網卡來連接其他容器和其他網絡。
|
||||
|
||||
可以在 `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 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
|
||||
可以在 `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=none` 后,可以自行配置网络,让容器达到跟平常一样具有访问网络的权限。通过这个过程,可以了解 Docker 配置网络的细节。
|
||||
### 網絡配置細節
|
||||
用戶使用 `--net=none` 後,可以自行配置網絡,讓容器達到跟平常一樣具有訪問網絡的權限。通過這個過程,可以了解 Docker 配置網絡的細節。
|
||||
|
||||
首先,启动一个 `/bin/bash` 容器,指定 `--net=none` 参数。
|
||||
首先,啟動一個 `/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
|
||||
@ -41,20 +41,20 @@ $ pid=2778
|
||||
$ sudo mkdir -p /var/run/netns
|
||||
$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
|
||||
```
|
||||
检查桥接网卡的 IP 和子网掩码信息。
|
||||
檢查橋接網卡的 IP 和子網掩碼信息。
|
||||
```
|
||||
$ ip addr show docker0
|
||||
21: 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
|
||||
$ sudo ip link set A up
|
||||
```
|
||||
将B放到容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP(桥接网段)和默认网关。
|
||||
將B放到容器的網絡命名空間,命名為 eth0,啟動它並配置一個可用 IP(橋接網段)和默認網關。
|
||||
```
|
||||
$ sudo ip link set B netns $pid
|
||||
$ sudo ip netns exec $pid ip link set dev B name eth0
|
||||
@ -62,8 +62,8 @@ $ sudo ip netns exec $pid ip link set eth0 up
|
||||
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0
|
||||
$ sudo ip netns exec $pid ip route add default via 172.17.42.1
|
||||
```
|
||||
以上,就是 Docker 配置网络的具体过程。
|
||||
以上,就是 Docker 配置網絡的具體過程。
|
||||
|
||||
当容器结束后,Docker 会清空容器,容器内的 eth0 会随网络命名空间一起被清除,A 接口也被自动从 `docker0` 卸载。
|
||||
當容器結束後,Docker 會清空容器,容器內的 eth0 會隨網絡命名空間一起被清除,A 接口也被自動從 `docker0` 卸載。
|
||||
|
||||
此外,用户可以使用 `ip netns exec` 命令来在指定网络名字空间中进行配置,从而配置容器内的网络。
|
||||
此外,用戶可以使用 `ip netns exec` 命令來在指定網絡名字空間中進行配置,從而配置容器內的網絡。
|
||||
|
@ -1,10 +1,10 @@
|
||||
## Union 文件系统
|
||||
Union文件系统([UnionFS](http://en.wikipedia.org/wiki/UnionFS))是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。
|
||||
## Union 文件系統
|
||||
Union文件系統([UnionFS](http://en.wikipedia.org/wiki/UnionFS))是一種分層、輕量級並且高性能的文件系統,它支持對文件系統的修改作為一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。
|
||||
|
||||
Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
|
||||
Union 文件系統是 Docker 鏡像的基礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以制作各種具體的應用鏡像。
|
||||
|
||||
另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。
|
||||
另外,不同 Docker 容器就可以共享一些基礎的文件系統層,同時再加上自己獨有的改動層,大大提高了存儲的效率。
|
||||
|
||||
Docker 中使用的 AUFS(AnotherUnionFS)就是一种 Union FS。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。
|
||||
Docker 中使用的 AUFS(AnotherUnionFS)就是一種 Union FS。 AUFS 支持為每一個成員目錄(類似 Git 的分支)設定只讀(readonly)、讀寫(readwrite)和寫出(whiteout-able)權限, 同時 AUFS 裏有一個類似分層的概念, 對只讀權限的分支可以邏輯上進行增量地修改(不影響只讀部分的)。
|
||||
|
||||
Docker 目前支持的 Union 文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper。
|
||||
Docker 目前支持的 Union 文件系統種類包括 AUFS, btrfs, vfs 和 DeviceMapper。
|
||||
|
Loading…
Reference in New Issue
Block a user